25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: dev_vga.c,v 1.101 2006/12/30 13:30:59 debug Exp $ |
* $Id: dev_vga.c,v 1.104 2007/06/15 19:57:34 debug Exp $ |
29 |
* |
* |
30 |
* VGA charcell and graphics device. |
* COMMENT: VGA framebuffer device (charcell and graphics modes) |
31 |
* |
* |
32 |
* It should work with 80x25 and 40x25 text modes, and with a few graphics |
* 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. |
* modes as long as no fancy VGA features are used. |
250 |
/* |
/* |
251 |
* vga_update_textmode(): |
* vga_update_textmode(): |
252 |
* |
* |
253 |
* Called from vga_update() when use_x11 is false. This causes modified |
* Called from vga_update() when x11 in_use is false. This causes modified |
254 |
* character cells to be "simulated" by outputing ANSI escape sequences |
* character cells to be "simulated" by outputing ANSI escape sequences |
255 |
* that draw the characters in a terminal window instead. |
* that draw the characters in a terminal window instead. |
256 |
*/ |
*/ |
407 |
base = ((d->crtc_reg[VGA_CRTC_START_ADDR_HIGH] << 8) |
base = ((d->crtc_reg[VGA_CRTC_START_ADDR_HIGH] << 8) |
408 |
+ d->crtc_reg[VGA_CRTC_START_ADDR_LOW]) * 2; |
+ d->crtc_reg[VGA_CRTC_START_ADDR_LOW]) * 2; |
409 |
|
|
410 |
if (!machine->use_x11) |
if (!machine->x11_md.in_use) |
411 |
vga_update_textmode(machine, d, base, start, end); |
vga_update_textmode(machine, d, base, start, end); |
412 |
|
|
413 |
for (i=start; i<=end; i+=2) { |
for (i=start; i<=end; i+=2) { |
467 |
continue; |
continue; |
468 |
dev_fb_access(machine->cpus[0], |
dev_fb_access(machine->cpus[0], |
469 |
machine->memory, addr, rgb_line, |
machine->memory, addr, rgb_line, |
470 |
3 * machine->x11_scaleup * font_width, |
3 * machine->x11_md.scaleup * font_width, |
471 |
MEM_WRITE, d->fb); |
MEM_WRITE, d->fb); |
472 |
} |
} |
473 |
} |
} |
503 |
} |
} |
504 |
|
|
505 |
|
|
506 |
/* |
DEVICE_TICK(vga) |
|
* dev_vga_tick(): |
|
|
*/ |
|
|
void dev_vga_tick(struct cpu *cpu, void *extra) |
|
507 |
{ |
{ |
508 |
struct vga_data *d = extra; |
struct vga_data *d = extra; |
509 |
int64_t low = -1, high; |
int64_t low = -1, high; |
556 |
} |
} |
557 |
} |
} |
558 |
|
|
559 |
if (!cpu->machine->use_x11) { |
if (!cpu->machine->x11_md.in_use) { |
560 |
/* NOTE: 2 > 0, so this only updates the cursor, no |
/* NOTE: 2 > 0, so this only updates the cursor, no |
561 |
character cells. */ |
character cells. */ |
562 |
vga_update_textmode(cpu->machine, d, 0, 2, 0); |
vga_update_textmode(cpu->machine, d, 0, 2, 0); |
584 |
|
|
585 |
|
|
586 |
/* |
/* |
|
* vga_graphics_access(): |
|
|
* |
|
587 |
* Reads and writes to the VGA video memory (pixels). |
* Reads and writes to the VGA video memory (pixels). |
588 |
*/ |
*/ |
589 |
DEVICE_ACCESS(vga_graphics) |
DEVICE_ACCESS(vga_graphics) |
679 |
|
|
680 |
|
|
681 |
/* |
/* |
682 |
* dev_vga_access(): |
* Reads and writes the VGA video memory (charcells). |
|
* |
|
|
* Reads and writes to the VGA video memory (charcells). |
|
683 |
*/ |
*/ |
684 |
DEVICE_ACCESS(vga) |
DEVICE_ACCESS(vga) |
685 |
{ |
{ |
783 |
case 0x01: |
case 0x01: |
784 |
d->cur_mode = MODE_CHARCELL; |
d->cur_mode = MODE_CHARCELL; |
785 |
d->max_x = 40; d->max_y = 25; |
d->max_x = 40; d->max_y = 25; |
786 |
d->pixel_repx = machine->x11_scaleup * 2; |
d->pixel_repx = machine->x11_md.scaleup * 2; |
787 |
d->pixel_repy = machine->x11_scaleup; |
d->pixel_repy = machine->x11_md.scaleup; |
788 |
d->font_width = 8; |
d->font_width = 8; |
789 |
d->font_height = 16; |
d->font_height = 16; |
790 |
d->font = font8x16; |
d->font = font8x16; |
794 |
case 0x03: |
case 0x03: |
795 |
d->cur_mode = MODE_CHARCELL; |
d->cur_mode = MODE_CHARCELL; |
796 |
d->max_x = 80; d->max_y = 25; |
d->max_x = 80; d->max_y = 25; |
797 |
d->pixel_repx = d->pixel_repy = machine->x11_scaleup; |
d->pixel_repx = d->pixel_repy = machine->x11_md.scaleup; |
798 |
d->font_width = 8; |
d->font_width = 8; |
799 |
d->font_height = 16; |
d->font_height = 16; |
800 |
d->font = font8x16; |
d->font = font8x16; |
804 |
d->max_x = 160; d->max_y = 200; |
d->max_x = 160; d->max_y = 200; |
805 |
d->graphics_mode = GRAPHICS_MODE_4BIT; |
d->graphics_mode = GRAPHICS_MODE_4BIT; |
806 |
d->bits_per_pixel = 4; |
d->bits_per_pixel = 4; |
807 |
d->pixel_repx = 4 * machine->x11_scaleup; |
d->pixel_repx = 4 * machine->x11_md.scaleup; |
808 |
d->pixel_repy = 2 * machine->x11_scaleup; |
d->pixel_repy = 2 * machine->x11_md.scaleup; |
809 |
break; |
break; |
810 |
case 0x09: |
case 0x09: |
811 |
case 0x0d: |
case 0x0d: |
814 |
d->graphics_mode = GRAPHICS_MODE_4BIT; |
d->graphics_mode = GRAPHICS_MODE_4BIT; |
815 |
d->bits_per_pixel = 4; |
d->bits_per_pixel = 4; |
816 |
d->pixel_repx = d->pixel_repy = |
d->pixel_repx = d->pixel_repy = |
817 |
2 * machine->x11_scaleup; |
2 * machine->x11_md.scaleup; |
818 |
break; |
break; |
819 |
case 0x0e: |
case 0x0e: |
820 |
d->cur_mode = MODE_GRAPHICS; |
d->cur_mode = MODE_GRAPHICS; |
821 |
d->max_x = 640; d->max_y = 200; |
d->max_x = 640; d->max_y = 200; |
822 |
d->graphics_mode = GRAPHICS_MODE_4BIT; |
d->graphics_mode = GRAPHICS_MODE_4BIT; |
823 |
d->bits_per_pixel = 4; |
d->bits_per_pixel = 4; |
824 |
d->pixel_repx = machine->x11_scaleup; |
d->pixel_repx = machine->x11_md.scaleup; |
825 |
d->pixel_repy = machine->x11_scaleup * 2; |
d->pixel_repy = machine->x11_md.scaleup * 2; |
826 |
break; |
break; |
827 |
case 0x10: |
case 0x10: |
828 |
d->cur_mode = MODE_GRAPHICS; |
d->cur_mode = MODE_GRAPHICS; |
829 |
d->max_x = 640; d->max_y = 350; |
d->max_x = 640; d->max_y = 350; |
830 |
d->graphics_mode = GRAPHICS_MODE_4BIT; |
d->graphics_mode = GRAPHICS_MODE_4BIT; |
831 |
d->bits_per_pixel = 4; |
d->bits_per_pixel = 4; |
832 |
d->pixel_repx = d->pixel_repy = machine->x11_scaleup; |
d->pixel_repx = d->pixel_repy = machine->x11_md.scaleup; |
833 |
break; |
break; |
834 |
case 0x12: |
case 0x12: |
835 |
d->cur_mode = MODE_GRAPHICS; |
d->cur_mode = MODE_GRAPHICS; |
836 |
d->max_x = 640; d->max_y = 480; |
d->max_x = 640; d->max_y = 480; |
837 |
d->graphics_mode = GRAPHICS_MODE_4BIT; |
d->graphics_mode = GRAPHICS_MODE_4BIT; |
838 |
d->bits_per_pixel = 4; |
d->bits_per_pixel = 4; |
839 |
d->pixel_repx = d->pixel_repy = machine->x11_scaleup; |
d->pixel_repx = d->pixel_repy = machine->x11_md.scaleup; |
840 |
break; |
break; |
841 |
case 0x13: |
case 0x13: |
842 |
d->cur_mode = MODE_GRAPHICS; |
d->cur_mode = MODE_GRAPHICS; |
844 |
d->graphics_mode = GRAPHICS_MODE_8BIT; |
d->graphics_mode = GRAPHICS_MODE_8BIT; |
845 |
d->bits_per_pixel = 8; |
d->bits_per_pixel = 8; |
846 |
d->pixel_repx = d->pixel_repy = |
d->pixel_repx = d->pixel_repy = |
847 |
2 * machine->x11_scaleup; |
2 * machine->x11_md.scaleup; |
848 |
break; |
break; |
849 |
default: |
default: |
850 |
fatal("TODO! video mode change hack (mode 0x%02x)\n", |
fatal("TODO! video mode change hack (mode 0x%02x)\n", |
875 |
if (d->cur_mode == MODE_GRAPHICS) |
if (d->cur_mode == MODE_GRAPHICS) |
876 |
d->gfx_mem_size = d->max_x * d->max_y / |
d->gfx_mem_size = d->max_x * d->max_y / |
877 |
(d->graphics_mode == GRAPHICS_MODE_8BIT? 1 : 2); |
(d->graphics_mode == GRAPHICS_MODE_8BIT? 1 : 2); |
878 |
d->gfx_mem = malloc(d->gfx_mem_size); |
|
879 |
|
CHECK_ALLOCATION(d->gfx_mem = malloc(d->gfx_mem_size)); |
880 |
|
|
881 |
/* Clear screen and reset the palette: */ |
/* Clear screen and reset the palette: */ |
882 |
memset(d->charcells_outputed, 0, d->charcells_size); |
memset(d->charcells_outputed, 0, d->charcells_size); |
1139 |
if ((d->current_retrace_line & 7) == 7) { |
if ((d->current_retrace_line & 7) == 7) { |
1140 |
if (d->retrace_palette == NULL && |
if (d->retrace_palette == NULL && |
1141 |
d->n_is1_reads > N_IS1_READ_THRESHOLD) { |
d->n_is1_reads > N_IS1_READ_THRESHOLD) { |
1142 |
d->retrace_palette = malloc( |
CHECK_ALLOCATION(d->retrace_palette = |
1143 |
MAX_RETRACE_SCANLINES * 256*3); |
malloc( |
1144 |
if (d->retrace_palette == NULL) { |
MAX_RETRACE_SCANLINES * 256*3)); |
|
fatal("out of memory\n"); |
|
|
exit(1); |
|
|
} |
|
1145 |
} |
} |
1146 |
if (d->retrace_palette != NULL) |
if (d->retrace_palette != NULL) |
1147 |
memcpy(d->retrace_palette + (d-> |
memcpy(d->retrace_palette + (d-> |
1190 |
uint64_t videomem_base, uint64_t control_base, char *name) |
uint64_t videomem_base, uint64_t control_base, char *name) |
1191 |
{ |
{ |
1192 |
struct vga_data *d; |
struct vga_data *d; |
1193 |
size_t i; |
size_t allocsize, i; |
|
size_t allocsize; |
|
1194 |
|
|
1195 |
d = malloc(sizeof(struct vga_data)); |
CHECK_ALLOCATION(d = malloc(sizeof(struct vga_data))); |
|
if (d == NULL) { |
|
|
fprintf(stderr, "out of memory\n"); |
|
|
exit(1); |
|
|
} |
|
1196 |
memset(d, 0, sizeof(struct vga_data)); |
memset(d, 0, sizeof(struct vga_data)); |
1197 |
|
|
1198 |
d->console_handle = console_start_slave(machine, "vga", |
d->console_handle = console_start_slave(machine, "vga", |
1206 |
d->crtc_reg[0xff] = 0x03; |
d->crtc_reg[0xff] = 0x03; |
1207 |
d->charcells_size = 0x8000; |
d->charcells_size = 0x8000; |
1208 |
d->gfx_mem_size = 1; /* Nothing, as we start in text mode */ |
d->gfx_mem_size = 1; /* Nothing, as we start in text mode */ |
1209 |
d->pixel_repx = d->pixel_repy = machine->x11_scaleup; |
d->pixel_repx = d->pixel_repy = machine->x11_md.scaleup; |
1210 |
|
|
1211 |
/* Allocate in full pages, to make it possible to use dyntrans: */ |
/* Allocate in full pages, to make it possible to use dyntrans: */ |
1212 |
allocsize = ((d->charcells_size-1) | (machine->arch_pagesize-1)) + 1; |
allocsize = ((d->charcells_size-1) | (machine->arch_pagesize-1)) + 1; |
1213 |
d->charcells = malloc(d->charcells_size); |
CHECK_ALLOCATION(d->charcells = malloc(d->charcells_size)); |
1214 |
d->charcells_outputed = malloc(d->charcells_size); |
CHECK_ALLOCATION(d->charcells_outputed = malloc(d->charcells_size)); |
1215 |
d->charcells_drawn = malloc(d->charcells_size); |
CHECK_ALLOCATION(d->charcells_drawn = malloc(d->charcells_size)); |
1216 |
d->gfx_mem = malloc(d->gfx_mem_size); |
CHECK_ALLOCATION(d->gfx_mem = malloc(d->gfx_mem_size)); |
|
if (d->charcells == NULL || d->charcells_outputed == NULL || |
|
|
d->charcells_drawn == NULL || d->gfx_mem == NULL) { |
|
|
fprintf(stderr, "out of memory in dev_vga_init()\n"); |
|
|
exit(1); |
|
|
} |
|
1217 |
|
|
1218 |
memset(d->charcells_drawn, 0, d->charcells_size); |
memset(d->charcells_drawn, 0, d->charcells_size); |
1219 |
|
|
1261 |
d->update_y2 = d->max_y - 1; |
d->update_y2 = d->max_y - 1; |
1262 |
d->modified = 1; |
d->modified = 1; |
1263 |
|
|
1264 |
machine_add_tickfunction(machine, dev_vga_tick, d, |
machine_add_tickfunction(machine, dev_vga_tick, d, VGA_TICK_SHIFT); |
|
VGA_TICK_SHIFT, 0.0); |
|
1265 |
|
|
1266 |
register_reset(d); |
register_reset(d); |
1267 |
|
|