/[gxemul]/trunk/src/devices/dev_vga.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/src/devices/dev_vga.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 14 - (show annotations)
Mon Oct 8 16:18:51 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 32510 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.982 2005/10/07 22:45:32 debug Exp $
20050816	Some success in decoding the way the SGI O2 PROM draws graphics
		during bootup; lines/rectangles and bitmaps work, enough to
		show the bootlogo etc. :-)
		Adding more PPC instructions, and (dummy) BAT registers.
20050817	Updating the pckbc to support scancode type 3 keyboards
		(required in order to interact with the SGI O2 PROM).
		Adding more PPC instructions.
20050818	Adding more ARM instructions; general register forms.
		Importing armreg.h from NetBSD (ARM cpu ids). Adding a (dummy)
		CATS machine mode (using SA110 as the default CPU).
		Continuing on general dyntrans related stuff.
20050819	Register forms for ARM load/stores. Gaah! The Compaq C Compiler
		bug is triggered for ARM loads as well, not just PPC :-(
		Adding full support for ARM PC-relative load/stores, and load/
		stores where the PC register is the destination register.
		Adding support for ARM a.out binaries.
20050820	Continuing to add more ARM instructions, and correcting some
		bugs. Continuing on CATS emulation.
		More work on the PPC stuff.
20050821	Minor PPC and ARM updates. Adding more machine types.
20050822	All ARM "data processing instructions" are now generated
		automatically.
20050824	Beginning the work on the ARM system control coprocessor.
		Adding support for ARM halfword load/stores, and signed loads.
20050825	Fixing an important bug related to the ARM condition codes.
		OpenBSD/zaurus and NetBSD/netwinder now print some boot
		messages. :)
		Adding a dummy SH (Hitachi SuperH) cpu family.
		Beginning to add some ARM virtual address translation.
		MIPS bugfixes: unaligned PC now cause an ADEL exception (at
		least for non-bintrans execution), and ADEL/ADES (not
		TLBL/TLBS) are used if userland tries to access kernel space.
		(Thanks to Joshua Wise for making me aware of these bugs.)
20050827	More work on the ARM emulation, and various other updates.
20050828	More ARM updates.
		Finally taking the time to work on translation invalidation
		(i.e. invalidating translated code mappings when memory is
		written to). Hopefully this doesn't break anything.
20050829	Moving CPU related files from src/ to a new subdir, src/cpus/.
		Moving PROM emulation stuff from src/ to src/promemul/.
		Better debug instruction trace for ARM loads and stores.
20050830	Various ARM updates (correcting CMP flag calculation, etc).
20050831	PPC instruction updates. (Flag fixes, etc.)
20050901	Various minor PPC and ARM instruction emulation updates.
		Minor OpenFirmware emulation updates.
20050903	Adding support for adding arbitrary ARM coprocessors (with
		the i80321 I/O coprocessor as a first test).
		Various other ARM and PPC updates.
20050904	Adding some SHcompact disassembly routines.
20050907	(Re)adding a dummy HPPA CPU module, and a dummy i960 module.
20050908	Began hacking on some Apple Partition Table support.
20050909	Adding support for loading Mach-O (Darwin PPC) binaries.
20050910	Fixing an ARM bug (Carry flag was incorrectly updated for some
		data processing instructions); OpenBSD/cats and NetBSD/
		netwinder get quite a bit further now.
		Applying a patch to dev_wdc, and a one-liner to dev_pcic, to
		make them work better when emulating new versions of OpenBSD.
		(Thanks to Alexander Yurchenko for the patches.)
		Also doing some other minor updates to dev_wdc. (Some cleanup,
		and finally converting to devinit, etc.)
20050912	IRIX doesn't have u_int64_t by default (noticed by Andreas
		<avr@gnulinux.nl>); configure updated to reflect this.
		Working on ARM register bank switching, CPSR vs SPSR issues,
		and beginning the work on interrupt/exception support.
20050913	Various minor ARM updates (speeding up load/store multiple,
		and fixing a ROR bug in R(); NetBSD/cats now boots as far as
		OpenBSD/cats).
20050917	Adding a dummy Atmel AVR (8-bit) cpu family skeleton.
20050918	Various minor updates.
20050919	Symbols are now loaded from Mach-O executables.
		Continuing the work on adding ARM exception support.
20050920	More work on ARM stuff: OpenBSD/cats and NetBSD/cats reach
		userland! :-)
20050921	Some more progress on ARM interrupt specifics.
20050923	Fixing linesize for VR4121 (patch by Yurchenko). Also fixing
		linesizes/cachesizes for some other VR4xxx.
		Adding a dummy Acer Labs M1543 PCI-ISA bridge (for CATS) and a
		dummy Symphony Labs 83C553 bridge (for Netwinder), usable by 
		dev_footbridge.
20050924	Some PPC progress.
20050925	More PPC progress.
20050926	PPC progress (fixing some bugs etc); Darwin's kernel gets
		slightly further than before.
20050928	Various updates: footbridge/ISA/pciide stuff, and finally
		fixing the VGA text scroll-by-changing-the-base-offset bug.
20050930	Adding a dummy S3 ViRGE pci card for CATS emulation, which
		both NetBSD and OpenBSD detects as VGA.
		Continuing on Footbridge (timers, ISA interrupt stuff).
20051001	Continuing... there are still bugs, probably interrupt-
		related.
20051002	More work on the Footbridge (interrupt stuff).
20051003	Various minor updates. (Trying to find the bug(s).)
20051004	Continuing on the ARM stuff.
20051005	More ARM-related fixes.
20051007	FINALLY! Found and fixed 2 ARM bugs: 1 memory related, and the
		other was because of an error in the ARM manual (load multiple
		with the S-bit set should _NOT_ load usermode registers, as the
		manual says, but it should load saved registers, which may or
		may not happen to be usermode registers).
		NetBSD/cats and OpenBSD/cats seem to install fine now :-)
		except for a minor bug at the end of the OpenBSD/cats install.
		Updating the documentation, preparing for the next release.
20051008	Continuing with release testing and cleanup.

1 /*
2 * Copyright (C) 2004-2005 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_vga.c,v 1.81 2005/10/07 22:10:52 debug Exp $
29 *
30 * VGA charcell and graphics device.
31 *
32 * It should work with 80x25 and 40x25 text modes, and with a few graphics
33 * modes as long as no fancy VGA features are used.
34 */
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 #include "console.h"
41 #include "cpu.h"
42 #include "devices.h"
43 #include "machine.h"
44 #include "memory.h"
45 #include "misc.h"
46
47 #include "vga.h"
48
49 /* These are generated from binary font files: */
50 #include "fonts/font8x8.c"
51 #include "fonts/font8x10.c"
52 #include "fonts/font8x16.c"
53
54
55 /* For bintranslated videomem -> framebuffer updates: */
56 #define VGA_TICK_SHIFT 16
57
58 #define MAX_RETRACE_SCANLINES 420
59 #define N_IS1_READ_THRESHOLD 50
60
61 #define GFX_ADDR_WINDOW 0x18000
62
63 #define VGA_FB_ADDR 0x1c00000000ULL
64
65 #define MODE_CHARCELL 1
66 #define MODE_GRAPHICS 2
67
68 #define GRAPHICS_MODE_8BIT 1
69 #define GRAPHICS_MODE_4BIT 2
70
71 struct vga_data {
72 uint64_t videomem_base;
73 uint64_t control_base;
74
75 struct vfb_data *fb;
76 size_t fb_size;
77
78 int fb_max_x; /* pixels */
79 int fb_max_y; /* pixels */
80 int max_x; /* charcells or pixels */
81 int max_y; /* charcells or pixels */
82
83 /* Selects charcell mode or graphics mode: */
84 int cur_mode;
85
86 /* Common for text and graphics modes: */
87 int pixel_repx, pixel_repy;
88
89 /* Textmode: */
90 int font_width;
91 int font_height;
92 unsigned char *font;
93 size_t charcells_size;
94 unsigned char *charcells; /* 2 bytes per char */
95 unsigned char *charcells_outputed;
96
97 /* Graphics: */
98 int graphics_mode;
99 int bits_per_pixel;
100 unsigned char *gfx_mem;
101 size_t gfx_mem_size;
102
103 /* Registers: */
104 int attribute_state; /* 0 or 1 */
105 unsigned char attribute_reg_select;
106 unsigned char attribute_reg[256];
107
108 unsigned char misc_output_reg;
109
110 unsigned char sequencer_reg_select;
111 unsigned char sequencer_reg[256];
112
113 unsigned char graphcontr_reg_select;
114 unsigned char graphcontr_reg[256];
115
116 unsigned char crtc_reg_select;
117 unsigned char crtc_reg[256];
118
119 unsigned char palette_read_index;
120 char palette_read_subindex;
121 unsigned char palette_write_index;
122 char palette_write_subindex;
123
124 int current_retrace_line;
125 int input_status_1;
126
127 /* Palette per scanline during retrace: */
128 unsigned char *retrace_palette;
129 int use_palette_per_line;
130 int64_t n_is1_reads;
131
132 /* Misc.: */
133 int console_handle;
134
135 int cursor_x;
136 int cursor_y;
137
138 int modified;
139 int update_x1;
140 int update_y1;
141 int update_x2;
142 int update_y2;
143 };
144
145
146 /*
147 * register_reset():
148 *
149 * Resets many registers to sane values.
150 */
151 static void register_reset(struct vga_data *d)
152 {
153 /* Home cursor: */
154 d->cursor_x = d->cursor_y = 0;
155 d->crtc_reg[VGA_CRTC_CURSOR_LOCATION_HIGH] =
156 d->crtc_reg[VGA_CRTC_CURSOR_LOCATION_LOW] = 0;
157
158 d->crtc_reg[VGA_CRTC_START_ADDR_HIGH] =
159 d->crtc_reg[VGA_CRTC_START_ADDR_LOW] = 0;
160
161 /* Reset cursor scanline stuff: */
162 d->crtc_reg[VGA_CRTC_CURSOR_SCANLINE_START] = d->font_height - 4;
163 d->crtc_reg[VGA_CRTC_CURSOR_SCANLINE_END] = d->font_height - 2;
164
165 d->sequencer_reg[VGA_SEQ_MAP_MASK] = 0x0f;
166 d->graphcontr_reg[VGA_GRAPHCONTR_MASK] = 0xff;
167
168 d->misc_output_reg = VGA_MISC_OUTPUT_IOAS;
169 d->n_is1_reads = 0;
170 }
171
172
173 static void c_putstr(struct vga_data *d, char *s)
174 {
175 while (*s)
176 console_putchar(d->console_handle, *s++);
177 }
178
179
180 /*
181 * reset_palette():
182 */
183 static void reset_palette(struct vga_data *d, int grayscale)
184 {
185 int i, r, g, b;
186
187 /* TODO: default values for entry 16..255? */
188 for (i=16; i<256; i++)
189 d->fb->rgb_palette[i*3 + 0] = d->fb->rgb_palette[i*3 + 1] =
190 d->fb->rgb_palette[i*3 + 2] = (i & 15) * 4;
191
192 i = 0;
193
194 if (grayscale) {
195 for (r=0; r<2; r++)
196 for (g=0; g<2; g++)
197 for (b=0; b<2; b++) {
198 d->fb->rgb_palette[i + 0] =
199 d->fb->rgb_palette[i + 1] =
200 d->fb->rgb_palette[i + 2] =
201 (r+g+b) * 0xaa / 3;
202 d->fb->rgb_palette[i + 8*3 + 0] =
203 d->fb->rgb_palette[i + 8*3 + 1] =
204 d->fb->rgb_palette[i + 8*3 + 2] =
205 (r+g+b) * 0xaa / 3 + 0x55;
206 i+=3;
207 }
208 return;
209 }
210
211 for (r=0; r<2; r++)
212 for (g=0; g<2; g++)
213 for (b=0; b<2; b++) {
214 d->fb->rgb_palette[i + 0] = r * 0xaa;
215 d->fb->rgb_palette[i + 1] = g * 0xaa;
216 d->fb->rgb_palette[i + 2] = b * 0xaa;
217 i+=3;
218 }
219 for (r=0; r<2; r++)
220 for (g=0; g<2; g++)
221 for (b=0; b<2; b++) {
222 d->fb->rgb_palette[i + 0] = r * 0xaa + 0x55;
223 d->fb->rgb_palette[i + 1] = g * 0xaa + 0x55;
224 d->fb->rgb_palette[i + 2] = b * 0xaa + 0x55;
225 i+=3;
226 }
227 }
228
229
230 /*
231 * vga_update_textmode():
232 *
233 * Called from vga_update() when use_x11 is false. This causes modified
234 * character cells to be "simulated" by outputing ANSI escape sequences
235 * that draw the characters in a terminal window instead.
236 */
237 static void vga_update_textmode(struct machine *machine,
238 struct vga_data *d, int base, int start, int end)
239 {
240 char s[50];
241 int i, oldcolor = -1, printed_last = 0;
242
243 for (i=start; i<=end; i+=2) {
244 unsigned char ch = d->charcells[base+i];
245 int fg = d->charcells[base+i+1] & 15;
246 int bg = (d->charcells[base+i+1] >> 4) & 15;
247 /* top bit of bg = blink */
248 int x = (i/2) % d->max_x;
249 int y = (i/2) / d->max_x;
250
251 if (d->charcells[base+i] == d->charcells_outputed[i] &&
252 d->charcells[base+i+1] == d->charcells_outputed[i+1]) {
253 printed_last = 0;
254 continue;
255 }
256
257 d->charcells_outputed[i] = d->charcells[base+i];
258 d->charcells_outputed[i+1] = d->charcells[base+i+1];
259
260 if (!printed_last || x == 0) {
261 snprintf(s, sizeof(s), "\033[%i;%iH", y + 1, x + 1);
262 c_putstr(d, s);
263 }
264 if (oldcolor < 0 || (bg<<4)+fg != oldcolor || !printed_last) {
265 snprintf(s, sizeof(s), "\033[0;"); c_putstr(d, s);
266
267 switch (fg & 7) {
268 case 0: c_putstr(d, "30"); break;
269 case 1: c_putstr(d, "34"); break;
270 case 2: c_putstr(d, "32"); break;
271 case 3: c_putstr(d, "36"); break;
272 case 4: c_putstr(d, "31"); break;
273 case 5: c_putstr(d, "35"); break;
274 case 6: c_putstr(d, "33"); break;
275 case 7: c_putstr(d, "37"); break;
276 }
277 if (fg & 8)
278 c_putstr(d, ";1");
279 c_putstr(d, ";");
280 switch (bg & 7) {
281 case 0: c_putstr(d, "40"); break;
282 case 1: c_putstr(d, "44"); break;
283 case 2: c_putstr(d, "42"); break;
284 case 3: c_putstr(d, "46"); break;
285 case 4: c_putstr(d, "41"); break;
286 case 5: c_putstr(d, "45"); break;
287 case 6: c_putstr(d, "43"); break;
288 case 7: c_putstr(d, "47"); break;
289 }
290 /* TODO: blink */
291 c_putstr(d, "m");
292 }
293
294 if (ch >= 0x20 && ch != 127)
295 console_putchar(d->console_handle, ch);
296
297 oldcolor = (bg << 4) + fg;
298 printed_last = 1;
299 }
300
301 /* Restore the terminal's cursor position: */
302 snprintf(s, sizeof(s), "\033[%i;%iH", d->cursor_y + 1, d->cursor_x + 1);
303 c_putstr(d, s);
304 }
305
306
307 /*
308 * vga_update_graphics():
309 *
310 * This function should be called whenever any part of d->gfx_mem[] has
311 * been written to. It will redraw all pixels within the range x1,y1
312 * .. x2,y2 using the right palette.
313 */
314 static void vga_update_graphics(struct machine *machine, struct vga_data *d,
315 int x1, int y1, int x2, int y2)
316 {
317 int x, y, ix, iy, c, rx = d->pixel_repx, ry = d->pixel_repy;
318 unsigned char pixel[3];
319
320 for (y=y1; y<=y2; y++)
321 for (x=x1; x<=x2; x++) {
322 /* addr is where to read from VGA memory, addr2 is
323 where to write on the 24-bit framebuffer device */
324 int addr = (y * d->max_x + x) * d->bits_per_pixel;
325 switch (d->bits_per_pixel) {
326 case 8: addr >>= 3;
327 c = d->gfx_mem[addr];
328 pixel[0] = d->fb->rgb_palette[c*3+0];
329 pixel[1] = d->fb->rgb_palette[c*3+1];
330 pixel[2] = d->fb->rgb_palette[c*3+2];
331 break;
332 case 4: addr >>= 2;
333 if (addr & 1)
334 c = d->gfx_mem[addr >> 1] >> 4;
335 else
336 c = d->gfx_mem[addr >> 1] & 0xf;
337 pixel[0] = d->fb->rgb_palette[c*3+0];
338 pixel[1] = d->fb->rgb_palette[c*3+1];
339 pixel[2] = d->fb->rgb_palette[c*3+2];
340 break;
341 }
342 for (iy=y*ry; iy<(y+1)*ry; iy++)
343 for (ix=x*rx; ix<(x+1)*rx; ix++) {
344 int addr2 = (d->fb_max_x * iy + ix) * 3;
345 if (addr2 < d->fb_size)
346 dev_fb_access(machine->cpus[0],
347 machine->memory, addr2,
348 pixel, sizeof(pixel),
349 MEM_WRITE, d->fb);
350 }
351 }
352 }
353
354
355 /*
356 * vga_update_text():
357 *
358 * This function should be called whenever any part of d->charcells[] has
359 * been written to. It will redraw all characters within the range x1,y1
360 * .. x2,y2 using the right palette.
361 */
362 static void vga_update_text(struct machine *machine, struct vga_data *d,
363 int x1, int y1, int x2, int y2)
364 {
365 int fg, bg, i, x,y, subx, line, start, end, base;
366 int font_size = d->font_height;
367 int font_width = d->font_width;
368 unsigned char *pal = d->fb->rgb_palette;
369
370 /* Hm... I'm still using the old start..end code: */
371 start = (d->max_x * y1 + x1) * 2;
372 end = (d->max_x * y2 + x2) * 2;
373
374 start &= ~1;
375 end |= 1;
376
377 if (end >= d->charcells_size)
378 end = d->charcells_size - 1;
379
380 base = ((d->crtc_reg[VGA_CRTC_START_ADDR_HIGH] << 8)
381 + d->crtc_reg[VGA_CRTC_START_ADDR_LOW]) * 2;
382
383 if (!machine->use_x11)
384 vga_update_textmode(machine, d, base, start, end);
385
386 for (i=start; i<=end; i+=2) {
387 unsigned char ch = d->charcells[i + base];
388 fg = d->charcells[i+base + 1] & 15;
389 bg = (d->charcells[i+base + 1] >> 4) & 7;
390
391 /* Blink is hard to do :-), but inversion might be ok too: */
392 if (d->charcells[i+base + 1] & 128) {
393 int tmp = fg; fg = bg; bg = tmp;
394 }
395
396 x = (i/2) % d->max_x; x *= font_width;
397 y = (i/2) / d->max_x; y *= font_size;
398
399 /* Draw the character: */
400 for (line = 0; line < font_size; line++) {
401 for (subx = 0; subx < font_width; subx++) {
402 int ix, iy, color_index;
403
404 if (d->use_palette_per_line) {
405 int sline = d->pixel_repy * (line+y);
406 if (sline < MAX_RETRACE_SCANLINES)
407 pal = d->retrace_palette
408 + sline * 256*3;
409 else
410 pal = d->fb->rgb_palette;
411 }
412
413 if (d->font[ch * font_size + line] &
414 (128 >> subx))
415 color_index = fg;
416 else
417 color_index = bg;
418
419 for (iy=0; iy<d->pixel_repy; iy++)
420 for (ix=0; ix<d->pixel_repx; ix++) {
421 int addr = (d->fb_max_x* (d->pixel_repy
422 * (line+y) + iy) + (x+subx) *
423 d->pixel_repx + ix) * 3;
424
425 if (addr >= d->fb_size)
426 continue;
427 dev_fb_access(machine->cpus[0],
428 machine->memory, addr,
429 &pal[color_index * 3], 3,
430 MEM_WRITE, d->fb);
431 }
432 }
433 }
434 }
435 }
436
437
438 /*
439 * vga_update_cursor():
440 */
441 static void vga_update_cursor(struct machine *machine, struct vga_data *d)
442 {
443 int onoff = 1, height = d->crtc_reg[VGA_CRTC_CURSOR_SCANLINE_END]
444 - d->crtc_reg[VGA_CRTC_CURSOR_SCANLINE_START] + 1;
445
446 if (d->cur_mode != MODE_CHARCELL)
447 onoff = 0;
448
449 if (d->crtc_reg[VGA_CRTC_CURSOR_SCANLINE_START] >
450 d->crtc_reg[VGA_CRTC_CURSOR_SCANLINE_END]) {
451 onoff = 0;
452 height = 1;
453 }
454
455 if (d->crtc_reg[VGA_CRTC_CURSOR_SCANLINE_START] >= d->font_height)
456 onoff = 0;
457
458 dev_fb_setcursor(d->fb,
459 d->cursor_x * d->font_width * d->pixel_repx, (d->cursor_y *
460 d->font_height + d->crtc_reg[VGA_CRTC_CURSOR_SCANLINE_START]) *
461 d->pixel_repy, onoff, d->font_width * d->pixel_repx, height *
462 d->pixel_repy);
463 }
464
465
466 /*
467 * dev_vga_tick():
468 */
469 void dev_vga_tick(struct cpu *cpu, void *extra)
470 {
471 struct vga_data *d = extra;
472 int64_t low = -1, high;
473
474 vga_update_cursor(cpu->machine, d);
475
476 /* TODO: text vs graphics tick? */
477 memory_device_dyntrans_access(cpu, cpu->mem, extra,
478 (uint64_t *) &low, (uint64_t *) &high);
479
480 if (low != -1) {
481 int base = ((d->crtc_reg[VGA_CRTC_START_ADDR_HIGH] << 8)
482 + d->crtc_reg[VGA_CRTC_START_ADDR_LOW]) * 2;
483 int new_u_y1, new_u_y2;
484 debug("[ dev_vga_tick: bintrans access, %llx .. %llx ]\n",
485 (long long)low, (long long)high);
486 low -= base;
487 high -= base;
488 d->update_x1 = 0;
489 d->update_x2 = d->max_x - 1;
490 new_u_y1 = (low/2) / d->max_x;
491 new_u_y2 = ((high/2) / d->max_x) + 1;
492 if (new_u_y1 < d->update_y1)
493 d->update_y1 = new_u_y1;
494 if (new_u_y2 > d->update_y2)
495 d->update_y2 = new_u_y2;
496 if (d->update_y2 < 0)
497 d->update_y2 = 0;
498 if (d->update_y2 >= d->max_y)
499 d->update_y2 = d->max_y - 1;
500 d->modified = 1;
501 }
502
503 if (d->n_is1_reads > N_IS1_READ_THRESHOLD &&
504 d->retrace_palette != NULL) {
505 d->use_palette_per_line = 1;
506 d->update_x1 = 0;
507 d->update_x2 = d->max_x - 1;
508 d->update_y1 = 0;
509 d->update_y2 = d->max_y - 1;
510 d->modified = 1;
511 } else {
512 if (d->use_palette_per_line) {
513 d->use_palette_per_line = 0;
514 d->update_x1 = 0;
515 d->update_x2 = d->max_x - 1;
516 d->update_y1 = 0;
517 d->update_y2 = d->max_y - 1;
518 d->modified = 1;
519 }
520 }
521
522 if (!cpu->machine->use_x11) {
523 /* NOTE: 2 > 0, so this only updates the cursor, no
524 character cells. */
525 vga_update_textmode(cpu->machine, d, 0, 2, 0);
526 }
527
528 if (d->modified) {
529 if (d->cur_mode == MODE_CHARCELL)
530 vga_update_text(cpu->machine, d, d->update_x1,
531 d->update_y1, d->update_x2, d->update_y2);
532 else
533 vga_update_graphics(cpu->machine, d, d->update_x1,
534 d->update_y1, d->update_x2, d->update_y2);
535
536 d->modified = 0;
537 d->update_x1 = 999999;
538 d->update_x2 = -1;
539 d->update_y1 = 999999;
540 d->update_y2 = -1;
541 }
542
543 if (d->n_is1_reads > N_IS1_READ_THRESHOLD)
544 d->n_is1_reads = 0;
545 }
546
547
548 /*
549 * vga_graphics_access():
550 *
551 * Reads and writes to the VGA video memory (pixels).
552 */
553 int dev_vga_graphics_access(struct cpu *cpu, struct memory *mem,
554 uint64_t relative_addr, unsigned char *data, size_t len,
555 int writeflag, void *extra)
556 {
557 struct vga_data *d = extra;
558 int i,j, x=0, y=0, x2=0, y2=0, modified = 0;
559
560 if (relative_addr + len >= GFX_ADDR_WINDOW)
561 return 0;
562
563 if (d->cur_mode != MODE_GRAPHICS)
564 return 1;
565
566 switch (d->graphics_mode) {
567 case GRAPHICS_MODE_8BIT:
568 y = relative_addr / d->max_x;
569 x = relative_addr % d->max_x;
570 y2 = (relative_addr+len-1) / d->max_x;
571 x2 = (relative_addr+len-1) % d->max_x;
572
573 if (writeflag == MEM_WRITE) {
574 memcpy(d->gfx_mem + relative_addr, data, len);
575 modified = 1;
576 } else
577 memcpy(data, d->gfx_mem + relative_addr, len);
578 break;
579 case GRAPHICS_MODE_4BIT:
580 y = relative_addr * 8 / d->max_x;
581 x = relative_addr * 8 % d->max_x;
582 y2 = ((relative_addr+len)*8-1) / d->max_x;
583 x2 = ((relative_addr+len)*8-1) % d->max_x;
584 /* TODO: color stuff */
585
586 /* Read/write d->gfx_mem in 4-bit color: */
587 if (writeflag == MEM_WRITE) {
588 /* i is byte index to write, j is bit index */
589 for (i=0; i<len; i++)
590 for (j=0; j<8; j++) {
591 int pixelmask = 1 << (7-j);
592 int b = data[i] & pixelmask;
593 int m = d->sequencer_reg[
594 VGA_SEQ_MAP_MASK] & 0x0f;
595 int addr = (y * d->max_x + x + i*8 + j)
596 * d->bits_per_pixel / 8;
597 unsigned char byte;
598 if (!(d->graphcontr_reg[
599 VGA_GRAPHCONTR_MASK] & pixelmask))
600 continue;
601 if (addr >= d->gfx_mem_size)
602 continue;
603 byte = d->gfx_mem[addr];
604 if (b && j&1)
605 byte |= m << 4;
606 if (b && !(j&1))
607 byte |= m;
608 if (!b && j&1)
609 byte &= ~(m << 4);
610 if (!b && !(j&1))
611 byte &= ~m;
612 d->gfx_mem[addr] = byte;
613 }
614 modified = 1;
615 } else {
616 fatal("TODO: 4 bit graphics read, mask=0x%02x\n",
617 d->sequencer_reg[VGA_SEQ_MAP_MASK]);
618 for (i=0; i<len; i++)
619 data[i] = random();
620 }
621 break;
622 default:fatal("dev_vga: Unimplemented graphics mode %i\n",
623 d->graphics_mode);
624 cpu->running = 0;
625 }
626
627 if (modified) {
628 d->modified = 1;
629 if (x < d->update_x1) d->update_x1 = x;
630 if (x > d->update_x2) d->update_x2 = x;
631 if (y < d->update_y1) d->update_y1 = y;
632 if (y > d->update_y2) d->update_y2 = y;
633 if (x2 < d->update_x1) d->update_x1 = x2;
634 if (x2 > d->update_x2) d->update_x2 = x2;
635 if (y2 < d->update_y1) d->update_y1 = y2;
636 if (y2 > d->update_y2) d->update_y2 = y2;
637 if (y != y2) {
638 d->update_x1 = 0;
639 d->update_x2 = d->max_x - 1;
640 }
641 }
642 return 1;
643 }
644
645
646 /*
647 * dev_vga_access():
648 *
649 * Reads and writes to the VGA video memory (charcells).
650 */
651 int dev_vga_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr,
652 unsigned char *data, size_t len, int writeflag, void *extra)
653 {
654 struct vga_data *d = extra;
655 uint64_t idata = 0, odata = 0;
656 int i, x, y, x2, y2, r, base;
657
658 idata = memory_readmax64(cpu, data, len);
659
660 base = ((d->crtc_reg[VGA_CRTC_START_ADDR_HIGH] << 8)
661 + d->crtc_reg[VGA_CRTC_START_ADDR_LOW]) * 2;
662 r = relative_addr - base;
663 y = r / (d->max_x * 2);
664 x = (r/2) % d->max_x;
665 y2 = (r+len-1) / (d->max_x * 2);
666 x2 = ((r+len-1)/2) % d->max_x;
667
668 if (relative_addr < d->charcells_size) {
669 if (writeflag == MEM_WRITE) {
670 for (i=0; i<len; i++) {
671 int old = d->charcells[relative_addr + i];
672 if (old != data[i]) {
673 d->charcells[relative_addr + i] =
674 data[i];
675 d->modified = 1;
676 }
677 }
678
679 if (d->modified) {
680 if (x < d->update_x1) d->update_x1 = x;
681 if (x > d->update_x2) d->update_x2 = x;
682 if (y < d->update_y1) d->update_y1 = y;
683 if (y > d->update_y2) d->update_y2 = y;
684 if (x2 < d->update_x1) d->update_x1 = x2;
685 if (x2 > d->update_x2) d->update_x2 = x2;
686 if (y2 < d->update_y1) d->update_y1 = y2;
687 if (y2 > d->update_y2) d->update_y2 = y2;
688
689 if (y != y2) {
690 d->update_x1 = 0;
691 d->update_x2 = d->max_x - 1;
692 }
693 }
694 } else
695 memcpy(data, d->charcells + relative_addr, len);
696 return 1;
697 }
698
699 switch (relative_addr) {
700 default:
701 if (writeflag==MEM_READ) {
702 debug("[ vga: read from 0x%08lx ]\n",
703 (long)relative_addr);
704 } else {
705 debug("[ vga: write to 0x%08lx: 0x%08x ]\n",
706 (long)relative_addr, idata);
707 }
708 }
709
710 if (writeflag == MEM_READ)
711 memory_writemax64(cpu, data, len, odata);
712
713 return 1;
714 }
715
716
717 /*
718 * vga_crtc_reg_write():
719 *
720 * Writes to VGA CRTC registers.
721 */
722 static void vga_crtc_reg_write(struct machine *machine, struct vga_data *d,
723 int regnr, int idata)
724 {
725 int ofs, grayscale;
726
727 switch (regnr) {
728 case VGA_CRTC_CURSOR_SCANLINE_START: /* 0x0a */
729 case VGA_CRTC_CURSOR_SCANLINE_END: /* 0x0b */
730 break;
731 case VGA_CRTC_START_ADDR_HIGH: /* 0x0c */
732 case VGA_CRTC_START_ADDR_LOW: /* 0x0d */
733 d->update_x1 = 0;
734 d->update_x2 = d->max_x - 1;
735 d->update_y1 = 0;
736 d->update_y2 = d->max_y - 1;
737 d->modified = 1;
738 break;
739 case VGA_CRTC_CURSOR_LOCATION_HIGH: /* 0x0e */
740 case VGA_CRTC_CURSOR_LOCATION_LOW: /* 0x0f */
741 ofs = d->crtc_reg[VGA_CRTC_CURSOR_LOCATION_HIGH] * 256 +
742 d->crtc_reg[VGA_CRTC_CURSOR_LOCATION_LOW];
743 d->cursor_x = ofs % d->max_x;
744 d->cursor_y = ofs / d->max_x;
745 break;
746 case 0xff:
747 grayscale = 0;
748 switch (d->crtc_reg[0xff]) {
749 case 0x00:
750 grayscale = 1;
751 case 0x01:
752 d->cur_mode = MODE_CHARCELL;
753 d->max_x = 40; d->max_y = 25;
754 d->pixel_repx = 2; d->pixel_repy = 1;
755 d->font_width = 8;
756 d->font_height = 16;
757 d->font = font8x16;
758 break;
759 case 0x02:
760 grayscale = 1;
761 case 0x03:
762 d->cur_mode = MODE_CHARCELL;
763 d->max_x = 80; d->max_y = 25;
764 d->pixel_repx = d->pixel_repy = 1;
765 d->font_width = 8;
766 d->font_height = 16;
767 d->font = font8x16;
768 break;
769 case 0x08:
770 d->cur_mode = MODE_GRAPHICS;
771 d->max_x = 160; d->max_y = 200;
772 d->graphics_mode = GRAPHICS_MODE_4BIT;
773 d->bits_per_pixel = 4;
774 d->pixel_repx = 4;
775 d->pixel_repy = 2;
776 break;
777 case 0x09:
778 case 0x0d:
779 d->cur_mode = MODE_GRAPHICS;
780 d->max_x = 320; d->max_y = 200;
781 d->graphics_mode = GRAPHICS_MODE_4BIT;
782 d->bits_per_pixel = 4;
783 d->pixel_repx = d->pixel_repy = 2;
784 break;
785 case 0x0e:
786 d->cur_mode = MODE_GRAPHICS;
787 d->max_x = 640; d->max_y = 200;
788 d->graphics_mode = GRAPHICS_MODE_4BIT;
789 d->bits_per_pixel = 4;
790 d->pixel_repx = 1;
791 d->pixel_repy = 2;
792 break;
793 case 0x10:
794 d->cur_mode = MODE_GRAPHICS;
795 d->max_x = 640; d->max_y = 350;
796 d->graphics_mode = GRAPHICS_MODE_4BIT;
797 d->bits_per_pixel = 4;
798 d->pixel_repx = d->pixel_repy = 1;
799 break;
800 case 0x12:
801 d->cur_mode = MODE_GRAPHICS;
802 d->max_x = 640; d->max_y = 480;
803 d->graphics_mode = GRAPHICS_MODE_4BIT;
804 d->bits_per_pixel = 4;
805 d->pixel_repx = d->pixel_repy = 1;
806 break;
807 case 0x13:
808 d->cur_mode = MODE_GRAPHICS;
809 d->max_x = 320; d->max_y = 200;
810 d->graphics_mode = GRAPHICS_MODE_8BIT;
811 d->bits_per_pixel = 8;
812 d->pixel_repx = d->pixel_repy = 2;
813 break;
814 default:
815 fatal("TODO! video mode change hack (mode 0x%02x)\n",
816 d->crtc_reg[0xff]);
817 exit(1);
818 }
819
820 if (d->cur_mode == MODE_CHARCELL) {
821 dev_fb_resize(d->fb, d->max_x * d->font_width *
822 d->pixel_repx, d->max_y * d->font_height *
823 d->pixel_repy);
824 d->fb_size = d->max_x * d->pixel_repx * d->font_width *
825 d->max_y * d->pixel_repy * d->font_height * 3;
826 } else {
827 dev_fb_resize(d->fb, d->max_x * d->pixel_repx,
828 d->max_y * d->pixel_repy);
829 d->fb_size = d->max_x * d->pixel_repx *
830 d->max_y * d->pixel_repy * 3;
831 }
832
833 if (d->gfx_mem != NULL)
834 free(d->gfx_mem);
835 d->gfx_mem_size = 1;
836 if (d->cur_mode == MODE_GRAPHICS)
837 d->gfx_mem_size = d->max_x * d->max_y /
838 (d->graphics_mode == GRAPHICS_MODE_8BIT? 1 : 2);
839 d->gfx_mem = malloc(d->gfx_mem_size);
840
841 /* Clear screen and reset the palette: */
842 memset(d->charcells_outputed, 0, d->charcells_size);
843 memset(d->gfx_mem, 0, d->gfx_mem_size);
844 d->update_x1 = 0;
845 d->update_x2 = d->max_x - 1;
846 d->update_y1 = 0;
847 d->update_y2 = d->max_y - 1;
848 d->modified = 1;
849 reset_palette(d, grayscale);
850 register_reset(d);
851 break;
852 default:fatal("[ vga_crtc_reg_write: regnr=0x%02x idata=0x%02x ]\n",
853 regnr, idata);
854 }
855 }
856
857
858 /*
859 * vga_sequencer_reg_write():
860 *
861 * Writes to VGA Sequencer registers.
862 */
863 static void vga_sequencer_reg_write(struct machine *machine, struct vga_data *d,
864 int regnr, int idata)
865 {
866 switch (regnr) {
867 case VGA_SEQ_MAP_MASK: /* 0x02 */
868 break;
869 default:fatal("[ vga_sequencer_reg_write: select %i ]\n", regnr);
870 /* cpu->running = 0; */
871 }
872 }
873
874
875 /*
876 * vga_graphcontr_reg_write():
877 *
878 * Writes to VGA Graphics Controller registers.
879 */
880 static void vga_graphcontr_reg_write(struct machine *machine,
881 struct vga_data *d, int regnr, int idata)
882 {
883 switch (regnr) {
884 case VGA_GRAPHCONTR_MASK: /* 0x08 */
885 break;
886 default:fatal("[ vga_graphcontr_reg_write: select %i ]\n", regnr);
887 /* cpu->running = 0; */
888 }
889 }
890
891
892 /*
893 * vga_attribute_reg_write():
894 *
895 * Writes to VGA Attribute registers.
896 */
897 static void vga_attribute_reg_write(struct machine *machine, struct vga_data *d,
898 int regnr, int idata)
899 {
900 switch (regnr) {
901 default:fatal("[ vga_attribute_reg_write: select %i ]\n", regnr);
902 /* cpu->running = 0; */
903 }
904 }
905
906
907 /*
908 * dev_vga_ctrl_access():
909 *
910 * Reads and writes of the VGA control registers.
911 */
912 int dev_vga_ctrl_access(struct cpu *cpu, struct memory *mem,
913 uint64_t relative_addr, unsigned char *data, size_t len,
914 int writeflag, void *extra)
915 {
916 struct vga_data *d = extra;
917 int i;
918 uint64_t idata = 0, odata = 0;
919
920 for (i=0; i<len; i++) {
921 idata = data[i];
922
923 /* 0x3C0 + relative_addr... */
924
925 switch (relative_addr) {
926
927 case VGA_ATTRIBUTE_ADDR: /* 0x00 */
928 switch (d->attribute_state) {
929 case 0: if (writeflag == MEM_READ)
930 odata = d->attribute_reg_select;
931 else {
932 d->attribute_reg_select = 1;
933 d->attribute_state = 1;
934 }
935 break;
936 case 1: d->attribute_state = 0;
937 d->attribute_reg[d->attribute_reg_select] =
938 idata;
939 vga_attribute_reg_write(cpu->machine, d,
940 d->attribute_reg_select, idata);
941 break;
942 }
943 break;
944 case VGA_ATTRIBUTE_DATA_READ: /* 0x01 */
945 if (writeflag == MEM_WRITE)
946 fatal("[ dev_vga: WARNING: Write to "
947 "VGA_ATTRIBUTE_DATA_READ? ]\n");
948 else {
949 if (d->attribute_state == 0)
950 fatal("[ dev_vga: WARNING: Read from "
951 "VGA_ATTRIBUTE_DATA_READ, but no"
952 " register selected? ]\n");
953 else
954 odata = d->attribute_reg[
955 d->attribute_reg_select];
956 }
957 break;
958
959 case VGA_MISC_OUTPUT_W: /* 0x02 */
960 if (writeflag == MEM_WRITE)
961 d->misc_output_reg = idata;
962 else {
963 /* Reads: Input Status 0 */
964 odata = 0x00;
965 }
966 break;
967
968 case VGA_SEQUENCER_ADDR: /* 0x04 */
969 if (writeflag == MEM_READ)
970 odata = d->sequencer_reg_select;
971 else
972 d->sequencer_reg_select = idata;
973 break;
974 case VGA_SEQUENCER_DATA: /* 0x05 */
975 if (writeflag == MEM_READ)
976 odata = d->sequencer_reg[
977 d->sequencer_reg_select];
978 else {
979 d->sequencer_reg[d->
980 sequencer_reg_select] = idata;
981 vga_sequencer_reg_write(cpu->machine, d,
982 d->sequencer_reg_select, idata);
983 }
984 break;
985
986 case VGA_DAC_ADDR_READ: /* 0x07 */
987 if (writeflag == MEM_WRITE) {
988 d->palette_read_index = idata;
989 d->palette_read_subindex = 0;
990 } else {
991 fatal("[ dev_vga: WARNING: Read from "
992 "VGA_DAC_ADDR_READ? TODO ]\n");
993 /* TODO */
994 }
995 break;
996 case VGA_DAC_ADDR_WRITE: /* 0x08 */
997 if (writeflag == MEM_WRITE) {
998 d->palette_write_index = idata;
999 d->palette_write_subindex = 0;
1000
1001 /* TODO: Is this correct? */
1002 d->palette_read_index = idata;
1003 d->palette_read_subindex = 0;
1004 } else {
1005 fatal("[ dev_vga: WARNING: Read from "
1006 "VGA_DAC_ADDR_WRITE? ]\n");
1007 odata = d->palette_write_index;
1008 }
1009 break;
1010 case VGA_DAC_DATA: /* 0x09 */
1011 if (writeflag == MEM_WRITE) {
1012 int new = (idata & 63) << 2;
1013 int old = d->fb->rgb_palette[d->
1014 palette_write_index*3+d->
1015 palette_write_subindex];
1016 d->fb->rgb_palette[d->palette_write_index * 3 +
1017 d->palette_write_subindex] = new;
1018 /* Redraw whole screen, if the
1019 palette changed: */
1020 if (new != old) {
1021 d->modified = 1;
1022 d->update_x1 = d->update_y1 = 0;
1023 d->update_x2 = d->max_x - 1;
1024 d->update_y2 = d->max_y - 1;
1025 }
1026 d->palette_write_subindex ++;
1027 if (d->palette_write_subindex == 3) {
1028 d->palette_write_index ++;
1029 d->palette_write_subindex = 0;
1030 }
1031 } else {
1032 odata = (d->fb->rgb_palette[d->
1033 palette_read_index * 3 +
1034 d->palette_read_subindex] >> 2) & 63;
1035 d->palette_read_subindex ++;
1036 if (d->palette_read_subindex == 3) {
1037 d->palette_read_index ++;
1038 d->palette_read_subindex = 0;
1039 }
1040 }
1041 break;
1042
1043 case VGA_MISC_OUTPUT_R:
1044 odata = d->misc_output_reg;
1045 break;
1046
1047 case VGA_GRAPHCONTR_ADDR: /* 0x0e */
1048 if (writeflag == MEM_READ)
1049 odata = d->graphcontr_reg_select;
1050 else
1051 d->graphcontr_reg_select = idata;
1052 break;
1053 case VGA_GRAPHCONTR_DATA: /* 0x0f */
1054 if (writeflag == MEM_READ)
1055 odata = d->graphcontr_reg[
1056 d->graphcontr_reg_select];
1057 else {
1058 d->graphcontr_reg[d->
1059 graphcontr_reg_select] = idata;
1060 vga_graphcontr_reg_write(cpu->machine, d,
1061 d->graphcontr_reg_select, idata);
1062 }
1063 break;
1064
1065 case VGA_CRTC_ADDR: /* 0x14 */
1066 if (writeflag == MEM_READ)
1067 odata = d->crtc_reg_select;
1068 else
1069 d->crtc_reg_select = idata;
1070 break;
1071 case VGA_CRTC_DATA: /* 0x15 */
1072 if (writeflag == MEM_READ)
1073 odata = d->crtc_reg[d->crtc_reg_select];
1074 else {
1075 d->crtc_reg[d->crtc_reg_select] = idata;
1076 vga_crtc_reg_write(cpu->machine, d,
1077 d->crtc_reg_select, idata);
1078 }
1079 break;
1080
1081 case VGA_INPUT_STATUS_1: /* 0x1A */
1082 odata = 0;
1083 d->n_is1_reads ++;
1084 d->current_retrace_line ++;
1085 d->current_retrace_line %= (MAX_RETRACE_SCANLINES * 8);
1086 /* Whenever we are "inside" a scan line, copy the
1087 current palette into retrace_palette[][]: */
1088 if ((d->current_retrace_line & 7) == 7) {
1089 if (d->retrace_palette == NULL &&
1090 d->n_is1_reads > N_IS1_READ_THRESHOLD) {
1091 d->retrace_palette = malloc(
1092 MAX_RETRACE_SCANLINES * 256*3);
1093 if (d->retrace_palette == NULL) {
1094 fatal("out of memory\n");
1095 exit(1);
1096 }
1097 }
1098 if (d->retrace_palette != NULL)
1099 memcpy(d->retrace_palette + (d->
1100 current_retrace_line >> 3) * 256*3,
1101 d->fb->rgb_palette, d->cur_mode ==
1102 MODE_CHARCELL? (16*3) : (256*3));
1103 }
1104 /* These need to go on and off, to fake the
1105 real vertical and horizontal retrace info. */
1106 if (d->current_retrace_line < 20*8)
1107 odata |= VGA_IS1_DISPLAY_VRETRACE;
1108 else {
1109 if ((d->current_retrace_line & 7) == 0)
1110 odata = VGA_IS1_DISPLAY_DISPLAY_DISABLE;
1111 }
1112 break;
1113
1114 default:
1115 if (writeflag==MEM_READ) {
1116 fatal("[ vga_ctrl: read from 0x%08lx ]\n",
1117 (long)relative_addr);
1118 } else {
1119 fatal("[ vga_ctrl: write to 0x%08lx: 0x%08x"
1120 " ]\n", (long)relative_addr, (int)idata);
1121 }
1122 }
1123
1124 if (writeflag == MEM_READ)
1125 data[i] = odata;
1126
1127 /* For multi-byte accesses: */
1128 relative_addr ++;
1129 }
1130
1131 return 1;
1132 }
1133
1134
1135 /*
1136 * dev_vga_init():
1137 *
1138 * Register a VGA text console device. max_x and max_y could be something
1139 * like 80 and 25, respectively.
1140 */
1141 void dev_vga_init(struct machine *machine, struct memory *mem,
1142 uint64_t videomem_base, uint64_t control_base, char *name)
1143 {
1144 struct vga_data *d;
1145 int i, tmpi;
1146 size_t allocsize;
1147
1148 d = malloc(sizeof(struct vga_data));
1149 if (d == NULL) {
1150 fprintf(stderr, "out of memory\n");
1151 exit(1);
1152 }
1153 memset(d, 0, sizeof(struct vga_data));
1154
1155 d->console_handle = console_start_slave(machine, name);
1156
1157 d->videomem_base = videomem_base;
1158 d->control_base = control_base;
1159 d->max_x = 80;
1160 d->max_y = 25;
1161 d->pixel_repx = 1;
1162 d->pixel_repy = 1;
1163 d->cur_mode = MODE_CHARCELL;
1164 d->crtc_reg[0xff] = 0x03;
1165 d->charcells_size = 0x8000;
1166 d->gfx_mem_size = 1; /* Nothing, as we start in text mode */
1167
1168 /* Allocate in full pages, to make it possible to use bintrans: */
1169 allocsize = ((d->charcells_size-1) | (machine->arch_pagesize-1)) + 1;
1170 d->charcells = malloc(d->charcells_size);
1171 d->charcells_outputed = malloc(d->charcells_size);
1172 d->gfx_mem = malloc(d->gfx_mem_size);
1173 if (d->charcells == NULL || d->charcells_outputed == NULL ||
1174 d->gfx_mem == NULL) {
1175 fprintf(stderr, "out of memory in dev_vga_init()\n");
1176 exit(1);
1177 }
1178
1179 for (i=0; i<d->charcells_size; i+=2) {
1180 d->charcells[i] = ' ';
1181 d->charcells[i+1] = 0x07; /* Default color */
1182 }
1183
1184 memset(d->charcells_outputed, 0, d->charcells_size);
1185 memset(d->gfx_mem, 0, d->gfx_mem_size);
1186
1187 d->font = font8x16;
1188 d->font_width = 8;
1189 d->font_height = 16;
1190
1191 d->fb_max_x = d->pixel_repx * d->max_x;
1192 d->fb_max_y = d->pixel_repy * d->max_y;
1193 if (d->cur_mode == MODE_CHARCELL) {
1194 d->fb_max_x *= d->font_width;
1195 d->fb_max_y *= d->font_height;
1196 }
1197
1198 d->fb = dev_fb_init(machine, mem, VGA_FB_ADDR, VFB_GENERIC,
1199 d->fb_max_x, d->fb_max_y, d->fb_max_x, d->fb_max_y, 24, "VGA");
1200 d->fb_size = d->fb_max_x * d->fb_max_y * 3;
1201
1202 reset_palette(d, 0);
1203
1204 /* MEM_DYNTRANS_WRITE_OK <-- This works with OpenBSD/arc, but not
1205 with Windows NT yet. Why? */
1206 memory_device_register(mem, "vga_charcells", videomem_base + 0x18000,
1207 allocsize, dev_vga_access, d, MEM_DYNTRANS_OK |
1208 MEM_READING_HAS_NO_SIDE_EFFECTS, d->charcells);
1209 memory_device_register(mem, "vga_gfx", videomem_base, GFX_ADDR_WINDOW,
1210 dev_vga_graphics_access, d, MEM_DEFAULT |
1211 MEM_READING_HAS_NO_SIDE_EFFECTS, d->gfx_mem);
1212 memory_device_register(mem, "vga_ctrl", control_base,
1213 32, dev_vga_ctrl_access, d, MEM_DEFAULT, NULL);
1214
1215 /* This will force an initial redraw/resynch: */
1216 d->update_x1 = 0;
1217 d->update_x2 = d->max_x - 1;
1218 d->update_y1 = 0;
1219 d->update_y2 = d->max_y - 1;
1220 d->modified = 1;
1221
1222 machine_add_tickfunction(machine, dev_vga_tick, d, VGA_TICK_SHIFT);
1223
1224 vga_update_cursor(machine, d);
1225
1226 tmpi = d->cursor_y * d->max_x + d->cursor_x;
1227
1228 register_reset(d);
1229 }
1230

  ViewVC Help
Powered by ViewVC 1.1.26