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

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

  ViewVC Help
Powered by ViewVC 1.1.26