/[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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.4  
changed lines
  Added in v.20

  ViewVC Help
Powered by ViewVC 1.1.26