25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: dev_vga.c,v 1.74 2005/05/29 16:04:28 debug Exp $ |
* $Id: dev_vga.c,v 1.81 2005/10/07 22:10:52 debug Exp $ |
29 |
* |
* |
30 |
* VGA charcell and graphics device. |
* VGA charcell and graphics device. |
31 |
* |
* |
58 |
#define MAX_RETRACE_SCANLINES 420 |
#define MAX_RETRACE_SCANLINES 420 |
59 |
#define N_IS1_READ_THRESHOLD 50 |
#define N_IS1_READ_THRESHOLD 50 |
60 |
|
|
|
#define VGA_MEM_MAXY 60 |
|
|
#define VGA_MEM_ALLOCY 60 |
|
61 |
#define GFX_ADDR_WINDOW 0x18000 |
#define GFX_ADDR_WINDOW 0x18000 |
62 |
|
|
63 |
#define VGA_FB_ADDR 0x1c00000000ULL |
#define VGA_FB_ADDR 0x1c00000000ULL |
258 |
d->charcells_outputed[i+1] = d->charcells[base+i+1]; |
d->charcells_outputed[i+1] = d->charcells[base+i+1]; |
259 |
|
|
260 |
if (!printed_last || x == 0) { |
if (!printed_last || x == 0) { |
261 |
sprintf(s, "\033[%i;%iH", y + 1, x + 1); |
snprintf(s, sizeof(s), "\033[%i;%iH", y + 1, x + 1); |
262 |
c_putstr(d, s); |
c_putstr(d, s); |
263 |
} |
} |
264 |
if (oldcolor < 0 || (bg<<4)+fg != oldcolor || !printed_last) { |
if (oldcolor < 0 || (bg<<4)+fg != oldcolor || !printed_last) { |
265 |
sprintf(s, "\033[0;"); c_putstr(d, s); |
snprintf(s, sizeof(s), "\033[0;"); c_putstr(d, s); |
266 |
|
|
267 |
switch (fg & 7) { |
switch (fg & 7) { |
268 |
case 0: c_putstr(d, "30"); break; |
case 0: c_putstr(d, "30"); break; |
299 |
} |
} |
300 |
|
|
301 |
/* Restore the terminal's cursor position: */ |
/* Restore the terminal's cursor position: */ |
302 |
sprintf(s, "\033[%i;%iH", d->cursor_y + 1, d->cursor_x + 1); |
snprintf(s, sizeof(s), "\033[%i;%iH", d->cursor_y + 1, d->cursor_x + 1); |
303 |
c_putstr(d, s); |
c_putstr(d, s); |
304 |
} |
} |
305 |
|
|
469 |
void dev_vga_tick(struct cpu *cpu, void *extra) |
void dev_vga_tick(struct cpu *cpu, void *extra) |
470 |
{ |
{ |
471 |
struct vga_data *d = extra; |
struct vga_data *d = extra; |
472 |
uint64_t low = (uint64_t)-1, high; |
int64_t low = -1, high; |
473 |
|
|
474 |
vga_update_cursor(cpu->machine, d); |
vga_update_cursor(cpu->machine, d); |
475 |
|
|
476 |
/* TODO: text vs graphics tick? */ |
/* TODO: text vs graphics tick? */ |
477 |
memory_device_bintrans_access(cpu, cpu->mem, extra, &low, &high); |
memory_device_dyntrans_access(cpu, cpu->mem, extra, |
478 |
|
(uint64_t *) &low, (uint64_t *) &high); |
479 |
|
|
480 |
if ((int64_t)low != -1) { |
if (low != -1) { |
481 |
|
int base = ((d->crtc_reg[VGA_CRTC_START_ADDR_HIGH] << 8) |
482 |
|
+ d->crtc_reg[VGA_CRTC_START_ADDR_LOW]) * 2; |
483 |
|
int new_u_y1, new_u_y2; |
484 |
debug("[ dev_vga_tick: bintrans access, %llx .. %llx ]\n", |
debug("[ dev_vga_tick: bintrans access, %llx .. %llx ]\n", |
485 |
(long long)low, (long long)high); |
(long long)low, (long long)high); |
486 |
|
low -= base; |
487 |
|
high -= base; |
488 |
d->update_x1 = 0; |
d->update_x1 = 0; |
489 |
d->update_x2 = d->max_x - 1; |
d->update_x2 = d->max_x - 1; |
490 |
d->update_y1 = (low/2) / d->max_x; |
new_u_y1 = (low/2) / d->max_x; |
491 |
d->update_y2 = ((high/2) / d->max_x) + 1; |
new_u_y2 = ((high/2) / d->max_x) + 1; |
492 |
|
if (new_u_y1 < d->update_y1) |
493 |
|
d->update_y1 = new_u_y1; |
494 |
|
if (new_u_y2 > d->update_y2) |
495 |
|
d->update_y2 = new_u_y2; |
496 |
|
if (d->update_y2 < 0) |
497 |
|
d->update_y2 = 0; |
498 |
if (d->update_y2 >= d->max_y) |
if (d->update_y2 >= d->max_y) |
499 |
d->update_y2 = d->max_y - 1; |
d->update_y2 = d->max_y - 1; |
500 |
d->modified = 1; |
d->modified = 1; |
1142 |
uint64_t videomem_base, uint64_t control_base, char *name) |
uint64_t videomem_base, uint64_t control_base, char *name) |
1143 |
{ |
{ |
1144 |
struct vga_data *d; |
struct vga_data *d; |
1145 |
int i, x,y, tmpi; |
int i, tmpi; |
1146 |
size_t allocsize; |
size_t allocsize; |
1147 |
|
|
1148 |
d = malloc(sizeof(struct vga_data)); |
d = malloc(sizeof(struct vga_data)); |
1162 |
d->pixel_repy = 1; |
d->pixel_repy = 1; |
1163 |
d->cur_mode = MODE_CHARCELL; |
d->cur_mode = MODE_CHARCELL; |
1164 |
d->crtc_reg[0xff] = 0x03; |
d->crtc_reg[0xff] = 0x03; |
1165 |
d->charcells_size = d->max_x * VGA_MEM_MAXY * 2; |
d->charcells_size = 0x8000; |
1166 |
d->gfx_mem_size = 1; /* Nothing, as we start in text mode */ |
d->gfx_mem_size = 1; /* Nothing, as we start in text mode */ |
1167 |
|
|
1168 |
/* Allocate in 4KB pages, to make it possible to use bintrans: */ |
/* Allocate in full pages, to make it possible to use bintrans: */ |
1169 |
allocsize = ((d->charcells_size - 1) | 0xfff) + 1; |
allocsize = ((d->charcells_size-1) | (machine->arch_pagesize-1)) + 1; |
1170 |
d->charcells = malloc(d->charcells_size); |
d->charcells = malloc(d->charcells_size); |
1171 |
d->charcells_outputed = malloc(d->charcells_size); |
d->charcells_outputed = malloc(d->charcells_size); |
1172 |
d->gfx_mem = malloc(d->gfx_mem_size); |
d->gfx_mem = malloc(d->gfx_mem_size); |
1176 |
exit(1); |
exit(1); |
1177 |
} |
} |
1178 |
|
|
1179 |
for (y=0; y<VGA_MEM_MAXY; y++) { |
for (i=0; i<d->charcells_size; i+=2) { |
1180 |
for (x=0; x<d->max_x; x++) { |
d->charcells[i] = ' '; |
1181 |
char ch = ' '; |
d->charcells[i+1] = 0x07; /* Default color */ |
|
i = (x + d->max_x * y) * 2; |
|
|
d->charcells[i] = ch; |
|
|
d->charcells[i+1] = 0x07; /* Default color */ |
|
|
} |
|
1182 |
} |
} |
1183 |
|
|
1184 |
memset(d->charcells_outputed, 0, d->charcells_size); |
memset(d->charcells_outputed, 0, d->charcells_size); |
1196 |
} |
} |
1197 |
|
|
1198 |
d->fb = dev_fb_init(machine, mem, VGA_FB_ADDR, VFB_GENERIC, |
d->fb = dev_fb_init(machine, mem, VGA_FB_ADDR, VFB_GENERIC, |
1199 |
d->fb_max_x, d->fb_max_y, d->fb_max_x, d->fb_max_y, 24, "VGA", 0); |
d->fb_max_x, d->fb_max_y, d->fb_max_x, d->fb_max_y, 24, "VGA"); |
1200 |
d->fb_size = d->fb_max_x * d->fb_max_y * 3; |
d->fb_size = d->fb_max_x * d->fb_max_y * 3; |
1201 |
|
|
1202 |
reset_palette(d, 0); |
reset_palette(d, 0); |
1203 |
|
|
1204 |
/* MEM_BINTRANS_WRITE_OK <-- This works with OpenBSD/arc, but not |
/* MEM_DYNTRANS_WRITE_OK <-- This works with OpenBSD/arc, but not |
1205 |
with Windows NT yet. Why? */ |
with Windows NT yet. Why? */ |
1206 |
memory_device_register(mem, "vga_charcells", videomem_base + 0x18000, |
memory_device_register(mem, "vga_charcells", videomem_base + 0x18000, |
1207 |
allocsize, dev_vga_access, d, MEM_BINTRANS_OK | |
allocsize, dev_vga_access, d, MEM_DYNTRANS_OK | |
1208 |
MEM_READING_HAS_NO_SIDE_EFFECTS, d->charcells); |
MEM_READING_HAS_NO_SIDE_EFFECTS, d->charcells); |
1209 |
memory_device_register(mem, "vga_gfx", videomem_base, GFX_ADDR_WINDOW, |
memory_device_register(mem, "vga_gfx", videomem_base, GFX_ADDR_WINDOW, |
1210 |
dev_vga_graphics_access, d, MEM_DEFAULT | |
dev_vga_graphics_access, d, MEM_DEFAULT | |