Merge branch '86Box:master' into nec-v20

This commit is contained in:
Jasmine Iwanek
2022-08-31 21:24:00 -04:00
committed by GitHub
98 changed files with 58701 additions and 56402 deletions

View File

@@ -903,7 +903,7 @@ then
# Now patch a 64-bit Mach-O header (0xFEEDFACF, little endian), either at
# the beginning or as a sub-header within a fat binary as parsed above.
if [ "$(dd if="$line" bs=1 seek=$macho_offset count=8 status=none)" = "$(printf '\xCF\xFA\xED\xFE\x07\x00\x00\x01')" ]
if [ "$(dd if="$line" bs=1 skip=$macho_offset count=8 status=none)" = "$(printf '\xCF\xFA\xED\xFE\x07\x00\x00\x01')" ]
then
# Change CPU subtype in the Mach-O header from ALL (0x00000003) to H (0x00000008).
printf '\x08\x00\x00\x00' | dd of="$line" bs=1 seek=$((macho_offset + 8)) count=4 conv=notrunc status=none

View File

@@ -29,7 +29,7 @@
#include <86box/chipset.h>
#include <86box/spd.h>
#include <86box/machine.h>
#include <86box/video.h>
#include <86box/agpgart.h>
enum
@@ -59,7 +59,7 @@ typedef struct
uint8_t mem_state[256];
int type;
smram_t *smram_low, *smram_high;
void *agpgart;
agpgart_t *agpgart;
void (*write_drbs)(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit);
} i4x0_t;

View File

@@ -33,7 +33,7 @@
#include <86box/pci.h>
#include <86box/chipset.h>
#include <86box/spd.h>
#include <86box/video.h>
#include <86box/agpgart.h>
#define VIA_585 0x05851000
#define VIA_595 0x05950000
@@ -50,8 +50,8 @@ typedef struct via_apollo_t
uint8_t drb_unit;
uint8_t pci_conf[256];
smram_t *smram;
void *agpgart;
smram_t *smram;
agpgart_t *agpgart;
} via_apollo_t;

View File

@@ -291,7 +291,7 @@ config_detect_bom(char *fn)
#endif
if (f == NULL)
return (0);
fread(bom, 1, 3, f);
(void) !fread(bom, 1, 3, f);
if (bom[0] == 0xEF && bom[1] == 0xBB && bom[2] == 0xBF) {
fclose(f);
return 1;
@@ -357,7 +357,7 @@ config_read(char *fn)
#ifdef __HAIKU__
config_fgetws(buff, sizeof_w(buff), f);
#else
fgetws(buff, sizeof_w(buff), f);
(void) !fgetws(buff, sizeof_w(buff), f);
#endif
if (feof(f))
break;
@@ -387,7 +387,7 @@ config_read(char *fn)
c++;
d = 0;
while (buff[c] != L']' && buff[c])
wctomb(&(sname[d++]), buff[c++]);
(void) !wctomb(&(sname[d++]), buff[c++]);
sname[d] = L'\0';
/* Is the section name properly terminated? */
@@ -408,7 +408,7 @@ config_read(char *fn)
/* Get the variable name. */
d = 0;
while ((buff[c] != L'=') && (buff[c] != L' ') && buff[c])
wctomb(&(ename[d++]), buff[c++]);
(void) !wctomb(&(ename[d++]), buff[c++]);
ename[d] = L'\0';
/* Skip incomplete lines. */

View File

@@ -119,12 +119,12 @@ cart_image_load(int drive, char *fn)
if (size & 0x00000fff) {
size -= 0x00000200;
fseek(f, 0x000001ce, SEEK_SET);
fread(&base, 1, 2, f);
(void) !fread(&base, 1, 2, f);
base <<= 4;
fseek(f, 0x00000200, SEEK_SET);
carts[drive].buf = (uint8_t *) malloc(size);
memset(carts[drive].buf, 0x00, size);
fread(carts[drive].buf, 1, size, f);
(void) !fread(carts[drive].buf, 1, size, f);
fclose(f);
} else {
base = drive ? 0xe0000 : 0xd0000;
@@ -133,7 +133,7 @@ cart_image_load(int drive, char *fn)
fseek(f, 0x00000000, SEEK_SET);
carts[drive].buf = (uint8_t *) malloc(size);
memset(carts[drive].buf, 0x00, size);
fread(carts[drive].buf, 1, size, f);
(void) !fread(carts[drive].buf, 1, size, f);
fclose(f);
}

View File

@@ -112,7 +112,7 @@ lm78_nvram(lm78_t *dev, uint8_t save)
if (save)
fwrite(&dev->as99127f.nvram, sizeof(dev->as99127f.nvram), 1, f);
else
fread(&dev->as99127f.nvram, sizeof(dev->as99127f.nvram), 1, f);
(void) !fread(&dev->as99127f.nvram, sizeof(dev->as99127f.nvram), 1, f);
fclose(f);
}

View File

@@ -71,7 +71,7 @@ MVHDMeta* mvhd_convert_to_vhd_sparse(const char* utf8_raw_path, const char* utf8
copy_sect = total_sectors - i;
memset(buff, 0, sizeof buff);
}
fread(buff, MVHD_SECTOR_SIZE, copy_sect, raw_img);
(void) !fread(buff, MVHD_SECTOR_SIZE, copy_sect, raw_img);
/* Only write data if there's data to write, to take advantage of the sparse VHD format */
if (memcmp(buff, empty_buff, sizeof buff) != 0) {
mvhd_write_sectors(vhdm, i, copy_sect, buff);

View File

@@ -214,7 +214,7 @@ MVHDMeta* mvhd_create_fixed_raw(const char* path, FILE* raw_img, uint64_t size_i
mvhd_gen_footer(&vhdm->footer, raw_size, geom, MVHD_TYPE_FIXED, 0);
mvhd_fseeko64(raw_img, 0, SEEK_SET);
for (s = 0; s < size_sectors; s++) {
fread(img_data, sizeof img_data, 1, raw_img);
(void) !fread(img_data, sizeof img_data, 1, raw_img);
fwrite(img_data, sizeof img_data, 1, f);
if (progress_callback)
progress_callback(s + 1, size_sectors);

View File

@@ -62,7 +62,7 @@ void mvhd_write_empty_sectors(FILE* f, int sector_count) {
static void mvhd_read_sect_bitmap(MVHDMeta* vhdm, int blk) {
if (vhdm->block_offset[blk] != MVHD_SPARSE_BLK) {
mvhd_fseeko64(vhdm->f, (uint64_t)vhdm->block_offset[blk] * MVHD_SECTOR_SIZE, SEEK_SET);
fread(vhdm->bitmap.curr_bitmap, vhdm->bitmap.sector_count * MVHD_SECTOR_SIZE, 1, vhdm->f);
(void) !fread(vhdm->bitmap.curr_bitmap, vhdm->bitmap.sector_count * MVHD_SECTOR_SIZE, 1, vhdm->f);
} else {
memset(vhdm->bitmap.curr_bitmap, 0, vhdm->bitmap.sector_count * MVHD_SECTOR_SIZE);
}
@@ -113,12 +113,12 @@ static void mvhd_create_block(MVHDMeta* vhdm, int blk) {
uint8_t footer[MVHD_FOOTER_SIZE];
/* Seek to where the footer SHOULD be */
mvhd_fseeko64(vhdm->f, -MVHD_FOOTER_SIZE, SEEK_END);
fread(footer, sizeof footer, 1, vhdm->f);
(void) !fread(footer, sizeof footer, 1, vhdm->f);
mvhd_fseeko64(vhdm->f, -MVHD_FOOTER_SIZE, SEEK_END);
if (!mvhd_is_conectix_str(footer)) {
/* Oh dear. We use the header instead, since something has gone wrong at the footer */
mvhd_fseeko64(vhdm->f, 0, SEEK_SET);
fread(footer, sizeof footer, 1, vhdm->f);
(void) !fread(footer, sizeof footer, 1, vhdm->f);
mvhd_fseeko64(vhdm->f, 0, SEEK_END);
}
int64_t abs_offset = mvhd_ftello64(vhdm->f);
@@ -150,7 +150,7 @@ int mvhd_fixed_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_
mvhd_check_sectors(offset, num_sectors, total_sectors, &transfer_sectors, &truncated_sectors);
addr = (int64_t)offset * MVHD_SECTOR_SIZE;
mvhd_fseeko64(vhdm->f, addr, SEEK_SET);
fread(out_buff, transfer_sectors*MVHD_SECTOR_SIZE, 1, vhdm->f);
(void) !fread(out_buff, transfer_sectors*MVHD_SECTOR_SIZE, 1, vhdm->f);
return truncated_sectors;
}
@@ -178,7 +178,7 @@ int mvhd_sparse_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out
}
}
if (VHD_TESTBIT(vhdm->bitmap.curr_bitmap, sib)) {
fread(buff, MVHD_SECTOR_SIZE, 1, vhdm->f);
(void) !fread(buff, MVHD_SECTOR_SIZE, 1, vhdm->f);
} else {
memset(buff, 0, MVHD_SECTOR_SIZE);
mvhd_fseeko64(vhdm->f, MVHD_SECTOR_SIZE, SEEK_CUR);

View File

@@ -45,7 +45,7 @@ static int mvhd_init_sector_bitmap(MVHDMeta* vhdm, MVHDError* err);
static void mvhd_read_footer(MVHDMeta* vhdm) {
uint8_t buffer[MVHD_FOOTER_SIZE];
mvhd_fseeko64(vhdm->f, -MVHD_FOOTER_SIZE, SEEK_END);
fread(buffer, sizeof buffer, 1, vhdm->f);
(void) !fread(buffer, sizeof buffer, 1, vhdm->f);
mvhd_buffer_to_footer(&vhdm->footer, buffer);
}
@@ -57,7 +57,7 @@ static void mvhd_read_footer(MVHDMeta* vhdm) {
static void mvhd_read_sparse_header(MVHDMeta* vhdm) {
uint8_t buffer[MVHD_SPARSE_SIZE];
mvhd_fseeko64(vhdm->f, vhdm->footer.data_offset, SEEK_SET);
fread(buffer, sizeof buffer, 1, vhdm->f);
(void) !fread(buffer, sizeof buffer, 1, vhdm->f);
mvhd_buffer_to_header(&vhdm->sparse, buffer);
}
@@ -104,7 +104,7 @@ static int mvhd_read_bat(MVHDMeta *vhdm, MVHDError* err) {
}
mvhd_fseeko64(vhdm->f, vhdm->sparse.bat_offset, SEEK_SET);
for (uint32_t i = 0; i < vhdm->sparse.max_bat_ent; i++) {
fread(&vhdm->block_offset[i], sizeof *vhdm->block_offset, 1, vhdm->f);
(void) !fread(&vhdm->block_offset[i], sizeof *vhdm->block_offset, 1, vhdm->f);
vhdm->block_offset[i] = mvhd_from_be32(vhdm->block_offset[i]);
}
return 0;
@@ -254,7 +254,7 @@ static char* mvhd_get_diff_parent_path(MVHDMeta* vhdm, int* err) {
goto paths_cleanup;
}
mvhd_fseeko64(vhdm->f, vhdm->sparse.par_loc_entry[i].plat_data_offset, SEEK_SET);
fread(paths->tmp_src_path, sizeof (uint8_t), utf_inlen, vhdm->f);
(void) !fread(paths->tmp_src_path, sizeof (uint8_t), utf_inlen, vhdm->f);
/* Note, the W2*u parent locators are UTF-16LE, unlike the filename field previously obtained,
which is UTF-16BE */
utf_ret = UTF16LEToUTF8(loc_path, &utf_outlen, (const unsigned char*)paths->tmp_src_path, &utf_inlen);
@@ -322,7 +322,7 @@ bool mvhd_file_is_vhd(FILE* f) {
if (f) {
uint8_t con_str[8];
mvhd_fseeko64(f, -MVHD_FOOTER_SIZE, SEEK_END);
fread(con_str, sizeof con_str, 1, f);
(void) !fread(con_str, sizeof con_str, 1, f);
return mvhd_is_conectix_str(con_str);
} else {
return false;

View File

@@ -2923,13 +2923,13 @@ d86f_read_track(int drive, int track, int thin_track, int side, uint16_t *da, ui
}
} else
dev->extra_bit_cells[side] = 0;
fread(&(dev->index_hole_pos[side]), 4, 1, dev->f);
(void) !fread(&(dev->index_hole_pos[side]), 4, 1, dev->f);
} else
fseek(dev->f, dev->track_offset[logical_track] + d86f_track_header_size(drive), SEEK_SET);
array_size = d86f_get_array_size(drive, side, 0);
fread(da, 1, array_size, dev->f);
(void) !fread(da, 1, array_size, dev->f);
if (d86f_has_surface_desc(drive))
fread(sa, 1, array_size, dev->f);
(void) !fread(sa, 1, array_size, dev->f);
} else {
if (! thin_track) {
switch((dev->disk_flags >> 1) & 3) {
@@ -3529,7 +3529,7 @@ d86f_load(int drive, char *fn)
len = ftell(dev->f);
fseek(dev->f, 0, SEEK_SET);
fread(&magic, 4, 1, dev->f);
(void) !fread(&magic, 4, 1, dev->f);
if (len < 16) {
/* File is WAY too small, abort. */
@@ -3570,7 +3570,7 @@ d86f_load(int drive, char *fn)
d86f_log("86F: Recognized file version: %i.%02i\n", dev->version >> 8, dev->version & 0xff);
}
fread(&(dev->disk_flags), 2, 1, dev->f);
(void) !fread(&(dev->disk_flags), 2, 1, dev->f);
if (d86f_has_surface_desc(drive)) {
for (i = 0; i < 2; i++)
@@ -3719,7 +3719,7 @@ d86f_load(int drive, char *fn)
fseek(dev->f, 8, SEEK_SET);
fread(dev->track_offset, 1, d86f_get_track_table_size(drive), dev->f);
(void) !fread(dev->track_offset, 1, d86f_get_track_table_size(drive), dev->f);
if (! (dev->track_offset[0])) {
/* File has no track 0 side 0, abort. */

View File

@@ -684,12 +684,12 @@ img_load(int drive, char *fn)
/* This is a Japanese FDI image, so let's read the header */
img_log("img_load(): File is a Japanese FDI image...\n");
fseek(dev->f, 0x10, SEEK_SET);
(void)fread(&bpb_bps, 1, 2, dev->f);
(void) !fread(&bpb_bps, 1, 2, dev->f);
fseek(dev->f, 0x0C, SEEK_SET);
(void)fread(&size, 1, 4, dev->f);
(void) !fread(&size, 1, 4, dev->f);
bpb_total = size / bpb_bps;
fseek(dev->f, 0x08, SEEK_SET);
(void)fread(&(dev->base), 1, 4, dev->f);
(void) !fread(&(dev->base), 1, 4, dev->f);
fseek(dev->f, dev->base + 0x15, SEEK_SET);
bpb_mid = fgetc(dev->f);
if (bpb_mid < 0xF0)
@@ -729,7 +729,7 @@ img_load(int drive, char *fn)
dev->disk_at_once = 1;
fseek(dev->f, 0x50, SEEK_SET);
(void)fread(&dev->tracks, 1, 4, dev->f);
(void) !fread(&dev->tracks, 1, 4, dev->f);
/* Decode the entire file - pass 1, no write to buffer, determine length. */
fseek(dev->f, 0x80, SEEK_SET);
@@ -740,10 +740,10 @@ img_load(int drive, char *fn)
if (! track_bytes) {
/* Skip first 3 bytes - their meaning is unknown to us but could be a checksum. */
first_byte = fgetc(dev->f);
fread(&track_bytes, 1, 2, dev->f);
(void) !fread(&track_bytes, 1, 2, dev->f);
img_log("Block header: %02X %04X ", first_byte, track_bytes);
/* Read the length of encoded data block. */
fread(&track_bytes, 1, 2, dev->f);
(void) !fread(&track_bytes, 1, 2, dev->f);
img_log("%04X\n", track_bytes);
}
@@ -765,7 +765,7 @@ img_load(int drive, char *fn)
/* Literal. */
track_bytes -= (run & 0x7f);
literal = (uint8_t *)malloc(run & 0x7f);
fread(literal, 1, (run & 0x7f), dev->f);
(void) !fread(literal, 1, (run & 0x7f), dev->f);
free(literal);
}
size += (run & 0x7f);
@@ -775,7 +775,7 @@ img_load(int drive, char *fn)
/* Literal block. */
size += (track_bytes - fdf_suppress_final_byte);
literal = (uint8_t *)malloc(track_bytes);
fread(literal, 1, track_bytes, dev->f);
(void) !fread(literal, 1, track_bytes, dev->f);
free(literal);
track_bytes = 0;
}
@@ -794,10 +794,10 @@ img_load(int drive, char *fn)
if (! track_bytes) {
/* Skip first 3 bytes - their meaning is unknown to us but could be a checksum. */
first_byte = fgetc(dev->f);
fread(&track_bytes, 1, 2, dev->f);
(void) !fread(&track_bytes, 1, 2, dev->f);
img_log("Block header: %02X %04X ", first_byte, track_bytes);
/* Read the length of encoded data block. */
fread(&track_bytes, 1, 2, dev->f);
(void) !fread(&track_bytes, 1, 2, dev->f);
img_log("%04X\n", track_bytes);
}
@@ -824,7 +824,7 @@ img_load(int drive, char *fn)
/* Literal. */
track_bytes -= real_run;
literal = (uint8_t *) malloc(real_run);
fread(literal, 1, real_run, dev->f);
(void) !fread(literal, 1, real_run, dev->f);
if (! track_bytes)
real_run -= fdf_suppress_final_byte;
if (run & 0x7f)
@@ -835,7 +835,7 @@ img_load(int drive, char *fn)
} else {
/* Literal block. */
literal = (uint8_t *) malloc(track_bytes);
fread(literal, 1, track_bytes, dev->f);
(void) !fread(literal, 1, track_bytes, dev->f);
memcpy(bpos, literal, track_bytes - fdf_suppress_final_byte);
free(literal);
bpos += (track_bytes - fdf_suppress_final_byte);
@@ -865,10 +865,10 @@ img_load(int drive, char *fn)
dev->f = plat_fopen(fn, "rb");
fseek(dev->f, 0x03, SEEK_SET);
fread(&bpb_bps, 1, 2, dev->f);
(void) !fread(&bpb_bps, 1, 2, dev->f);
#if 0
fseek(dev->f, 0x0B, SEEK_SET);
fread(&bpb_total, 1, 2, dev->f);
(void) !fread(&bpb_total, 1, 2, dev->f);
#endif
fseek(dev->f, 0x10, SEEK_SET);
bpb_sectors = fgetc(dev->f);
@@ -888,7 +888,7 @@ img_load(int drive, char *fn)
memset(dev->disk_data, 0xf6, ((uint32_t) bpb_total) * ((uint32_t) bpb_bps));
fseek(dev->f, 0x6F, SEEK_SET);
fread(&comment_len, 1, 2, dev->f);
(void) !fread(&comment_len, 1, 2, dev->f);
fseek(dev->f, -1, SEEK_END);
size = ftell(dev->f) + 1;
@@ -898,7 +898,7 @@ img_load(int drive, char *fn)
cur_pos = 0;
while(! feof(dev->f)) {
fread(&block_len, 1, 2, dev->f);
(void) !fread(&block_len, 1, 2, dev->f);
if (! feof(dev->f)) {
if (block_len < 0) {
@@ -915,10 +915,10 @@ img_load(int drive, char *fn)
} else if (block_len > 0) {
if ((cur_pos + block_len) > ((uint32_t) bpb_total) * ((uint32_t) bpb_bps)) {
block_len = ((uint32_t) bpb_total) * ((uint32_t) bpb_bps) - cur_pos;
fread(dev->disk_data + cur_pos, 1, block_len, dev->f);
(void) !fread(dev->disk_data + cur_pos, 1, block_len, dev->f);
break;
} else {
fread(dev->disk_data + cur_pos, 1, block_len, dev->f);
(void) !fread(dev->disk_data + cur_pos, 1, block_len, dev->f);
cur_pos += block_len;
}
}
@@ -939,9 +939,9 @@ img_load(int drive, char *fn)
} else
img_log("img_load(): File is a raw image...\n");
fseek(dev->f, dev->base + 0x0B, SEEK_SET);
fread(&bpb_bps, 1, 2, dev->f);
(void) !fread(&bpb_bps, 1, 2, dev->f);
fseek(dev->f, dev->base + 0x13, SEEK_SET);
fread(&bpb_total, 1, 2, dev->f);
(void) !fread(&bpb_total, 1, 2, dev->f);
fseek(dev->f, dev->base + 0x15, SEEK_SET);
bpb_mid = fgetc(dev->f);
fseek(dev->f, dev->base + 0x18, SEEK_SET);
@@ -1112,7 +1112,7 @@ jump_if_fdf:
/* The image is a Japanese FDI, therefore we read the number of tracks from the header. */
if (fseek(dev->f, 0x1C, SEEK_SET) == -1)
fatal("Japanese FDI: Failed when seeking to 0x1C\n");
fread(&(dev->tracks), 1, 4, dev->f);
(void) !fread(&(dev->tracks), 1, 4, dev->f);
} else {
if (!cqm && !fdf) {
/* Number of tracks = number of total sectors divided by sides times sectors per track. */

View File

@@ -645,7 +645,7 @@ td0_initialize(int drive)
}
fseek(dev->f, 0, SEEK_SET);
fread(header, 1, 12, dev->f);
(void) !fread(header, 1, 12, dev->f);
head_count = header[9];
if (header[0] == 't') {

View File

@@ -20,11 +20,18 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef _WIN32
# ifndef __clang__
# include <unistd.h>
# else
# include <io.h>
# define ssize_t long
# define strtok_r(a, b, c) strtok_s(a, b, c)
# endif
# include <winsock2.h>
# include <ws2tcpip.h>
#else
# include <unistd.h>
# include <arpa/inet.h>
# include <sys/socket.h>
# include <errno.h>
@@ -706,6 +713,8 @@ gdbstub_client_read_reg(int index, uint8_t *buf)
static void
gdbstub_client_packet(gdbstub_client_t *client)
{
gdbstub_breakpoint_t *breakpoint, *prev_breakpoint = NULL, **first_breakpoint = NULL;
#ifdef GDBSTUB_CHECK_CHECKSUM /* msys2 gdb 11.1 transmits qSupported and H with invalid checksum... */
uint8_t rcv_checksum = 0, checksum = 0;
#endif
@@ -1202,7 +1211,6 @@ unknown:
case 'z': /* remove break/watchpoint */
case 'Z': /* insert break/watchpoint */
gdbstub_breakpoint_t *breakpoint, *prev_breakpoint = NULL, **first_breakpoint;
/* Parse breakpoint type. */
switch (client->packet[1]) {

View File

@@ -0,0 +1,35 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* AGP Graphics Address Remapping Table remapping emulation.
*
*
*
* Authors: RichardG, <richardg867@gmail.com>
*
* Copyright 2021 RichardG.
*/
#ifndef EMU_AGPGART_H
#define EMU_AGPGART_H
typedef struct agpgart_s {
int aperture_enable;
uint32_t aperture_base, aperture_size, aperture_mask, gart_base;
mem_mapping_t aperture_mapping;
} agpgart_t;
extern void agpgart_set_aperture(agpgart_t *dev, uint32_t base, uint32_t size, int enable);
extern void agpgart_set_gart(agpgart_t *dev, uint32_t base);
#ifdef EMU_DEVICE_H
/* AGP GART */
extern const device_t agpgart_device;
#endif
#endif /*EMU_AGPGART_H*/

View File

@@ -361,9 +361,9 @@
#define IDM_ACTION_END_TRACE 40019
#define IDM_ACTION_TRACE 40020
#endif
#define IDM_CONFIG 40020
#define IDM_VID_HIDE_STATUS_BAR 40021
#define IDM_VID_HIDE_TOOLBAR 40022
#define IDM_CONFIG 40021
#define IDM_VID_HIDE_STATUS_BAR 40022
#define IDM_VID_HIDE_TOOLBAR 40023
#define IDM_UPDATE_ICONS 40030
#define IDM_SND_GAIN 40031
#define IDM_VID_RESIZE 40040

View File

@@ -258,9 +258,6 @@ extern int get_actual_size_y(void);
extern uint32_t video_color_transform(uint32_t color);
extern void agpgart_set_aperture(void *handle, uint32_t base, uint32_t size, int enable);
extern void agpgart_set_gart(void *handle, uint32_t base);
#define video_inform(type, video_timings_ptr) video_inform_monitor(type, video_timings_ptr, monitor_index_global)
#define video_get_type() video_get_type_monitor(0)
#define video_blend(x, y) video_blend_monitor(x, y, monitor_index_global)
@@ -532,8 +529,6 @@ extern const device_t velocity_100_agp_device;
/* Wyse 700 */
extern const device_t wy700_device;
/* AGP GART */
extern const device_t agpgart_device;
#endif
#endif /*EMU_VIDEO_H*/

View File

@@ -1041,7 +1041,7 @@ t1000_emsboard_load(void)
if (mem_size > 512) {
f = plat_fopen(nvr_path("t1000_ems.nvr"), "rb");
if (f != NULL) {
fread(&ram[512 * 1024], 1024, (mem_size - 512), f);
(void) !fread(&ram[512 * 1024], 1024, (mem_size - 512), f);
fclose(f);
}
}

View File

@@ -217,7 +217,7 @@ catalyst_flash_init(const device_t *info)
f = nvr_fopen(flash_path, "rb");
if (f) {
fread(dev->array, 0x20000, 1, f);
(void) !fread(dev->array, 0x20000, 1, f);
fclose(f);
}

View File

@@ -518,16 +518,16 @@ intel_flash_init(const device_t *info)
f = nvr_fopen(flash_path, "rb");
if (f) {
fread(&(dev->array[dev->block_start[BLOCK_MAIN1]]), dev->block_len[BLOCK_MAIN1], 1, f);
(void) !fread(&(dev->array[dev->block_start[BLOCK_MAIN1]]), dev->block_len[BLOCK_MAIN1], 1, f);
if (dev->block_len[BLOCK_MAIN2])
fread(&(dev->array[dev->block_start[BLOCK_MAIN2]]), dev->block_len[BLOCK_MAIN2], 1, f);
(void) !fread(&(dev->array[dev->block_start[BLOCK_MAIN2]]), dev->block_len[BLOCK_MAIN2], 1, f);
if (dev->block_len[BLOCK_MAIN3])
fread(&(dev->array[dev->block_start[BLOCK_MAIN3]]), dev->block_len[BLOCK_MAIN3], 1, f);
(void) !fread(&(dev->array[dev->block_start[BLOCK_MAIN3]]), dev->block_len[BLOCK_MAIN3], 1, f);
if (dev->block_len[BLOCK_MAIN4])
fread(&(dev->array[dev->block_start[BLOCK_MAIN4]]), dev->block_len[BLOCK_MAIN4], 1, f);
(void) !fread(&(dev->array[dev->block_start[BLOCK_MAIN4]]), dev->block_len[BLOCK_MAIN4], 1, f);
fread(&(dev->array[dev->block_start[BLOCK_DATA1]]), dev->block_len[BLOCK_DATA1], 1, f);
fread(&(dev->array[dev->block_start[BLOCK_DATA2]]), dev->block_len[BLOCK_DATA2], 1, f);
(void) !fread(&(dev->array[dev->block_start[BLOCK_DATA1]]), dev->block_len[BLOCK_DATA1], 1, f);
(void) !fread(&(dev->array[dev->block_start[BLOCK_DATA2]]), dev->block_len[BLOCK_DATA2], 1, f);
fclose(f);
}

View File

@@ -30,9 +30,9 @@
#include <pthread.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdatomic.h>
#endif
#include <stdatomic.h>
#include <minitrace/minitrace.h>
#ifdef __GNUC__
@@ -293,8 +293,13 @@ void mtr_start() {
#ifndef MTR_ENABLED
return;
#endif
#ifdef _WIN32
pthread_cond_init(&buffer_not_full_cond);
pthread_cond_init(&buffer_full_cond);
#else
pthread_cond_init(&buffer_not_full_cond, NULL);
pthread_cond_init(&buffer_full_cond, NULL);
#endif
atomic_store(&is_tracing, TRUE);
init_flushing_thread();
}

View File

@@ -23,7 +23,7 @@ net_event_init(net_evt_t *event)
#ifdef _WIN32
event->handle = CreateEvent(NULL, FALSE, FALSE, NULL);
#else
(void)pipe(event->fds);
(void) !pipe(event->fds);
setup_fd(event->fds[0]);
setup_fd(event->fds[1]);
#endif
@@ -35,7 +35,7 @@ net_event_set(net_evt_t *event)
#ifdef _WIN32
SetEvent(event->handle);
#else
(void)write(event->fds[1], "a", 1);
(void) !write(event->fds[1], "a", 1);
#endif
}
@@ -46,7 +46,7 @@ net_event_clear(net_evt_t *event)
/* Do nothing on WIN32 since we use an auto-reset event */
#else
char dummy[1];
(void)read(event->fds[0], &dummy, sizeof(dummy));
(void) !read(event->fds[0], &dummy, sizeof(dummy));
#endif
}

View File

@@ -182,7 +182,12 @@ if(WIN32)
enable_language(RC)
target_sources(86Box PUBLIC ../win/86Box-qt.rc)
target_sources(plat PRIVATE win_dynld.c)
target_sources(plat PRIVATE win_joystick_rawinput.c)
if(DINPUT)
target_sources(plat PRIVATE win_joystick.cpp)
target_link_libraries(86Box dinput8)
else()
target_sources(plat PRIVATE win_joystick_rawinput.c)
endif()
target_sources(ui PRIVATE qt_d3d9renderer.hpp qt_d3d9renderer.cpp)
target_link_libraries(86Box hid d3d9)

View File

@@ -289,7 +289,7 @@ MediaHistoryManager::removeMissingImages(device_index_list_t &device_history)
continue;
}
// For this check, explicitly prepend `usr_path` to relative paths to account for $CWD platform variances
QFileInfo absolute_path = file_info.isRelative() ? getUsrPath().append(file_info.filePath()) : file_info;
QFileInfo absolute_path = file_info.isRelative() ? QFileInfo(getUsrPath().append(file_info.filePath())) : file_info;
if(!absolute_path.exists()) {
qWarning("Image file %s does not exist - removing from history", qPrintable(file_info.filePath()));
checked_path = "";

View File

@@ -758,11 +758,11 @@ aha_setbios(x54x_t *dev)
/* Load first chunk of BIOS (which is the main BIOS, aka ROM1.) */
dev->rom1 = malloc(ROM_SIZE);
(void)fread(dev->rom1, ROM_SIZE, 1, f);
(void) !fread(dev->rom1, ROM_SIZE, 1, f);
temp -= ROM_SIZE;
if (temp > 0) {
dev->rom2 = malloc(ROM_SIZE);
(void)fread(dev->rom2, ROM_SIZE, 1, f);
(void) !fread(dev->rom2, ROM_SIZE, 1, f);
temp -= ROM_SIZE;
} else {
dev->rom2 = NULL;
@@ -875,10 +875,10 @@ aha_setmcode(x54x_t *dev)
}
aha1542cp_pnp_rom = (uint8_t *) malloc(dev->pnp_len + 7);
fseek(f, dev->pnp_offset, SEEK_SET);
(void)fread(aha1542cp_pnp_rom, dev->pnp_len, 1, f);
(void) !fread(aha1542cp_pnp_rom, dev->pnp_len, 1, f);
memset(&(aha1542cp_pnp_rom[4]), 0x00, 5);
fseek(f, dev->pnp_offset + 4, SEEK_SET);
(void)fread(&(aha1542cp_pnp_rom[9]), dev->pnp_len - 4, 1, f);
(void) !fread(&(aha1542cp_pnp_rom[9]), dev->pnp_len - 4, 1, f);
/* Even the real AHA-1542CP microcode seem to be flipping bit
4 to not erroneously indicate there is a range length. */
aha1542cp_pnp_rom[0x87] |= 0x04;
@@ -889,7 +889,7 @@ aha_setmcode(x54x_t *dev)
/* Load the SCSISelect decompression code. */
fseek(f, dev->cmd_33_offset, SEEK_SET);
(void)fread(dev->cmd_33_buf, dev->cmd_33_len, 1, f);
(void) !fread(dev->cmd_33_buf, dev->cmd_33_len, 1, f);
(void)fclose(f);
}

View File

@@ -1747,7 +1747,7 @@ buslogic_init(const device_t *info)
if (has_autoscsi_rom) {
f = rom_fopen(autoscsi_rom_name, "rb");
if (f) {
fread(bl->AutoSCSIROM, 1, autoscsi_rom_size, f);
(void) !fread(bl->AutoSCSIROM, 1, autoscsi_rom_size, f);
fclose(f);
f = NULL;
}
@@ -1756,7 +1756,7 @@ buslogic_init(const device_t *info)
if (has_scam_rom) {
f = rom_fopen(scam_rom_name, "rb");
if (f) {
fread(bl->SCAMData, 1, scam_rom_size, f);
(void) !fread(bl->SCAMData, 1, scam_rom_size, f);
fclose(f);
f = NULL;
}

View File

@@ -1464,7 +1464,7 @@ ncr53c8xx_eeprom(ncr53c8xx_t *dev, uint8_t save)
if (save)
fwrite(&dev->nvram, sizeof(dev->nvram), 1, f);
else
fread(&dev->nvram, sizeof(dev->nvram), 1, f);
(void) !fread(&dev->nvram, sizeof(dev->nvram), 1, f);
fclose(f);
}
}

View File

@@ -156,7 +156,7 @@ cs423x_nvram(cs423x_t *dev, uint8_t save)
if (save)
fwrite(dev->eeprom_data, sizeof(dev->eeprom_data), 1, f);
else
fread(dev->eeprom_data, sizeof(dev->eeprom_data), 1, f);
(void) !fread(dev->eeprom_data, sizeof(dev->eeprom_data), 1, f);
fclose(f);
}
}

View File

@@ -23,14 +23,7 @@
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/mem.h>
typedef struct {
int aperture_enable;
uint32_t aperture_base, aperture_size, aperture_mask, gart_base;
mem_mapping_t aperture_mapping;
} agpgart_t;
#include <86box/agpgart.h>
#ifdef ENABLE_AGPGART_LOG
int agpgart_do_log = ENABLE_AGPGART_LOG;
@@ -41,51 +34,45 @@ agpgart_log(const char *fmt, ...)
va_list ap;
if (agpgart_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define agpgart_log(fmt, ...)
# define agpgart_log(fmt, ...)
#endif
void
agpgart_set_aperture(void *handle, uint32_t base, uint32_t size, int enable)
agpgart_set_aperture(agpgart_t *dev, uint32_t base, uint32_t size, int enable)
{
agpgart_t *dev = (agpgart_t *) handle;
agpgart_log("AGP GART: set_aperture(%08X, %d, %d)\n", base, size, enable);
/* Disable old aperture mapping. */
mem_mapping_disable(&dev->aperture_mapping);
/* Set new aperture base address, size and mask. */
/* Set new aperture base address, size, mask and enable. */
dev->aperture_base = base;
dev->aperture_size = size;
dev->aperture_mask = size - 1;
dev->aperture_enable = enable;
/* Enable new aperture mapping if requested. */
if (dev->aperture_base && dev->aperture_size && dev->aperture_enable) {
mem_mapping_set_addr(&dev->aperture_mapping, dev->aperture_base, dev->aperture_size);
mem_mapping_enable(&dev->aperture_mapping);
mem_mapping_set_addr(&dev->aperture_mapping, dev->aperture_base, dev->aperture_size);
mem_mapping_enable(&dev->aperture_mapping);
}
}
void
agpgart_set_gart(void *handle, uint32_t base)
agpgart_set_gart(agpgart_t *dev, uint32_t base)
{
agpgart_t *dev = (agpgart_t *) handle;
agpgart_log("AGP GART: set_gart(%08X)\n", base);
/* Set GART base address. */
dev->gart_base = base;
}
static uint32_t
agpgart_translate(uint32_t addr, agpgart_t *dev)
{
@@ -99,7 +86,6 @@ agpgart_translate(uint32_t addr, agpgart_t *dev)
return gart_ptr | (addr & 0x00000fff);
}
static uint8_t
agpgart_aperture_readb(uint32_t addr, void *priv)
{
@@ -107,7 +93,6 @@ agpgart_aperture_readb(uint32_t addr, void *priv)
return mem_readb_phys(agpgart_translate(addr, dev));
}
static uint16_t
agpgart_aperture_readw(uint32_t addr, void *priv)
{
@@ -115,7 +100,6 @@ agpgart_aperture_readw(uint32_t addr, void *priv)
return mem_readw_phys(agpgart_translate(addr, dev));
}
static uint32_t
agpgart_aperture_readl(uint32_t addr, void *priv)
{
@@ -123,7 +107,6 @@ agpgart_aperture_readl(uint32_t addr, void *priv)
return mem_readl_phys(agpgart_translate(addr, dev));
}
static void
agpgart_aperture_writeb(uint32_t addr, uint8_t val, void *priv)
{
@@ -131,7 +114,6 @@ agpgart_aperture_writeb(uint32_t addr, uint8_t val, void *priv)
mem_writeb_phys(agpgart_translate(addr, dev), val);
}
static void
agpgart_aperture_writew(uint32_t addr, uint16_t val, void *priv)
{
@@ -139,7 +121,6 @@ agpgart_aperture_writew(uint32_t addr, uint16_t val, void *priv)
mem_writew_phys(agpgart_translate(addr, dev), val);
}
static void
agpgart_aperture_writel(uint32_t addr, uint32_t val, void *priv)
{
@@ -147,7 +128,6 @@ agpgart_aperture_writel(uint32_t addr, uint32_t val, void *priv)
mem_writel_phys(agpgart_translate(addr, dev), val);
}
static void *
agpgart_init(const device_t *info)
{
@@ -158,14 +138,13 @@ agpgart_init(const device_t *info)
/* Create aperture mapping. */
mem_mapping_add(&dev->aperture_mapping, 0, 0,
agpgart_aperture_readb, agpgart_aperture_readw, agpgart_aperture_readl,
agpgart_aperture_writeb, agpgart_aperture_writew, agpgart_aperture_writel,
NULL, MEM_MAPPING_EXTERNAL, dev);
agpgart_aperture_readb, agpgart_aperture_readw, agpgart_aperture_readl,
agpgart_aperture_writeb, agpgart_aperture_writew, agpgart_aperture_writel,
NULL, MEM_MAPPING_EXTERNAL, dev);
return dev;
}
static void
agpgart_close(void *priv)
{
@@ -180,15 +159,15 @@ agpgart_close(void *priv)
}
const device_t agpgart_device = {
.name = "AGP Graphics Address Remapping Table",
.name = "AGP Graphics Address Remapping Table",
.internal_name = "agpgart",
.flags = DEVICE_PCI,
.local = 0,
.init = agpgart_init,
.close = agpgart_close,
.reset = NULL,
.flags = DEVICE_PCI,
.local = 0,
.init = agpgart_init,
.close = agpgart_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};

File diff suppressed because it is too large Load Diff

View File

@@ -32,296 +32,293 @@
#include <86box/vid_svga.h>
#include <86box/vid_svga_render.h>
#if defined(DEV_BRANCH) && defined(USE_VGAWONDER)
#define BIOS_ROM_PATH_WONDER "roms/video/ati18800/VGA_Wonder_V3-1.02.bin"
# define BIOS_ROM_PATH_WONDER "roms/video/ati18800/VGA_Wonder_V3-1.02.bin"
#endif
#define BIOS_ROM_PATH_VGA88 "roms/video/ati18800/vga88.bin"
#define BIOS_ROM_PATH_EDGE16 "roms/video/ati18800/vgaedge16.vbi"
#define BIOS_ROM_PATH_VGA88 "roms/video/ati18800/vga88.bin"
#define BIOS_ROM_PATH_EDGE16 "roms/video/ati18800/vgaedge16.vbi"
enum {
#if defined(DEV_BRANCH) && defined(USE_VGAWONDER)
ATI18800_WONDER = 0,
ATI18800_VGA88,
ATI18800_EDGE16
ATI18800_WONDER = 0,
ATI18800_VGA88,
ATI18800_EDGE16
#else
ATI18800_VGA88 = 0,
ATI18800_EDGE16
ATI18800_VGA88 = 0,
ATI18800_EDGE16
#endif
};
typedef struct ati18800_t {
svga_t svga;
ati_eeprom_t eeprom;
typedef struct ati18800_t
{
svga_t svga;
ati_eeprom_t eeprom;
rom_t bios_rom;
rom_t bios_rom;
uint8_t regs[256];
int index;
uint8_t regs[256];
int index;
} ati18800_t;
static video_timings_t timing_ati18800 = {VIDEO_ISA, 8, 16, 32, 8, 16, 32};
static video_timings_t timing_ati18800 = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 };
static void ati18800_out(uint16_t addr, uint8_t val, void *p)
static void
ati18800_out(uint16_t addr, uint8_t val, void *p)
{
ati18800_t *ati18800 = (ati18800_t *)p;
svga_t *svga = &ati18800->svga;
uint8_t old;
ati18800_t *ati18800 = (ati18800_t *) p;
svga_t *svga = &ati18800->svga;
uint8_t old;
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
switch (addr)
{
case 0x1ce:
ati18800->index = val;
break;
case 0x1cf:
ati18800->regs[ati18800->index] = val;
switch (ati18800->index)
{
case 0xb0:
svga_recalctimings(svga);
break;
case 0xb2:
case 0xbe:
if (ati18800->regs[0xbe] & 8) /*Read/write bank mode*/
{
svga->read_bank = ((ati18800->regs[0xb2] >> 5) & 7) * 0x10000;
svga->write_bank = ((ati18800->regs[0xb2] >> 1) & 7) * 0x10000;
}
else /*Single bank mode*/
svga->read_bank = svga->write_bank = ((ati18800->regs[0xb2] >> 1) & 7) * 0x10000;
break;
case 0xb3:
ati_eeprom_write(&ati18800->eeprom, val & 8, val & 2, val & 1);
break;
}
break;
switch (addr) {
case 0x1ce:
ati18800->index = val;
break;
case 0x1cf:
ati18800->regs[ati18800->index] = val;
switch (ati18800->index) {
case 0xb0:
svga_recalctimings(svga);
break;
case 0xb2:
case 0xbe:
if (ati18800->regs[0xbe] & 8) /*Read/write bank mode*/
{
svga->read_bank = ((ati18800->regs[0xb2] >> 5) & 7) * 0x10000;
svga->write_bank = ((ati18800->regs[0xb2] >> 1) & 7) * 0x10000;
} else /*Single bank mode*/
svga->read_bank = svga->write_bank = ((ati18800->regs[0xb2] >> 1) & 7) * 0x10000;
break;
case 0xb3:
ati_eeprom_write(&ati18800->eeprom, val & 8, val & 2, val & 1);
break;
}
break;
case 0x3D4:
svga->crtcreg = val & 0x3f;
case 0x3D4:
svga->crtcreg = val & 0x3f;
return;
case 0x3D5:
if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80) && !(ati18800->regs[0xb4] & 0x80))
return;
case 0x3D5:
if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80) && !(ati18800->regs[0xb4] & 0x80))
return;
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80) && !(ati18800->regs[0xb4] & 0x80))
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
old = svga->crtc[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
if (old != val)
{
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
{
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
}
}
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80) && !(ati18800->regs[0xb4] & 0x80))
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
old = svga->crtc[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
if (old != val) {
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
}
}
break;
}
svga_out(addr, val, svga);
}
break;
}
svga_out(addr, val, svga);
}
static uint8_t ati18800_in(uint16_t addr, void *p)
static uint8_t
ati18800_in(uint16_t addr, void *p)
{
ati18800_t *ati18800 = (ati18800_t *)p;
svga_t *svga = &ati18800->svga;
uint8_t temp = 0xff;
ati18800_t *ati18800 = (ati18800_t *) p;
svga_t *svga = &ati18800->svga;
uint8_t temp = 0xff;
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) addr ^= 0x60;
if (((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && !(svga->miscout & 1))
addr ^= 0x60;
switch (addr)
{
case 0x1ce:
temp = ati18800->index;
break;
case 0x1cf:
switch (ati18800->index)
{
case 0xb7:
temp = ati18800->regs[ati18800->index] & ~8;
if (ati_eeprom_read(&ati18800->eeprom))
temp |= 8;
break;
default:
temp = ati18800->regs[ati18800->index];
break;
}
break;
case 0x3D4:
temp = svga->crtcreg;
break;
case 0x3D5:
temp = svga->crtc[svga->crtcreg];
break;
switch (addr) {
case 0x1ce:
temp = ati18800->index;
break;
case 0x1cf:
switch (ati18800->index) {
case 0xb7:
temp = ati18800->regs[ati18800->index] & ~8;
if (ati_eeprom_read(&ati18800->eeprom))
temp |= 8;
break;
default:
temp = svga_in(addr, svga);
break;
}
return temp;
temp = ati18800->regs[ati18800->index];
break;
}
break;
case 0x3D4:
temp = svga->crtcreg;
break;
case 0x3D5:
temp = svga->crtc[svga->crtcreg];
break;
default:
temp = svga_in(addr, svga);
break;
}
return temp;
}
static void ati18800_recalctimings(svga_t *svga)
static void
ati18800_recalctimings(svga_t *svga)
{
ati18800_t *ati18800 = (ati18800_t *)svga->p;
ati18800_t *ati18800 = (ati18800_t *) svga->p;
if(svga->crtc[0x17] & 4)
{
svga->vtotal <<= 1;
svga->dispend <<= 1;
svga->vsyncstart <<= 1;
svga->split <<= 1;
svga->vblankstart <<= 1;
}
if (svga->crtc[0x17] & 4) {
svga->vtotal <<= 1;
svga->dispend <<= 1;
svga->vsyncstart <<= 1;
svga->split <<= 1;
svga->vblankstart <<= 1;
}
if (!svga->scrblank && ((ati18800->regs[0xb0] & 0x02) || (ati18800->regs[0xb0] & 0x04))) /*Extended 256 colour modes*/
{
svga->render = svga_render_8bpp_highres;
svga->bpp = 8;
svga->rowoffset <<= 1;
svga->ma <<= 1;
}
if (!svga->scrblank && ((ati18800->regs[0xb0] & 0x02) || (ati18800->regs[0xb0] & 0x04))) /*Extended 256 colour modes*/
{
svga->render = svga_render_8bpp_highres;
svga->bpp = 8;
svga->rowoffset <<= 1;
svga->ma <<= 1;
}
}
static void *ati18800_init(const device_t *info)
static void *
ati18800_init(const device_t *info)
{
ati18800_t *ati18800 = malloc(sizeof(ati18800_t));
memset(ati18800, 0, sizeof(ati18800_t));
ati18800_t *ati18800 = malloc(sizeof(ati18800_t));
memset(ati18800, 0, sizeof(ati18800_t));
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ati18800);
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ati18800);
switch (info->local) {
switch (info->local) {
#if defined(DEV_BRANCH) && defined(USE_VGAWONDER)
case ATI18800_WONDER:
case ATI18800_WONDER:
#endif
default:
default:
#if defined(DEV_BRANCH) && defined(USE_VGAWONDER)
rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_WONDER, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
break;
rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_WONDER, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
break;
#endif
case ATI18800_VGA88:
rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_VGA88, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
break;
case ATI18800_EDGE16:
rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_EDGE16, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
break;
};
case ATI18800_VGA88:
rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_VGA88, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
break;
case ATI18800_EDGE16:
rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_EDGE16, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
break;
};
if (info->local == ATI18800_EDGE16) {
svga_init(info, &ati18800->svga, ati18800, 1 << 18, /*256kb*/
ati18800_recalctimings,
ati18800_in, ati18800_out,
NULL,
NULL);
} else {
svga_init(info, &ati18800->svga, ati18800, 1 << 19, /*512kb*/
ati18800_recalctimings,
ati18800_in, ati18800_out,
NULL,
NULL);
}
if (info->local == ATI18800_EDGE16) {
svga_init(info, &ati18800->svga, ati18800, 1 << 18, /*256kb*/
ati18800_recalctimings,
ati18800_in, ati18800_out,
NULL,
NULL);
} else {
svga_init(info, &ati18800->svga, ati18800, 1 << 19, /*512kb*/
ati18800_recalctimings,
ati18800_in, ati18800_out,
NULL,
NULL);
}
io_sethandler(0x01ce, 0x0002, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800);
io_sethandler(0x03c0, 0x0020, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800);
io_sethandler(0x01ce, 0x0002, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800);
io_sethandler(0x03c0, 0x0020, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800);
ati18800->svga.miscout = 1;
ati18800->svga.miscout = 1;
ati_eeprom_load(&ati18800->eeprom, "ati18800.nvr", 0);
ati_eeprom_load(&ati18800->eeprom, "ati18800.nvr", 0);
return ati18800;
return ati18800;
}
#if defined(DEV_BRANCH) && defined(USE_VGAWONDER)
static int ati18800_wonder_available(void)
static int
ati18800_wonder_available(void)
{
return rom_present(BIOS_ROM_PATH_WONDER);
return rom_present(BIOS_ROM_PATH_WONDER);
}
#endif
static int ati18800_vga88_available(void)
static int
ati18800_vga88_available(void)
{
return rom_present(BIOS_ROM_PATH_VGA88);
return rom_present(BIOS_ROM_PATH_VGA88);
}
static int ati18800_available(void)
static int
ati18800_available(void)
{
return rom_present(BIOS_ROM_PATH_EDGE16);
return rom_present(BIOS_ROM_PATH_EDGE16);
}
static void ati18800_close(void *p)
static void
ati18800_close(void *p)
{
ati18800_t *ati18800 = (ati18800_t *)p;
ati18800_t *ati18800 = (ati18800_t *) p;
svga_close(&ati18800->svga);
svga_close(&ati18800->svga);
free(ati18800);
free(ati18800);
}
static void ati18800_speed_changed(void *p)
static void
ati18800_speed_changed(void *p)
{
ati18800_t *ati18800 = (ati18800_t *)p;
ati18800_t *ati18800 = (ati18800_t *) p;
svga_recalctimings(&ati18800->svga);
svga_recalctimings(&ati18800->svga);
}
static void ati18800_force_redraw(void *p)
static void
ati18800_force_redraw(void *p)
{
ati18800_t *ati18800 = (ati18800_t *)p;
ati18800_t *ati18800 = (ati18800_t *) p;
ati18800->svga.fullchange = changeframecount;
ati18800->svga.fullchange = changeframecount;
}
#if defined(DEV_BRANCH) && defined(USE_VGAWONDER)
const device_t ati18800_wonder_device = {
.name = "ATI-18800",
.name = "ATI-18800",
.internal_name = "ati18800w",
.flags = DEVICE_ISA,
.local = ATI18800_WONDER,
.init = ati18800_init,
.close = ati18800_close,
.reset = NULL,
.flags = DEVICE_ISA,
.local = ATI18800_WONDER,
.init = ati18800_init,
.close = ati18800_close,
.reset = NULL,
{ .available = ati18800_wonder_available },
.speed_changed = ati18800_speed_changed,
.force_redraw = ati18800_force_redraw,
.config = NULL
.force_redraw = ati18800_force_redraw,
.config = NULL
};
#endif
const device_t ati18800_vga88_device =
{
.name = "ATI-18800-1",
const device_t ati18800_vga88_device = {
.name = "ATI-18800-1",
.internal_name = "ati18800v",
.flags = DEVICE_ISA,
.local = ATI18800_VGA88,
.init = ati18800_init,
.close = ati18800_close,
.reset = NULL,
.flags = DEVICE_ISA,
.local = ATI18800_VGA88,
.init = ati18800_init,
.close = ati18800_close,
.reset = NULL,
{ .available = ati18800_vga88_available },
.speed_changed = ati18800_speed_changed,
.force_redraw = ati18800_force_redraw,
.config = NULL
.force_redraw = ati18800_force_redraw,
.config = NULL
};
const device_t ati18800_device =
{
.name = "ATI-18800-5",
const device_t ati18800_device = {
.name = "ATI-18800-5",
.internal_name = "ati18800",
.flags = DEVICE_ISA,
.local = ATI18800_EDGE16,
.init = ati18800_init,
.close = ati18800_close,
.reset = NULL,
.flags = DEVICE_ISA,
.local = ATI18800_EDGE16,
.init = ati18800_init,
.close = ati18800_close,
.reset = NULL,
{ .available = ati18800_available },
.speed_changed = ati18800_speed_changed,
.force_redraw = ati18800_force_redraw,
.config = NULL
.force_redraw = ati18800_force_redraw,
.config = NULL
};

File diff suppressed because it is too large Load Diff

View File

@@ -49,111 +49,112 @@
#include <86box/vid_svga.h>
#include <86box/vid_svga_render.h>
typedef struct ati68860_ramdac_t
{
typedef struct ati68860_ramdac_t {
uint8_t regs[16];
void (*render)(struct svga_t *svga);
int dac_addr, dac_pos;
int dac_r, dac_g;
PALETTE pal;
int dac_addr, dac_pos;
int dac_r, dac_g;
PALETTE pal;
uint32_t pallook[2];
int ramdac_type;
} ati68860_ramdac_t;
void
ati68860_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga)
{
ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) p;
switch (addr) {
case 0:
svga_out(0x3c8, val, svga);
break;
case 1:
svga_out(0x3c9, val, svga);
break;
case 2:
svga_out(0x3c6, val, svga);
break;
case 3:
svga_out(0x3c7, val, svga);
break;
default:
ramdac->regs[addr & 0xf] = val;
switch (addr & 0xf) {
case 0x4:
ramdac->dac_addr = val;
ramdac->dac_pos = 0;
break;
case 0x5:
switch (ramdac->dac_pos) {
case 0:
ramdac->dac_r = val;
ramdac->dac_pos++;
break;
case 1:
ramdac->dac_g = val;
ramdac->dac_pos++;
break;
case 2:
if (ramdac->dac_addr > 1)
break;
ramdac->pal[ramdac->dac_addr].r = ramdac->dac_r;
ramdac->pal[ramdac->dac_addr].g = ramdac->dac_g;
ramdac->pal[ramdac->dac_addr].b = val;
if (ramdac->ramdac_type == RAMDAC_8BIT)
ramdac->pallook[ramdac->dac_addr] = makecol32(ramdac->pal[ramdac->dac_addr].r,
ramdac->pal[ramdac->dac_addr].g,
ramdac->pal[ramdac->dac_addr].b);
else
ramdac->pallook[ramdac->dac_addr] = makecol32(video_6to8[ramdac->pal[ramdac->dac_addr].r & 0x3f],
video_6to8[ramdac->pal[ramdac->dac_addr].g & 0x3f],
video_6to8[ramdac->pal[ramdac->dac_addr].b & 0x3f]);
ramdac->dac_pos = 0;
ramdac->dac_addr = (ramdac->dac_addr + 1) & 255;
break;
}
break;
case 0xb:
switch (val) {
case 0x82:
ramdac->render = svga_render_4bpp_highres;
break;
case 0x83:
ramdac->render = svga_render_8bpp_highres;
break;
case 0xa0: case 0xb0:
ramdac->render = svga_render_15bpp_highres;
break;
case 0xa1: case 0xb1:
ramdac->render = svga_render_16bpp_highres;
break;
case 0xc0: case 0xd0:
ramdac->render = svga_render_24bpp_highres;
break;
case 0xe2: case 0xf7:
ramdac->render = svga_render_32bpp_highres;
break;
case 0xe3:
ramdac->render = svga_render_ABGR8888_highres;
break;
case 0xf2:
ramdac->render = svga_render_RGBA8888_highres;
break;
default:
ramdac->render = svga_render_8bpp_highres;
break;
}
break;
case 0xc:
svga_set_ramdac_type(svga, (val & 1) ? RAMDAC_6BIT : RAMDAC_8BIT);
break;
}
break;
case 0:
svga_out(0x3c8, val, svga);
break;
case 1:
svga_out(0x3c9, val, svga);
break;
case 2:
svga_out(0x3c6, val, svga);
break;
case 3:
svga_out(0x3c7, val, svga);
break;
default:
ramdac->regs[addr & 0xf] = val;
switch (addr & 0xf) {
case 0x4:
ramdac->dac_addr = val;
ramdac->dac_pos = 0;
break;
case 0x5:
switch (ramdac->dac_pos) {
case 0:
ramdac->dac_r = val;
ramdac->dac_pos++;
break;
case 1:
ramdac->dac_g = val;
ramdac->dac_pos++;
break;
case 2:
if (ramdac->dac_addr > 1)
break;
ramdac->pal[ramdac->dac_addr].r = ramdac->dac_r;
ramdac->pal[ramdac->dac_addr].g = ramdac->dac_g;
ramdac->pal[ramdac->dac_addr].b = val;
if (ramdac->ramdac_type == RAMDAC_8BIT)
ramdac->pallook[ramdac->dac_addr] = makecol32(ramdac->pal[ramdac->dac_addr].r,
ramdac->pal[ramdac->dac_addr].g,
ramdac->pal[ramdac->dac_addr].b);
else
ramdac->pallook[ramdac->dac_addr] = makecol32(video_6to8[ramdac->pal[ramdac->dac_addr].r & 0x3f],
video_6to8[ramdac->pal[ramdac->dac_addr].g & 0x3f],
video_6to8[ramdac->pal[ramdac->dac_addr].b & 0x3f]);
ramdac->dac_pos = 0;
ramdac->dac_addr = (ramdac->dac_addr + 1) & 255;
break;
}
break;
case 0xb:
switch (val) {
case 0x82:
ramdac->render = svga_render_4bpp_highres;
break;
case 0x83:
ramdac->render = svga_render_8bpp_highres;
break;
case 0xa0:
case 0xb0:
ramdac->render = svga_render_15bpp_highres;
break;
case 0xa1:
case 0xb1:
ramdac->render = svga_render_16bpp_highres;
break;
case 0xc0:
case 0xd0:
ramdac->render = svga_render_24bpp_highres;
break;
case 0xe2:
case 0xf7:
ramdac->render = svga_render_32bpp_highres;
break;
case 0xe3:
ramdac->render = svga_render_ABGR8888_highres;
break;
case 0xf2:
ramdac->render = svga_render_RGBA8888_highres;
break;
default:
ramdac->render = svga_render_8bpp_highres;
break;
}
break;
case 0xc:
svga_set_ramdac_type(svga, (val & 1) ? RAMDAC_6BIT : RAMDAC_8BIT);
break;
}
break;
}
}
@@ -161,61 +162,61 @@ uint8_t
ati68860_ramdac_in(uint16_t addr, void *p, svga_t *svga)
{
ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) p;
uint8_t temp = 0;
uint8_t temp = 0;
switch (addr) {
case 0:
temp = svga_in(0x3c8, svga);
break;
case 1:
temp = svga_in(0x3c9, svga);
break;
case 2:
temp = svga_in(0x3c6, svga);
break;
case 3:
temp = svga_in(0x3c7, svga);
break;
case 4: case 8:
temp = 2;
break;
case 6: case 0xa:
temp = 0x1d;
break;
case 0xf:
temp = 0xd0;
break;
case 0:
temp = svga_in(0x3c8, svga);
break;
case 1:
temp = svga_in(0x3c9, svga);
break;
case 2:
temp = svga_in(0x3c6, svga);
break;
case 3:
temp = svga_in(0x3c7, svga);
break;
case 4:
case 8:
temp = 2;
break;
case 6:
case 0xa:
temp = 0x1d;
break;
case 0xf:
temp = 0xd0;
break;
default:
temp = ramdac->regs[addr & 0xf];
break;
default:
temp = ramdac->regs[addr & 0xf];
break;
}
return temp;
}
void
ati68860_set_ramdac_type(void *p, int type)
{
ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) p;
int c;
int c;
if (ramdac->ramdac_type != type) {
ramdac->ramdac_type = type;
ramdac->ramdac_type = type;
for (c = 0; c < 2; c++) {
if (ramdac->ramdac_type == RAMDAC_8BIT)
ramdac->pallook[c] = makecol32(ramdac->pal[c].r, ramdac->pal[c].g,
ramdac->pal[c].b);
else
ramdac->pallook[c] = makecol32(video_6to8[ramdac->pal[c].r & 0x3f], video_6to8[ramdac->pal[c].g & 0x3f],
video_6to8[ramdac->pal[c].b & 0x3f]);
}
for (c = 0; c < 2; c++) {
if (ramdac->ramdac_type == RAMDAC_8BIT)
ramdac->pallook[c] = makecol32(ramdac->pal[c].r, ramdac->pal[c].g,
ramdac->pal[c].b);
else
ramdac->pallook[c] = makecol32(video_6to8[ramdac->pal[c].r & 0x3f], video_6to8[ramdac->pal[c].g & 0x3f],
video_6to8[ramdac->pal[c].b & 0x3f]);
}
}
}
static void *
ati68860_ramdac_init(const device_t *info)
{
@@ -227,7 +228,6 @@ ati68860_ramdac_init(const device_t *info)
return ramdac;
}
void
ati68860_ramdac_set_render(void *p, svga_t *svga)
{
@@ -236,7 +236,6 @@ ati68860_ramdac_set_render(void *p, svga_t *svga)
svga->render = ramdac->render;
}
void
ati68860_ramdac_set_pallook(void *p, int i, uint32_t col)
{
@@ -245,57 +244,63 @@ ati68860_ramdac_set_pallook(void *p, int i, uint32_t col)
ramdac->pallook[i] = col;
}
void
ati68860_hwcursor_draw(svga_t *svga, int displine)
{
ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) svga->ramdac;
int x, offset;
uint8_t dat;
uint32_t col0 = ramdac->pallook[0];
uint32_t col1 = ramdac->pallook[1];
int x, offset;
uint8_t dat;
uint32_t col0 = ramdac->pallook[0];
uint32_t col1 = ramdac->pallook[1];
offset = svga->dac_hwcursor_latch.xoff;
for (x = 0; x < 64 - svga->dac_hwcursor_latch.xoff; x += 4) {
dat = svga->vram[svga->dac_hwcursor_latch.addr + (offset >> 2)];
if (!(dat & 2)) buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add] = (dat & 1) ? col1 : col0;
else if ((dat & 3) == 3) buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add] ^= 0xFFFFFF;
dat >>= 2;
if (!(dat & 2)) buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 1] = (dat & 1) ? col1 : col0;
else if ((dat & 3) == 3) buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 1] ^= 0xFFFFFF;
dat >>= 2;
if (!(dat & 2)) buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 2] = (dat & 1) ? col1 : col0;
else if ((dat & 3) == 3) buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 2] ^= 0xFFFFFF;
dat >>= 2;
if (!(dat & 2)) buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 3] = (dat & 1) ? col1 : col0;
else if ((dat & 3) == 3) buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 3] ^= 0xFFFFFF;
dat >>= 2;
offset += 4;
dat = svga->vram[svga->dac_hwcursor_latch.addr + (offset >> 2)];
if (!(dat & 2))
buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add] = (dat & 1) ? col1 : col0;
else if ((dat & 3) == 3)
buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add] ^= 0xFFFFFF;
dat >>= 2;
if (!(dat & 2))
buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 1] = (dat & 1) ? col1 : col0;
else if ((dat & 3) == 3)
buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 1] ^= 0xFFFFFF;
dat >>= 2;
if (!(dat & 2))
buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 2] = (dat & 1) ? col1 : col0;
else if ((dat & 3) == 3)
buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 2] ^= 0xFFFFFF;
dat >>= 2;
if (!(dat & 2))
buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 3] = (dat & 1) ? col1 : col0;
else if ((dat & 3) == 3)
buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 3] ^= 0xFFFFFF;
dat >>= 2;
offset += 4;
}
svga->dac_hwcursor_latch.addr += 16;
}
static void
ati68860_ramdac_close(void *priv)
{
ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) priv;
if (ramdac)
free(ramdac);
free(ramdac);
}
const device_t ati68860_ramdac_device = {
.name = "ATI-68860 RAMDAC",
.name = "ATI-68860 RAMDAC",
.internal_name = "ati68860_ramdac",
.flags = 0,
.local = 0,
.init = ati68860_ramdac_init,
.close = ati68860_ramdac_close,
.reset = NULL,
.flags = 0,
.local = 0,
.init = ati68860_ramdac_init,
.close = ati68860_ramdac_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};

View File

@@ -27,184 +27,168 @@
#include <86box/nvr.h>
#include <86box/vid_ati_eeprom.h>
void ati_eeprom_load(ati_eeprom_t *eeprom, char *fn, int type)
void
ati_eeprom_load(ati_eeprom_t *eeprom, char *fn, int type)
{
FILE *f;
int size;
eeprom->type = type;
strncpy(eeprom->fn, fn, sizeof(eeprom->fn) - 1);
f = nvr_fopen(eeprom->fn, "rb");
size = eeprom->type ? 512 : 128;
if (!f) {
memset(eeprom->data, 0xff, size);
return;
}
if (fread(eeprom->data, 1, size, f) != size)
memset(eeprom->data, 0, size);
fclose(f);
FILE *f;
int size;
eeprom->type = type;
strncpy(eeprom->fn, fn, sizeof(eeprom->fn) - 1);
f = nvr_fopen(eeprom->fn, "rb");
size = eeprom->type ? 512 : 128;
if (!f) {
memset(eeprom->data, 0xff, size);
return;
}
if (fread(eeprom->data, 1, size, f) != size)
memset(eeprom->data, 0, size);
fclose(f);
}
void ati_eeprom_save(ati_eeprom_t *eeprom)
void
ati_eeprom_save(ati_eeprom_t *eeprom)
{
FILE *f = nvr_fopen(eeprom->fn, "wb");
if (!f) return;
fwrite(eeprom->data, 1, eeprom->type ? 512 : 128, f);
fclose(f);
FILE *f = nvr_fopen(eeprom->fn, "wb");
if (!f)
return;
fwrite(eeprom->data, 1, eeprom->type ? 512 : 128, f);
fclose(f);
}
void ati_eeprom_write(ati_eeprom_t *eeprom, int ena, int clk, int dat)
void
ati_eeprom_write(ati_eeprom_t *eeprom, int ena, int clk, int dat)
{
int c;
if (!ena)
{
eeprom->out = 1;
}
if (clk && !eeprom->oldclk)
{
if (ena && !eeprom->oldena)
{
eeprom->state = EEPROM_WAIT;
eeprom->opcode = 0;
eeprom->count = 3;
eeprom->out = 1;
}
else if (ena)
{
switch (eeprom->state)
{
case EEPROM_WAIT:
if (!dat)
int c;
if (!ena) {
eeprom->out = 1;
}
if (clk && !eeprom->oldclk) {
if (ena && !eeprom->oldena) {
eeprom->state = EEPROM_WAIT;
eeprom->opcode = 0;
eeprom->count = 3;
eeprom->out = 1;
} else if (ena) {
switch (eeprom->state) {
case EEPROM_WAIT:
if (!dat)
break;
eeprom->state = EEPROM_OPCODE;
/* fall through */
case EEPROM_OPCODE:
eeprom->opcode = (eeprom->opcode << 1) | (dat ? 1 : 0);
eeprom->count--;
if (!eeprom->count) {
switch (eeprom->opcode) {
case EEPROM_OP_WRITE:
eeprom->count = eeprom->type ? 24 : 22;
eeprom->state = EEPROM_INPUT;
eeprom->dat = 0;
break;
case EEPROM_OP_READ:
eeprom->count = eeprom->type ? 8 : 6;
eeprom->state = EEPROM_INPUT;
eeprom->dat = 0;
break;
case EEPROM_OP_EW:
eeprom->count = 2;
eeprom->state = EEPROM_INPUT;
eeprom->dat = 0;
break;
case EEPROM_OP_ERASE:
eeprom->count = eeprom->type ? 8 : 6;
eeprom->state = EEPROM_INPUT;
eeprom->dat = 0;
break;
}
}
break;
case EEPROM_INPUT:
eeprom->dat = (eeprom->dat << 1) | (dat ? 1 : 0);
eeprom->count--;
if (!eeprom->count) {
switch (eeprom->opcode) {
case EEPROM_OP_WRITE:
if (!eeprom->wp) {
eeprom->data[(eeprom->dat >> 16) & (eeprom->type ? 255 : 63)] = eeprom->dat & 0xffff;
ati_eeprom_save(eeprom);
}
eeprom->state = EEPROM_IDLE;
eeprom->out = 1;
break;
case EEPROM_OP_READ:
eeprom->count = 17;
eeprom->state = EEPROM_OUTPUT;
eeprom->dat = eeprom->data[eeprom->dat];
break;
case EEPROM_OP_EW:
switch (eeprom->dat) {
case EEPROM_OP_EWDS:
eeprom->wp = 1;
break;
eeprom->state = EEPROM_OPCODE;
/* fall through */
case EEPROM_OPCODE:
eeprom->opcode = (eeprom->opcode << 1) | (dat ? 1 : 0);
eeprom->count--;
if (!eeprom->count)
{
switch (eeprom->opcode)
{
case EEPROM_OP_WRITE:
eeprom->count = eeprom->type ? 24 : 22;
eeprom->state = EEPROM_INPUT;
eeprom->dat = 0;
break;
case EEPROM_OP_READ:
eeprom->count = eeprom->type ? 8 : 6;
eeprom->state = EEPROM_INPUT;
eeprom->dat = 0;
break;
case EEPROM_OP_EW:
eeprom->count = 2;
eeprom->state = EEPROM_INPUT;
eeprom->dat = 0;
break;
case EEPROM_OP_ERASE:
eeprom->count = eeprom->type ? 8 : 6;
eeprom->state = EEPROM_INPUT;
eeprom->dat = 0;
break;
case EEPROM_OP_WRAL:
eeprom->opcode = EEPROM_OP_WRALMAIN;
eeprom->count = 20;
break;
case EEPROM_OP_ERAL:
if (!eeprom->wp) {
memset(eeprom->data, 0xff, 128);
ati_eeprom_save(eeprom);
}
break;
case EEPROM_OP_EWEN:
eeprom->wp = 0;
break;
}
eeprom->state = EEPROM_IDLE;
eeprom->out = 1;
break;
case EEPROM_INPUT:
eeprom->dat = (eeprom->dat << 1) | (dat ? 1 : 0);
eeprom->count--;
if (!eeprom->count)
{
switch (eeprom->opcode)
{
case EEPROM_OP_WRITE:
if (!eeprom->wp)
{
eeprom->data[(eeprom->dat >> 16) & (eeprom->type ? 255 : 63)] = eeprom->dat & 0xffff;
ati_eeprom_save(eeprom);
}
eeprom->state = EEPROM_IDLE;
eeprom->out = 1;
break;
case EEPROM_OP_READ:
eeprom->count = 17;
eeprom->state = EEPROM_OUTPUT;
eeprom->dat = eeprom->data[eeprom->dat];
break;
case EEPROM_OP_EW:
switch (eeprom->dat)
{
case EEPROM_OP_EWDS:
eeprom->wp = 1;
break;
case EEPROM_OP_WRAL:
eeprom->opcode = EEPROM_OP_WRALMAIN;
eeprom->count = 20;
break;
case EEPROM_OP_ERAL:
if (!eeprom->wp)
{
memset(eeprom->data, 0xff, 128);
ati_eeprom_save(eeprom);
}
break;
case EEPROM_OP_EWEN:
eeprom->wp = 0;
break;
}
eeprom->state = EEPROM_IDLE;
eeprom->out = 1;
break;
case EEPROM_OP_ERASE:
if (!eeprom->wp)
{
eeprom->data[eeprom->dat] = 0xffff;
ati_eeprom_save(eeprom);
}
eeprom->state = EEPROM_IDLE;
eeprom->out = 1;
break;
case EEPROM_OP_WRALMAIN:
if (!eeprom->wp)
{
for (c = 0; c < 256; c++)
eeprom->data[c] = eeprom->dat;
ati_eeprom_save(eeprom);
}
eeprom->state = EEPROM_IDLE;
eeprom->out = 1;
break;
}
case EEPROM_OP_ERASE:
if (!eeprom->wp) {
eeprom->data[eeprom->dat] = 0xffff;
ati_eeprom_save(eeprom);
}
eeprom->state = EEPROM_IDLE;
eeprom->out = 1;
break;
case EEPROM_OP_WRALMAIN:
if (!eeprom->wp) {
for (c = 0; c < 256; c++)
eeprom->data[c] = eeprom->dat;
ati_eeprom_save(eeprom);
}
eeprom->state = EEPROM_IDLE;
eeprom->out = 1;
break;
}
}
eeprom->oldena = ena;
}
break;
}
}
else if (!clk && eeprom->oldclk)
{
if (ena)
{
switch (eeprom->state)
{
case EEPROM_OUTPUT:
eeprom->out = (eeprom->dat & 0x10000) ? 1 : 0;
eeprom->dat <<= 1;
eeprom->count--;
if (!eeprom->count)
{
eeprom->state = EEPROM_IDLE;
}
break;
}
}
eeprom->oldena = ena;
} else if (!clk && eeprom->oldclk) {
if (ena) {
switch (eeprom->state) {
case EEPROM_OUTPUT:
eeprom->out = (eeprom->dat & 0x10000) ? 1 : 0;
eeprom->dat <<= 1;
eeprom->count--;
if (!eeprom->count) {
eeprom->state = EEPROM_IDLE;
}
break;
}
}
eeprom->oldclk = clk;
}
eeprom->oldclk = clk;
}
int ati_eeprom_read(ati_eeprom_t *eeprom)
int
ati_eeprom_read(ati_eeprom_t *eeprom)
{
return eeprom->out;
return eeprom->out;
}

File diff suppressed because it is too large Load Diff

View File

@@ -28,131 +28,126 @@
#include <86box/video.h>
#include <86box/vid_svga.h>
typedef struct
{
int type;
int state;
int type;
int state;
uint8_t ctrl;
} att49x_ramdac_t;
enum
{
ATT_490 = 0,
ATT_491,
ATT_492
enum {
ATT_490 = 0,
ATT_491,
ATT_492
};
static void
att49x_ramdac_control(uint8_t val, void *p, svga_t *svga)
{
att49x_ramdac_t *ramdac = (att49x_ramdac_t *) p;
ramdac->ctrl = val;
switch ((ramdac->ctrl >> 5) & 7) {
case 0:
case 1:
case 2:
case 3:
svga->bpp = 8;
break;
case 4:
case 5:
svga->bpp = 15;
break;
case 6:
svga->bpp = 16;
break;
case 7:
svga->bpp = 24;
break;
}
if (ramdac->type == ATT_490 || ramdac->type == ATT_491)
svga_set_ramdac_type(svga, (val & 2) ? RAMDAC_8BIT : RAMDAC_6BIT);
svga_recalctimings(svga);
att49x_ramdac_t *ramdac = (att49x_ramdac_t *) p;
ramdac->ctrl = val;
switch ((ramdac->ctrl >> 5) & 7) {
case 0:
case 1:
case 2:
case 3:
svga->bpp = 8;
break;
case 4:
case 5:
svga->bpp = 15;
break;
case 6:
svga->bpp = 16;
break;
case 7:
svga->bpp = 24;
break;
}
if (ramdac->type == ATT_490 || ramdac->type == ATT_491)
svga_set_ramdac_type(svga, (val & 2) ? RAMDAC_8BIT : RAMDAC_6BIT);
svga_recalctimings(svga);
}
void
att49x_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga)
{
att49x_ramdac_t *ramdac = (att49x_ramdac_t *) p;
uint8_t rs = (addr & 0x03);
uint8_t rs = (addr & 0x03);
rs |= ((!!rs2) << 2);
switch (rs) {
case 0x00:
case 0x01:
case 0x03:
case 0x04:
case 0x05:
case 0x07:
svga_out(addr, val, svga);
ramdac->state = 0;
break;
case 0x02:
switch (ramdac->state) {
case 4:
att49x_ramdac_control(val, ramdac, svga);
break;
default:
svga_out(addr, val, svga);
break;
}
break;
case 0x06:
att49x_ramdac_control(val, ramdac, svga);
ramdac->state = 0;
break;
case 0x00:
case 0x01:
case 0x03:
case 0x04:
case 0x05:
case 0x07:
svga_out(addr, val, svga);
ramdac->state = 0;
break;
case 0x02:
switch (ramdac->state) {
case 4:
att49x_ramdac_control(val, ramdac, svga);
break;
default:
svga_out(addr, val, svga);
break;
}
break;
case 0x06:
att49x_ramdac_control(val, ramdac, svga);
ramdac->state = 0;
break;
}
}
uint8_t
att49x_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga)
{
att49x_ramdac_t *ramdac = (att49x_ramdac_t *) p;
uint8_t temp = 0xff;
uint8_t rs = (addr & 0x03);
uint8_t temp = 0xff;
uint8_t rs = (addr & 0x03);
rs |= ((!!rs2) << 2);
switch (rs) {
case 0x00:
case 0x01:
case 0x03:
case 0x04:
case 0x05:
case 0x07:
temp = svga_in(addr, svga);
ramdac->state = 0;
break;
case 0x02:
switch (ramdac->state) {
case 1:
case 2: case 3:
temp = 0x00;
ramdac->state++;
break;
case 4:
temp = ramdac->ctrl;
ramdac->state = 0;
break;
default:
temp = svga_in(addr, svga);
ramdac->state++;
break;
}
break;
case 0x06:
temp = ramdac->ctrl;
ramdac->state = 0;
break;
case 0x00:
case 0x01:
case 0x03:
case 0x04:
case 0x05:
case 0x07:
temp = svga_in(addr, svga);
ramdac->state = 0;
break;
case 0x02:
switch (ramdac->state) {
case 1:
case 2:
case 3:
temp = 0x00;
ramdac->state++;
break;
case 4:
temp = ramdac->ctrl;
ramdac->state = 0;
break;
default:
temp = svga_in(addr, svga);
ramdac->state++;
break;
}
break;
case 0x06:
temp = ramdac->ctrl;
ramdac->state = 0;
break;
}
return temp;
}
static void *
att49x_ramdac_init(const device_t *info)
{
@@ -164,54 +159,53 @@ att49x_ramdac_init(const device_t *info)
return ramdac;
}
static void
att49x_ramdac_close(void *priv)
{
att49x_ramdac_t *ramdac = (att49x_ramdac_t *) priv;
if (ramdac)
free(ramdac);
free(ramdac);
}
const device_t att490_ramdac_device = {
.name = "AT&T 20c490 RAMDAC",
.name = "AT&T 20c490 RAMDAC",
.internal_name = "att490_ramdac",
.flags = 0,
.local = ATT_490,
.init = att49x_ramdac_init,
.close = att49x_ramdac_close,
.reset = NULL,
.flags = 0,
.local = ATT_490,
.init = att49x_ramdac_init,
.close = att49x_ramdac_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
const device_t att491_ramdac_device = {
.name = "AT&T 20c491 RAMDAC",
.name = "AT&T 20c491 RAMDAC",
.internal_name = "att491_ramdac",
.flags = 0,
.local = ATT_491,
.init = att49x_ramdac_init,
.close = att49x_ramdac_close,
.reset = NULL,
.flags = 0,
.local = ATT_491,
.init = att49x_ramdac_init,
.close = att49x_ramdac_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
const device_t att492_ramdac_device = {
.name = "AT&T 20c492 RAMDAC",
.name = "AT&T 20c492 RAMDAC",
.internal_name = "att492_ramdac",
.flags = 0,
.local = ATT_492,
.init = att49x_ramdac_init,
.close = att49x_ramdac_close,
.reset = NULL,
.flags = 0,
.local = ATT_492,
.init = att49x_ramdac_init,
.close = att49x_ramdac_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};

View File

@@ -28,133 +28,130 @@
#include <86box/video.h>
#include <86box/vid_svga.h>
typedef struct
{
int type;
int state;
int loop;
int type;
int state;
int loop;
uint8_t ctrl;
} att498_ramdac_t;
static void
att498_ramdac_control(uint8_t val, void *p, svga_t *svga)
{
att498_ramdac_t *ramdac = (att498_ramdac_t *) p;
ramdac->ctrl = val;
att498_ramdac_t *ramdac = (att498_ramdac_t *) p;
ramdac->ctrl = val;
if (val == 0xff)
return;
if (val == 0xff)
return;
switch ((ramdac->ctrl >> 4) & 0x0f) {
default:
svga->bpp = 8;
break;
case 1:
if (ramdac->ctrl & 4)
svga->bpp = 15;
else
svga->bpp = 8;
break;
case 3:
case 6:
svga->bpp = 16;
break;
case 5:
case 7:
svga->bpp = 32;
break;
case 0x0e:
svga->bpp = 24;
break;
}
switch ((ramdac->ctrl >> 4) & 0x0f) {
default:
svga->bpp = 8;
break;
case 1:
if (ramdac->ctrl & 4)
svga->bpp = 15;
else
svga->bpp = 8;
break;
case 3:
case 6:
svga->bpp = 16;
break;
case 5:
case 7:
svga->bpp = 32;
break;
case 0x0e:
svga->bpp = 24;
break;
}
svga_set_ramdac_type(svga, (ramdac->ctrl & 2) ? RAMDAC_8BIT : RAMDAC_6BIT);
svga_recalctimings(svga);
svga_set_ramdac_type(svga, (ramdac->ctrl & 2) ? RAMDAC_8BIT : RAMDAC_6BIT);
svga_recalctimings(svga);
}
void
att498_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga)
{
att498_ramdac_t *ramdac = (att498_ramdac_t *) p;
uint8_t rs = (addr & 0x03);
uint8_t rs = (addr & 0x03);
rs |= ((!!rs2) << 2);
switch (rs) {
case 0x00:
case 0x01:
case 0x03:
case 0x04:
case 0x05:
case 0x07:
svga_out(addr, val, svga);
ramdac->state = 0;
break;
case 0x02:
switch (ramdac->state) {
case 4:
att498_ramdac_control(val, ramdac, svga);
break;
default:
svga_out(addr, val, svga);
break;
}
break;
case 0x06:
att498_ramdac_control(val, ramdac, svga);
break;
case 0x00:
case 0x01:
case 0x03:
case 0x04:
case 0x05:
case 0x07:
svga_out(addr, val, svga);
ramdac->state = 0;
break;
case 0x02:
switch (ramdac->state) {
case 4:
att498_ramdac_control(val, ramdac, svga);
break;
default:
svga_out(addr, val, svga);
break;
}
break;
case 0x06:
att498_ramdac_control(val, ramdac, svga);
break;
}
}
uint8_t
att498_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga)
{
att498_ramdac_t *ramdac = (att498_ramdac_t *) p;
uint8_t temp = 0xff;
uint8_t rs = (addr & 0x03);
uint8_t temp = 0xff;
uint8_t rs = (addr & 0x03);
rs |= ((!!rs2) << 2);
switch (rs) {
case 0x00:
case 0x01:
case 0x03:
case 0x04:
case 0x05:
case 0x07:
temp = svga_in(addr, svga);
ramdac->state = 0;
break;
case 0x02:
switch (ramdac->state) {
case 4:
temp = ramdac->ctrl;
ramdac->state++;
break;
case 5:
temp = 0x84;
ramdac->state++;
break;
case 6:
temp = ramdac->ctrl;
ramdac->state = 0;
break;
default:
temp = svga_in(addr, svga);
ramdac->state++;
break;
}
break;
case 0x06:
temp = ramdac->ctrl;
ramdac->state = 0;
break;
case 0x00:
case 0x01:
case 0x03:
case 0x04:
case 0x05:
case 0x07:
temp = svga_in(addr, svga);
ramdac->state = 0;
break;
case 0x02:
switch (ramdac->state) {
case 4:
temp = ramdac->ctrl;
ramdac->state++;
break;
case 5:
temp = 0x84;
ramdac->state++;
break;
case 6:
temp = ramdac->ctrl;
ramdac->state = 0;
break;
default:
temp = svga_in(addr, svga);
ramdac->state++;
break;
}
break;
case 0x06:
temp = ramdac->ctrl;
ramdac->state = 0;
break;
}
return temp;
}
static void *
att498_ramdac_init(const device_t *info)
{
@@ -166,26 +163,25 @@ att498_ramdac_init(const device_t *info)
return ramdac;
}
static void
att498_ramdac_close(void *priv)
{
att498_ramdac_t *ramdac = (att498_ramdac_t *) priv;
if (ramdac)
free(ramdac);
free(ramdac);
}
const device_t att498_ramdac_device = {
.name = "AT&T 22c498 RAMDAC",
.name = "AT&T 22c498 RAMDAC",
.internal_name = "att498_ramdac",
.flags = 0,
.local = 0,
.init = att498_ramdac_init,
.close = att498_ramdac_close,
.reset = NULL,
.flags = 0,
.local = 0,
.init = att498_ramdac_init,
.close = att498_ramdac_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};

View File

@@ -28,65 +28,62 @@
#include <86box/video.h>
#include <86box/vid_svga.h>
float
av9194_getclock(int clock, void *p)
{
float ret = 0.0;
switch (clock & 0x0f)
{
case 0:
ret = 25175000.0;
break;
case 1:
ret = 28322000.0;
break;
case 2:
ret = 40000000.0;
break;
case 4:
ret = 50000000.0;
break;
case 5:
ret = 77000000.0;
break;
case 6:
ret = 36000000.0;
break;
case 7:
ret = 44900000.0;
break;
case 8:
ret = 130000000.0;
break;
case 9:
ret = 120000000.0;
break;
case 0xa:
ret = 80000000.0;
break;
case 0xb:
ret = 31500000.0;
break;
case 0xc:
ret = 110000000.0;
break;
case 0xd:
ret = 65000000.0;
break;
case 0xe:
ret = 75000000.0;
break;
case 0xf:
ret = 94500000.0;
break;
switch (clock & 0x0f) {
case 0:
ret = 25175000.0;
break;
case 1:
ret = 28322000.0;
break;
case 2:
ret = 40000000.0;
break;
case 4:
ret = 50000000.0;
break;
case 5:
ret = 77000000.0;
break;
case 6:
ret = 36000000.0;
break;
case 7:
ret = 44900000.0;
break;
case 8:
ret = 130000000.0;
break;
case 9:
ret = 120000000.0;
break;
case 0xa:
ret = 80000000.0;
break;
case 0xb:
ret = 31500000.0;
break;
case 0xc:
ret = 110000000.0;
break;
case 0xd:
ret = 65000000.0;
break;
case 0xe:
ret = 75000000.0;
break;
case 0xf:
ret = 94500000.0;
break;
}
return ret;
}
static void *
av9194_init(const device_t *info)
{
@@ -94,17 +91,16 @@ av9194_init(const device_t *info)
return (void *) &av9194_device;
}
const device_t av9194_device = {
.name = "AV9194 Clock Generator",
.name = "AV9194 Clock Generator",
.internal_name = "av9194",
.flags = 0,
.local = 0,
.init = av9194_init,
.close = NULL,
.reset = NULL,
.flags = 0,
.local = 0,
.init = av9194_init,
.close = NULL,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};

View File

@@ -29,324 +29,319 @@
#include <86box/video.h>
#include <86box/vid_svga.h>
typedef struct
{
PALETTE extpal;
uint32_t extpallook[256];
uint8_t cursor32_data[256];
uint8_t cursor64_data[1024];
int hwc_y, hwc_x;
uint8_t cmd_r0;
uint8_t cmd_r1;
uint8_t cmd_r2;
uint8_t cmd_r3;
uint8_t cmd_r4;
uint8_t status;
uint8_t type;
PALETTE extpal;
uint32_t extpallook[256];
uint8_t cursor32_data[256];
uint8_t cursor64_data[1024];
int hwc_y, hwc_x;
uint8_t cmd_r0;
uint8_t cmd_r1;
uint8_t cmd_r2;
uint8_t cmd_r3;
uint8_t cmd_r4;
uint8_t status;
uint8_t type;
} bt48x_ramdac_t;
enum {
BT484 = 0,
ATT20C504,
BT485,
ATT20C505,
BT485A
BT484 = 0,
ATT20C504,
BT485,
ATT20C505,
BT485A
};
static void
bt48x_set_bpp(bt48x_ramdac_t *ramdac, svga_t *svga)
{
if ((!(ramdac->cmd_r2 & 0x20)) || ((ramdac->type >= BT485A) && ((ramdac->cmd_r3 & 0x60) == 0x60)))
svga->bpp = 8;
svga->bpp = 8;
else if ((ramdac->type >= BT485A) && ((ramdac->cmd_r3 & 0x60) == 0x40))
svga->bpp = 24;
else switch (ramdac->cmd_r1 & 0x60) {
case 0x00:
svga->bpp = 32;
break;
case 0x20:
if (ramdac->cmd_r1 & 0x08)
svga->bpp = 16;
else
svga->bpp = 15;
break;
case 0x40:
svga->bpp = 8;
break;
case 0x60:
svga->bpp = 4;
break;
}
svga->bpp = 24;
else
switch (ramdac->cmd_r1 & 0x60) {
case 0x00:
svga->bpp = 32;
break;
case 0x20:
if (ramdac->cmd_r1 & 0x08)
svga->bpp = 16;
else
svga->bpp = 15;
break;
case 0x40:
svga->bpp = 8;
break;
case 0x60:
svga->bpp = 4;
break;
}
svga_recalctimings(svga);
}
void
bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *p, svga_t *svga)
{
bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) p;
uint32_t o32;
uint8_t *cd;
uint16_t index;
uint8_t rs = (addr & 0x03);
uint16_t da_mask = 0x03ff;
uint32_t o32;
uint8_t *cd;
uint16_t index;
uint8_t rs = (addr & 0x03);
uint16_t da_mask = 0x03ff;
rs |= (!!rs2 << 2);
rs |= (!!rs3 << 3);
if (ramdac->type < BT485)
da_mask = 0x00ff;
da_mask = 0x00ff;
switch (rs) {
case 0x00: /* Palette Write Index Register (RS value = 0000) */
case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */
case 0x03:
case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */
svga->dac_pos = 0;
svga->dac_status = addr & 0x03;
svga->dac_addr = val;
if (ramdac->type >= BT485)
svga->dac_addr |= ((int) (ramdac->cmd_r3 & 0x03) << 8);
if (svga->dac_status)
svga->dac_addr = (svga->dac_addr + 1) & da_mask;
break;
case 0x01: /* Palette Data Register (RS value = 0001) */
case 0x02: /* Pixel Read Mask Register (RS value = 0010) */
svga_out(addr, val, svga);
break;
case 0x05: /* Ext Palette Data Register (RS value = 0101) */
svga->dac_status = 0;
svga->fullchange = changeframecount;
switch (svga->dac_pos) {
case 0:
svga->dac_r = val;
svga->dac_pos++;
break;
case 1:
svga->dac_g = val;
svga->dac_pos++;
break;
case 2:
index = svga->dac_addr & 3;
ramdac->extpal[index].r = svga->dac_r;
ramdac->extpal[index].g = svga->dac_g;
ramdac->extpal[index].b = val;
if (svga->ramdac_type == RAMDAC_8BIT)
ramdac->extpallook[index] = makecol32(ramdac->extpal[index].r, ramdac->extpal[index].g, ramdac->extpal[index].b);
else
ramdac->extpallook[index] = makecol32(video_6to8[ramdac->extpal[index].r & 0x3f], video_6to8[ramdac->extpal[index].g & 0x3f], video_6to8[ramdac->extpal[index].b & 0x3f]);
case 0x00: /* Palette Write Index Register (RS value = 0000) */
case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */
case 0x03:
case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */
svga->dac_pos = 0;
svga->dac_status = addr & 0x03;
svga->dac_addr = val;
if (ramdac->type >= BT485)
svga->dac_addr |= ((int) (ramdac->cmd_r3 & 0x03) << 8);
if (svga->dac_status)
svga->dac_addr = (svga->dac_addr + 1) & da_mask;
break;
case 0x01: /* Palette Data Register (RS value = 0001) */
case 0x02: /* Pixel Read Mask Register (RS value = 0010) */
svga_out(addr, val, svga);
break;
case 0x05: /* Ext Palette Data Register (RS value = 0101) */
svga->dac_status = 0;
svga->fullchange = changeframecount;
switch (svga->dac_pos) {
case 0:
svga->dac_r = val;
svga->dac_pos++;
break;
case 1:
svga->dac_g = val;
svga->dac_pos++;
break;
case 2:
index = svga->dac_addr & 3;
ramdac->extpal[index].r = svga->dac_r;
ramdac->extpal[index].g = svga->dac_g;
ramdac->extpal[index].b = val;
if (svga->ramdac_type == RAMDAC_8BIT)
ramdac->extpallook[index] = makecol32(ramdac->extpal[index].r, ramdac->extpal[index].g, ramdac->extpal[index].b);
else
ramdac->extpallook[index] = makecol32(video_6to8[ramdac->extpal[index].r & 0x3f], video_6to8[ramdac->extpal[index].g & 0x3f], video_6to8[ramdac->extpal[index].b & 0x3f]);
if (svga->ext_overscan && !index) {
o32 = svga->overscan_color;
svga->overscan_color = ramdac->extpallook[0];
if (o32 != svga->overscan_color)
svga_recalctimings(svga);
}
svga->dac_addr = (svga->dac_addr + 1) & 0xff;
svga->dac_pos = 0;
break;
}
break;
case 0x06: /* Command Register 0 (RS value = 0110) */
ramdac->cmd_r0 = val;
svga->ramdac_type = (val & 0x02) ? RAMDAC_8BIT : RAMDAC_6BIT;
break;
case 0x08: /* Command Register 1 (RS value = 1000) */
ramdac->cmd_r1 = val;
bt48x_set_bpp(ramdac, svga);
break;
case 0x09: /* Command Register 2 (RS value = 1001) */
ramdac->cmd_r2 = val;
svga->dac_hwcursor.ena = !!(val & 0x03);
bt48x_set_bpp(ramdac, svga);
break;
case 0x0a:
if ((ramdac->type >= BT485) && (ramdac->cmd_r0 & 0x80)) {
switch ((svga->dac_addr & ((ramdac->type >= BT485A) ? 0xff : 0x3f))) {
case 0x01:
/* Command Register 3 (RS value = 1010) */
ramdac->cmd_r3 = val;
if (ramdac->type >= BT485A)
bt48x_set_bpp(ramdac, svga);
svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = (val & 4) ? 64 : 32;
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
svga->dac_addr = (svga->dac_addr & 0x00ff) | ((val & 0x03) << 8);
svga_recalctimings(svga);
break;
case 0x02:
case 0x20:
case 0x21:
case 0x22:
if (ramdac->type != BT485A)
break;
else if (svga->dac_addr == 2) {
ramdac->cmd_r4 = val;
break;
}
break;
}
}
break;
case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */
index = svga->dac_addr & da_mask;
if ((ramdac->type >= BT485) && (svga->dac_hwcursor.cur_xsize == 64))
cd = (uint8_t *) ramdac->cursor64_data;
else {
index &= 0xff;
cd = (uint8_t *) ramdac->cursor32_data;
}
if (svga->ext_overscan && !index) {
o32 = svga->overscan_color;
svga->overscan_color = ramdac->extpallook[0];
if (o32 != svga->overscan_color)
svga_recalctimings(svga);
}
svga->dac_addr = (svga->dac_addr + 1) & 0xff;
svga->dac_pos = 0;
break;
}
break;
case 0x06: /* Command Register 0 (RS value = 0110) */
ramdac->cmd_r0 = val;
svga->ramdac_type = (val & 0x02) ? RAMDAC_8BIT : RAMDAC_6BIT;
break;
case 0x08: /* Command Register 1 (RS value = 1000) */
ramdac->cmd_r1 = val;
bt48x_set_bpp(ramdac, svga);
break;
case 0x09: /* Command Register 2 (RS value = 1001) */
ramdac->cmd_r2 = val;
svga->dac_hwcursor.ena = !!(val & 0x03);
bt48x_set_bpp(ramdac, svga);
break;
case 0x0a:
if ((ramdac->type >= BT485) && (ramdac->cmd_r0 & 0x80)) {
switch ((svga->dac_addr & ((ramdac->type >= BT485A) ? 0xff : 0x3f))) {
case 0x01:
/* Command Register 3 (RS value = 1010) */
ramdac->cmd_r3 = val;
if (ramdac->type >= BT485A)
bt48x_set_bpp(ramdac, svga);
svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = (val & 4) ? 64 : 32;
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
svga->dac_addr = (svga->dac_addr & 0x00ff) | ((val & 0x03) << 8);
svga_recalctimings(svga);
break;
case 0x02:
case 0x20:
case 0x21:
case 0x22:
if (ramdac->type != BT485A)
break;
else if (svga->dac_addr == 2) {
ramdac->cmd_r4 = val;
break;
}
break;
}
}
break;
case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */
index = svga->dac_addr & da_mask;
if ((ramdac->type >= BT485) && (svga->dac_hwcursor.cur_xsize == 64))
cd = (uint8_t *) ramdac->cursor64_data;
else {
index &= 0xff;
cd = (uint8_t *) ramdac->cursor32_data;
}
cd[index] = val;
cd[index] = val;
svga->dac_addr = (svga->dac_addr + 1) & da_mask;
break;
case 0x0c: /* Cursor X Low Register (RS value = 1100) */
ramdac->hwc_x = (ramdac->hwc_x & 0x0f00) | val;
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
break;
case 0x0d: /* Cursor X High Register (RS value = 1101) */
ramdac->hwc_x = (ramdac->hwc_x & 0x00ff) | ((val & 0x0f) << 8);
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
break;
case 0x0e: /* Cursor Y Low Register (RS value = 1110) */
ramdac->hwc_y = (ramdac->hwc_y & 0x0f00) | val;
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
break;
case 0x0f: /* Cursor Y High Register (RS value = 1111) */
ramdac->hwc_y = (ramdac->hwc_y & 0x00ff) | ((val & 0x0f) << 8);
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
break;
svga->dac_addr = (svga->dac_addr + 1) & da_mask;
break;
case 0x0c: /* Cursor X Low Register (RS value = 1100) */
ramdac->hwc_x = (ramdac->hwc_x & 0x0f00) | val;
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
break;
case 0x0d: /* Cursor X High Register (RS value = 1101) */
ramdac->hwc_x = (ramdac->hwc_x & 0x00ff) | ((val & 0x0f) << 8);
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
break;
case 0x0e: /* Cursor Y Low Register (RS value = 1110) */
ramdac->hwc_y = (ramdac->hwc_y & 0x0f00) | val;
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
break;
case 0x0f: /* Cursor Y High Register (RS value = 1111) */
ramdac->hwc_y = (ramdac->hwc_y & 0x00ff) | ((val & 0x0f) << 8);
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
break;
}
return;
}
uint8_t
bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, void *p, svga_t *svga)
{
bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) p;
uint8_t temp = 0xff;
uint8_t *cd;
uint16_t index;
uint8_t rs = (addr & 0x03);
uint16_t da_mask = 0x03ff;
uint8_t temp = 0xff;
uint8_t *cd;
uint16_t index;
uint8_t rs = (addr & 0x03);
uint16_t da_mask = 0x03ff;
rs |= (!!rs2 << 2);
rs |= (!!rs3 << 3);
if (ramdac->type < BT485)
da_mask = 0x00ff;
da_mask = 0x00ff;
switch (rs) {
case 0x00: /* Palette Write Index Register (RS value = 0000) */
case 0x01: /* Palette Data Register (RS value = 0001) */
case 0x02: /* Pixel Read Mask Register (RS value = 0010) */
case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */
temp = svga_in(addr, svga);
break;
case 0x03: /* Palette Read Index Register (RS value = 0011) */
case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */
temp = svga->dac_addr & 0xff;
break;
case 0x05: /* Ext Palette Data Register (RS value = 0101) */
index = (svga->dac_addr - 1) & 3;
svga->dac_status = 3;
switch (svga->dac_pos) {
case 0:
svga->dac_pos++;
if (svga->ramdac_type == RAMDAC_8BIT)
temp = ramdac->extpal[index].r;
else
temp = ramdac->extpal[index].r & 0x3f;
break;
case 1:
svga->dac_pos++;
if (svga->ramdac_type == RAMDAC_8BIT)
temp = ramdac->extpal[index].g;
else
temp = ramdac->extpal[index].g & 0x3f;
break;
case 2:
svga->dac_pos=0;
svga->dac_addr = svga->dac_addr + 1;
if (svga->ramdac_type == RAMDAC_8BIT)
temp = ramdac->extpal[index].b;
else
temp = ramdac->extpal[index].b & 0x3f;
break;
}
break;
case 0x06: /* Command Register 0 (RS value = 0110) */
temp = ramdac->cmd_r0;
break;
case 0x08: /* Command Register 1 (RS value = 1000) */
temp = ramdac->cmd_r1;
break;
case 0x09: /* Command Register 2 (RS value = 1001) */
temp = ramdac->cmd_r2;
break;
case 0x0a:
if ((ramdac->type >= BT485) && (ramdac->cmd_r0 & 0x80)) {
switch ((svga->dac_addr & ((ramdac->type >= BT485A) ? 0xff : 0x3f))) {
case 0x00:
default:
temp = ramdac->status | (svga->dac_status ? 0x04 : 0x00);
break;
case 0x01:
temp = ramdac->cmd_r3 & 0xfc;
temp |= (svga->dac_addr & 0x300) >> 8;
break;
case 0x02:
case 0x20:
case 0x21:
case 0x22:
if (ramdac->type != BT485A)
break;
else if (svga->dac_addr == 2) {
temp = ramdac->cmd_r4;
break;
} else {
/* TODO: Red, Green, and Blue Signature Analysis Registers */
temp = 0xff;
break;
}
break;
}
} else
temp = ramdac->status | (svga->dac_status ? 0x04 : 0x00);
break;
case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */
index = (svga->dac_addr - 1) & da_mask;
if ((ramdac->type >= BT485) && (svga->dac_hwcursor.cur_xsize == 64))
cd = (uint8_t *) ramdac->cursor64_data;
else {
index &= 0xff;
cd = (uint8_t *) ramdac->cursor32_data;
}
case 0x00: /* Palette Write Index Register (RS value = 0000) */
case 0x01: /* Palette Data Register (RS value = 0001) */
case 0x02: /* Pixel Read Mask Register (RS value = 0010) */
case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */
temp = svga_in(addr, svga);
break;
case 0x03: /* Palette Read Index Register (RS value = 0011) */
case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */
temp = svga->dac_addr & 0xff;
break;
case 0x05: /* Ext Palette Data Register (RS value = 0101) */
index = (svga->dac_addr - 1) & 3;
svga->dac_status = 3;
switch (svga->dac_pos) {
case 0:
svga->dac_pos++;
if (svga->ramdac_type == RAMDAC_8BIT)
temp = ramdac->extpal[index].r;
else
temp = ramdac->extpal[index].r & 0x3f;
break;
case 1:
svga->dac_pos++;
if (svga->ramdac_type == RAMDAC_8BIT)
temp = ramdac->extpal[index].g;
else
temp = ramdac->extpal[index].g & 0x3f;
break;
case 2:
svga->dac_pos = 0;
svga->dac_addr = svga->dac_addr + 1;
if (svga->ramdac_type == RAMDAC_8BIT)
temp = ramdac->extpal[index].b;
else
temp = ramdac->extpal[index].b & 0x3f;
break;
}
break;
case 0x06: /* Command Register 0 (RS value = 0110) */
temp = ramdac->cmd_r0;
break;
case 0x08: /* Command Register 1 (RS value = 1000) */
temp = ramdac->cmd_r1;
break;
case 0x09: /* Command Register 2 (RS value = 1001) */
temp = ramdac->cmd_r2;
break;
case 0x0a:
if ((ramdac->type >= BT485) && (ramdac->cmd_r0 & 0x80)) {
switch ((svga->dac_addr & ((ramdac->type >= BT485A) ? 0xff : 0x3f))) {
case 0x00:
default:
temp = ramdac->status | (svga->dac_status ? 0x04 : 0x00);
break;
case 0x01:
temp = ramdac->cmd_r3 & 0xfc;
temp |= (svga->dac_addr & 0x300) >> 8;
break;
case 0x02:
case 0x20:
case 0x21:
case 0x22:
if (ramdac->type != BT485A)
break;
else if (svga->dac_addr == 2) {
temp = ramdac->cmd_r4;
break;
} else {
/* TODO: Red, Green, and Blue Signature Analysis Registers */
temp = 0xff;
break;
}
break;
}
} else
temp = ramdac->status | (svga->dac_status ? 0x04 : 0x00);
break;
case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */
index = (svga->dac_addr - 1) & da_mask;
if ((ramdac->type >= BT485) && (svga->dac_hwcursor.cur_xsize == 64))
cd = (uint8_t *) ramdac->cursor64_data;
else {
index &= 0xff;
cd = (uint8_t *) ramdac->cursor32_data;
}
temp = cd[index];
temp = cd[index];
svga->dac_addr = (svga->dac_addr + 1) & da_mask;
break;
case 0x0c: /* Cursor X Low Register (RS value = 1100) */
temp = ramdac->hwc_x & 0xff;
break;
case 0x0d: /* Cursor X High Register (RS value = 1101) */
temp = (ramdac->hwc_x >> 8) & 0xff;
break;
case 0x0e: /* Cursor Y Low Register (RS value = 1110) */
temp = ramdac->hwc_y & 0xff;
break;
case 0x0f: /* Cursor Y High Register (RS value = 1111) */
temp = (ramdac->hwc_y >> 8) & 0xff;
break;
svga->dac_addr = (svga->dac_addr + 1) & da_mask;
break;
case 0x0c: /* Cursor X Low Register (RS value = 1100) */
temp = ramdac->hwc_x & 0xff;
break;
case 0x0d: /* Cursor X High Register (RS value = 1101) */
temp = (ramdac->hwc_x >> 8) & 0xff;
break;
case 0x0e: /* Cursor Y Low Register (RS value = 1110) */
temp = ramdac->hwc_y & 0xff;
break;
case 0x0f: /* Cursor Y High Register (RS value = 1111) */
temp = (ramdac->hwc_y >> 8) & 0xff;
break;
}
return temp;
}
void
bt48x_recalctimings(void *p, svga_t *svga)
{
@@ -354,19 +349,18 @@ bt48x_recalctimings(void *p, svga_t *svga)
svga->interlace = ramdac->cmd_r2 & 0x08;
if (ramdac->cmd_r3 & 0x08)
svga->hdisp *= 2; /* x2 clock multiplier */
svga->hdisp *= 2; /* x2 clock multiplier */
}
void
bt48x_hwcursor_draw(svga_t *svga, int displine)
{
int x, xx, comb, b0, b1;
uint16_t dat[2];
int offset = svga->dac_hwcursor_latch.x - svga->dac_hwcursor_latch.xoff;
int pitch, bppl, mode, x_pos, y_pos;
uint32_t clr1, clr2, clr3, *p;
uint8_t *cd;
int x, xx, comb, b0, b1;
uint16_t dat[2];
int offset = svga->dac_hwcursor_latch.x - svga->dac_hwcursor_latch.xoff;
int pitch, bppl, mode, x_pos, y_pos;
uint32_t clr1, clr2, clr3, *p;
uint8_t *cd;
bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) svga->ramdac;
clr1 = ramdac->extpallook[1];
@@ -376,85 +370,82 @@ bt48x_hwcursor_draw(svga_t *svga, int displine)
/* The planes come in two parts, and each plane is 1bpp,
so a 32x32 cursor has 4 bytes per line, and a 64x64
cursor has 8 bytes per line. */
pitch = (svga->dac_hwcursor_latch.cur_xsize >> 3); /* Bytes per line. */
pitch = (svga->dac_hwcursor_latch.cur_xsize >> 3); /* Bytes per line. */
/* A 32x32 cursor has 128 bytes per line, and a 64x64
cursor has 512 bytes per line. */
bppl = (pitch * svga->dac_hwcursor_latch.cur_ysize); /* Bytes per plane. */
bppl = (pitch * svga->dac_hwcursor_latch.cur_ysize); /* Bytes per plane. */
mode = ramdac->cmd_r2 & 0x03;
if (svga->interlace && svga->dac_hwcursor_oddeven)
svga->dac_hwcursor_latch.addr += pitch;
svga->dac_hwcursor_latch.addr += pitch;
if (svga->dac_hwcursor_latch.cur_xsize == 64)
cd = (uint8_t *) ramdac->cursor64_data;
cd = (uint8_t *) ramdac->cursor64_data;
else
cd = (uint8_t *) ramdac->cursor32_data;
cd = (uint8_t *) ramdac->cursor32_data;
for (x = 0; x < svga->dac_hwcursor_latch.cur_xsize; x += 16) {
dat[0] = (cd[svga->dac_hwcursor_latch.addr] << 8) |
cd[svga->dac_hwcursor_latch.addr + 1];
dat[1] = (cd[svga->dac_hwcursor_latch.addr + bppl] << 8) |
cd[svga->dac_hwcursor_latch.addr + bppl + 1];
dat[0] = (cd[svga->dac_hwcursor_latch.addr] << 8) | cd[svga->dac_hwcursor_latch.addr + 1];
dat[1] = (cd[svga->dac_hwcursor_latch.addr + bppl] << 8) | cd[svga->dac_hwcursor_latch.addr + bppl + 1];
for (xx = 0; xx < 16; xx++) {
b0 = (dat[0] >> (15 - xx)) & 1;
b1 = (dat[1] >> (15 - xx)) & 1;
comb = (b0 | (b1 << 1));
for (xx = 0; xx < 16; xx++) {
b0 = (dat[0] >> (15 - xx)) & 1;
b1 = (dat[1] >> (15 - xx)) & 1;
comb = (b0 | (b1 << 1));
y_pos = displine;
x_pos = offset + svga->x_add;
p = buffer32->line[y_pos];
y_pos = displine;
x_pos = offset + svga->x_add;
p = buffer32->line[y_pos];
if (offset >= svga->dac_hwcursor_latch.x) {
switch (mode) {
case 1: /* Three Color */
switch (comb) {
case 1:
p[x_pos] = clr1;
break;
case 2:
p[x_pos] = clr2;
break;
case 3:
p[x_pos] = clr3;
break;
}
break;
case 2: /* PM/Windows */
switch (comb) {
case 0:
p[x_pos] = clr1;
break;
case 1:
p[x_pos] = clr2;
break;
case 3:
p[x_pos] ^= 0xffffff;
break;
}
break;
case 3: /* X-Windows */
switch (comb) {
case 2:
p[x_pos] = clr1;
break;
case 3:
p[x_pos] = clr2;
break;
}
break;
}
}
offset++;
}
svga->dac_hwcursor_latch.addr += 2;
if (offset >= svga->dac_hwcursor_latch.x) {
switch (mode) {
case 1: /* Three Color */
switch (comb) {
case 1:
p[x_pos] = clr1;
break;
case 2:
p[x_pos] = clr2;
break;
case 3:
p[x_pos] = clr3;
break;
}
break;
case 2: /* PM/Windows */
switch (comb) {
case 0:
p[x_pos] = clr1;
break;
case 1:
p[x_pos] = clr2;
break;
case 3:
p[x_pos] ^= 0xffffff;
break;
}
break;
case 3: /* X-Windows */
switch (comb) {
case 2:
p[x_pos] = clr1;
break;
case 3:
p[x_pos] = clr2;
break;
}
break;
}
}
offset++;
}
svga->dac_hwcursor_latch.addr += 2;
}
if (svga->interlace && !svga->dac_hwcursor_oddeven)
svga->dac_hwcursor_latch.addr += pitch;
svga->dac_hwcursor_latch.addr += pitch;
}
void *
bt48x_ramdac_init(const device_t *info)
{
@@ -465,106 +456,105 @@ bt48x_ramdac_init(const device_t *info)
/* Set the RAM DAC status byte to the correct ID bits.
Both the BT484 and BT485 datasheets say this:
SR7-SR6: These bits are identification values. SR7=0 and SR6=1.
But all other sources seem to assume SR7=1 and SR6=0. */
Both the BT484 and BT485 datasheets say this:
SR7-SR6: These bits are identification values. SR7=0 and SR6=1.
But all other sources seem to assume SR7=1 and SR6=0. */
switch (ramdac->type) {
case BT484:
ramdac->status = 0x40;
break;
case ATT20C504:
ramdac->status = 0x40;
break;
case BT485:
ramdac->status = 0x60;
break;
case ATT20C505:
ramdac->status = 0xd0;
break;
case BT485A:
ramdac->status = 0x20;
break;
case BT484:
ramdac->status = 0x40;
break;
case ATT20C504:
ramdac->status = 0x40;
break;
case BT485:
ramdac->status = 0x60;
break;
case ATT20C505:
ramdac->status = 0xd0;
break;
case BT485A:
ramdac->status = 0x20;
break;
}
return ramdac;
}
static void
bt48x_ramdac_close(void *priv)
{
bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) priv;
if (ramdac)
free(ramdac);
free(ramdac);
}
const device_t bt484_ramdac_device = {
.name = "Brooktree Bt484 RAMDAC",
.name = "Brooktree Bt484 RAMDAC",
.internal_name = "bt484_ramdac",
.flags = 0,
.local = BT484,
.init = bt48x_ramdac_init,
.close = bt48x_ramdac_close,
.reset = NULL,
.flags = 0,
.local = BT484,
.init = bt48x_ramdac_init,
.close = bt48x_ramdac_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
const device_t att20c504_ramdac_device = {
.name = "AT&T 20c504 RAMDAC",
.name = "AT&T 20c504 RAMDAC",
.internal_name = "att20c504_ramdac",
.flags = 0,
.local = ATT20C504,
.init = bt48x_ramdac_init,
.close = bt48x_ramdac_close,
.reset = NULL,
.flags = 0,
.local = ATT20C504,
.init = bt48x_ramdac_init,
.close = bt48x_ramdac_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
const device_t bt485_ramdac_device = {
.name = "Brooktree Bt485 RAMDAC",
.name = "Brooktree Bt485 RAMDAC",
.internal_name = "bt485_ramdac",
.flags = 0,
.local = BT485,
.init = bt48x_ramdac_init,
.close = bt48x_ramdac_close,
.reset = NULL,
.flags = 0,
.local = BT485,
.init = bt48x_ramdac_init,
.close = bt48x_ramdac_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
const device_t att20c505_ramdac_device = {
.name = "AT&T 20c505 RAMDAC",
.name = "AT&T 20c505 RAMDAC",
.internal_name = "att20c505_ramdac",
.flags = 0,
.local = ATT20C505,
.init = bt48x_ramdac_init,
.close = bt48x_ramdac_close,
.reset = NULL,
.flags = 0,
.local = ATT20C505,
.init = bt48x_ramdac_init,
.close = bt48x_ramdac_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
const device_t bt485a_ramdac_device = {
.name = "Brooktree Bt485A RAMDAC",
.name = "Brooktree Bt485A RAMDAC",
.internal_name = "bt485a_ramdac",
.flags = 0,
.local = BT485A,
.init = bt48x_ramdac_init,
.close = bt48x_ramdac_close,
.reset = NULL,
.flags = 0,
.local = BT485A,
.init = bt48x_ramdac_init,
.close = bt48x_ramdac_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};

View File

@@ -34,68 +34,64 @@
#include <86box/vid_cga.h>
#include <86box/vid_cga_comp.h>
#define CGA_RGB 0
#define CGA_RGB 0
#define CGA_COMPOSITE 1
#define COMPOSITE_OLD 0
#define COMPOSITE_NEW 1
static uint8_t crtcmask[32] =
{
0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
static uint8_t crtcmask[32] = {
0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static video_timings_t timing_cga = {VIDEO_ISA, 8, 16, 32, 8, 16, 32};
static video_timings_t timing_cga = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 };
void cga_recalctimings(cga_t *cga);
void
cga_out(uint16_t addr, uint8_t val, void *p)
{
cga_t *cga = (cga_t *) p;
cga_t *cga = (cga_t *) p;
uint8_t old;
if ((addr >= 0x3d0) && (addr <= 0x3d7))
addr = (addr & 0xff9) | 0x004;
addr = (addr & 0xff9) | 0x004;
switch (addr) {
case 0x3D4:
cga->crtcreg = val & 31;
return;
case 0x3D5:
old = cga->crtc[cga->crtcreg];
cga->crtc[cga->crtcreg] = val & crtcmask[cga->crtcreg];
if (old != val) {
if ((cga->crtcreg < 0xe) || (cga->crtcreg > 0x10)) {
cga->fullchange = changeframecount;
cga_recalctimings(cga);
}
}
return;
case 0x3D8:
old = cga->cgamode;
cga->cgamode = val;
case 0x3D4:
cga->crtcreg = val & 31;
return;
case 0x3D5:
old = cga->crtc[cga->crtcreg];
cga->crtc[cga->crtcreg] = val & crtcmask[cga->crtcreg];
if (old != val) {
if ((cga->crtcreg < 0xe) || (cga->crtcreg > 0x10)) {
cga->fullchange = changeframecount;
cga_recalctimings(cga);
}
}
return;
case 0x3D8:
old = cga->cgamode;
cga->cgamode = val;
if (old ^ val) {
if ((old ^ val) & 0x05)
update_cga16_color(val);
if (old ^ val) {
if ((old ^ val) & 0x05)
update_cga16_color(val);
cga_recalctimings(cga);
}
return;
case 0x3D9:
old = cga->cgacol;
cga->cgacol = val;
if (old ^ val)
cga_recalctimings(cga);
return;
cga_recalctimings(cga);
}
return;
case 0x3D9:
old = cga->cgacol;
cga->cgacol = val;
if (old ^ val)
cga_recalctimings(cga);
return;
}
}
uint8_t
cga_in(uint16_t addr, void *p)
{
@@ -104,35 +100,33 @@ cga_in(uint16_t addr, void *p)
uint8_t ret = 0xff;
if ((addr >= 0x3d0) && (addr <= 0x3d7))
addr = (addr & 0xff9) | 0x004;
addr = (addr & 0xff9) | 0x004;
switch (addr) {
case 0x3D4:
ret = cga->crtcreg;
break;
case 0x3D5:
ret = cga->crtc[cga->crtcreg];
break;
case 0x3DA:
ret = cga->cgastat;
break;
case 0x3D4:
ret = cga->crtcreg;
break;
case 0x3D5:
ret = cga->crtc[cga->crtcreg];
break;
case 0x3DA:
ret = cga->cgastat;
break;
}
return ret;
}
void
cga_waitstates(void *p)
{
int ws_array[16] = {3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8};
int ws_array[16] = { 3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8 };
int ws;
ws = ws_array[cycles & 0xf];
cycles -= ws;
}
void
cga_write(uint32_t addr, uint8_t val, void *p)
{
@@ -140,14 +134,13 @@ cga_write(uint32_t addr, uint8_t val, void *p)
cga->vram[addr & 0x3fff] = val;
if (cga->snow_enabled) {
int offset = ((timer_get_remaining_u64(&cga->timer) / CGACONST) * 2) & 0xfc;
cga->charbuffer[offset] = cga->vram[addr & 0x3fff];
cga->charbuffer[offset | 1] = cga->vram[addr & 0x3fff];
int offset = ((timer_get_remaining_u64(&cga->timer) / CGACONST) * 2) & 0xfc;
cga->charbuffer[offset] = cga->vram[addr & 0x3fff];
cga->charbuffer[offset | 1] = cga->vram[addr & 0x3fff];
}
cga_waitstates(cga);
}
uint8_t
cga_read(uint32_t addr, void *p)
{
@@ -155,14 +148,13 @@ cga_read(uint32_t addr, void *p)
cga_waitstates(cga);
if (cga->snow_enabled) {
int offset = ((timer_get_remaining_u64(&cga->timer) / CGACONST) * 2) & 0xfc;
cga->charbuffer[offset] = cga->vram[addr & 0x3fff];
cga->charbuffer[offset | 1] = cga->vram[addr & 0x3fff];
int offset = ((timer_get_remaining_u64(&cga->timer) / CGACONST) * 2) & 0xfc;
cga->charbuffer[offset] = cga->vram[addr & 0x3fff];
cga->charbuffer[offset | 1] = cga->vram[addr & 0x3fff];
}
return cga->vram[addr & 0x3fff];
}
void
cga_recalctimings(cga_t *cga)
{
@@ -170,354 +162,331 @@ cga_recalctimings(cga_t *cga)
double _dispontime, _dispofftime;
if (cga->cgamode & 1) {
disptime = (double) (cga->crtc[0] + 1);
_dispontime = (double) cga->crtc[1];
disptime = (double) (cga->crtc[0] + 1);
_dispontime = (double) cga->crtc[1];
} else {
disptime = (double) ((cga->crtc[0] + 1) << 1);
_dispontime = (double) (cga->crtc[1] << 1);
disptime = (double) ((cga->crtc[0] + 1) << 1);
_dispontime = (double) (cga->crtc[1] << 1);
}
_dispofftime = disptime - _dispontime;
_dispontime = _dispontime * CGACONST;
_dispofftime = _dispofftime * CGACONST;
cga->dispontime = (uint64_t)(_dispontime);
cga->dispofftime = (uint64_t)(_dispofftime);
_dispofftime = disptime - _dispontime;
_dispontime = _dispontime * CGACONST;
_dispofftime = _dispofftime * CGACONST;
cga->dispontime = (uint64_t) (_dispontime);
cga->dispofftime = (uint64_t) (_dispofftime);
}
void
cga_poll(void *p)
{
cga_t *cga = (cga_t *)p;
uint16_t ca = (cga->crtc[15] | (cga->crtc[14] << 8)) & 0x3fff;
int drawcursor;
int x, c, xs_temp, ys_temp;
int oldvc;
uint8_t chr, attr;
uint8_t border;
cga_t *cga = (cga_t *) p;
uint16_t ca = (cga->crtc[15] | (cga->crtc[14] << 8)) & 0x3fff;
int drawcursor;
int x, c, xs_temp, ys_temp;
int oldvc;
uint8_t chr, attr;
uint8_t border;
uint16_t dat;
int cols[4];
int col;
int oldsc;
int cols[4];
int col;
int oldsc;
if (!cga->linepos) {
timer_advance_u64(&cga->timer, cga->dispofftime);
cga->cgastat |= 1;
cga->linepos = 1;
oldsc = cga->sc;
if ((cga->crtc[8] & 3) == 3)
cga->sc = ((cga->sc << 1) + cga->oddeven) & 7;
if (cga->cgadispon) {
if (cga->displine < cga->firstline) {
cga->firstline = cga->displine;
video_wait_for_buffer();
}
cga->lastline = cga->displine;
for (c = 0; c < 8; c++) {
if ((cga->cgamode & 0x12) == 0x12) {
buffer32->line[(cga->displine << 1)][c] =
buffer32->line[(cga->displine << 1) + 1][c] = 0;
if (cga->cgamode & 1) {
buffer32->line[(cga->displine << 1)][c + (cga->crtc[1] << 3) + 8] =
buffer32->line[(cga->displine << 1) + 1][c + (cga->crtc[1] << 3) + 8] = 0;
} else {
buffer32->line[(cga->displine << 1)][c + (cga->crtc[1] << 4) + 8] =
buffer32->line[(cga->displine << 1) + 1][c + (cga->crtc[1] << 4) + 8] = 0;
}
} else {
buffer32->line[(cga->displine << 1)][c] =
buffer32->line[(cga->displine << 1) + 1][c] = (cga->cgacol & 15) + 16;
if (cga->cgamode & 1) {
buffer32->line[(cga->displine << 1)][c + (cga->crtc[1] << 3) + 8] =
buffer32->line[(cga->displine << 1) + 1][c + (cga->crtc[1] << 3) + 8] = (cga->cgacol & 15) + 16;
} else {
buffer32->line[(cga->displine << 1)][c + (cga->crtc[1] << 4) + 8] =
buffer32->line[(cga->displine << 1) + 1][c + (cga->crtc[1] << 4) + 8] = (cga->cgacol & 15) + 16;
}
}
}
if (cga->cgamode & 1) {
for (x = 0; x < cga->crtc[1]; x++) {
if (cga->cgamode & 8) {
chr = cga->charbuffer[x << 1];
attr = cga->charbuffer[(x << 1) + 1];
} else
chr = attr = 0;
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
cols[1] = (attr & 15) + 16;
if (cga->cgamode & 0x20) {
cols[0] = ((attr >> 4) & 7) + 16;
if ((cga->cgablink & 8) && (attr & 0x80) && !cga->drawcursor)
cols[1] = cols[0];
} else
cols[0] = (attr >> 4) + 16;
if (drawcursor) {
for (c = 0; c < 8; c++) {
buffer32->line[(cga->displine << 1)][(x << 3) + c + 8] =
buffer32->line[(cga->displine << 1) + 1][(x << 3) + c + 8] =
cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
}
} else {
for (c = 0; c < 8; c++) {
buffer32->line[(cga->displine << 1)][(x << 3) + c + 8] =
buffer32->line[(cga->displine << 1) + 1][(x << 3) + c + 8] =
cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
}
cga->ma++;
}
} else if (!(cga->cgamode & 2)) {
for (x = 0; x < cga->crtc[1]; x++) {
if (cga->cgamode & 8) {
chr = cga->vram[((cga->ma << 1) & 0x3fff)];
attr = cga->vram[(((cga->ma << 1) + 1) & 0x3fff)];
} else
chr = attr = 0;
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
cols[1] = (attr & 15) + 16;
if (cga->cgamode & 0x20) {
cols[0] = ((attr >> 4) & 7) + 16;
if ((cga->cgablink & 8) && (attr & 0x80))
cols[1] = cols[0];
} else
cols[0] = (attr >> 4) + 16;
cga->ma++;
if (drawcursor) {
for (c = 0; c < 8; c++) {
buffer32->line[(cga->displine << 1)][(x << 4) + (c << 1) + 8] =
buffer32->line[(cga->displine << 1)][(x << 4) + (c << 1) + 1 + 8] =
buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 8] =
buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] =
cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
}
} else {
for (c = 0; c < 8; c++) {
buffer32->line[(cga->displine << 1)][(x << 4) + (c << 1) + 8] =
buffer32->line[(cga->displine << 1)][(x << 4) + (c << 1) + 1 + 8] =
buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 8] =
buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] =
cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
}
}
} else if (!(cga->cgamode & 16)) {
cols[0] = (cga->cgacol & 15) | 16;
col = (cga->cgacol & 16) ? 24 : 16;
if (cga->cgamode & 4) {
cols[1] = col | 3; /* Cyan */
cols[2] = col | 4; /* Red */
cols[3] = col | 7; /* White */
} else if (cga->cgacol & 32) {
cols[1] = col | 3; /* Cyan */
cols[2] = col | 5; /* Magenta */
cols[3] = col | 7; /* White */
} else {
cols[1] = col | 2; /* Green */
cols[2] = col | 4; /* Red */
cols[3] = col | 6; /* Yellow */
}
for (x = 0; x < cga->crtc[1]; x++) {
if (cga->cgamode & 8)
dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
else
dat = 0;
cga->ma++;
for (c = 0; c < 8; c++) {
buffer32->line[(cga->displine << 1)][(x << 4) + (c << 1) + 8] =
buffer32->line[(cga->displine << 1)][(x << 4) + (c << 1) + 1 + 8] =
buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 8] =
buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] =
cols[dat >> 14];
dat <<= 2;
}
}
} else {
cols[0] = 0; cols[1] = (cga->cgacol & 15) + 16;
for (x = 0; x < cga->crtc[1]; x++) {
if (cga->cgamode & 8)
dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
else
dat = 0;
cga->ma++;
for (c = 0; c < 16; c++) {
buffer32->line[(cga->displine << 1)][(x << 4) + c + 8] =
buffer32->line[(cga->displine << 1) + 1][(x << 4) + c + 8] =
cols[dat >> 15];
dat <<= 1;
}
}
}
} else {
cols[0] = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15) + 16;
if (cga->cgamode & 1) {
hline(buffer32, 0, (cga->displine << 1), ((cga->crtc[1] << 3) + 16) << 2, cols[0]);
hline(buffer32, 0, (cga->displine << 1) + 1, ((cga->crtc[1] << 3) + 16) << 2, cols[0]);
} else {
hline(buffer32, 0, (cga->displine << 1), ((cga->crtc[1] << 4) + 16) << 2, cols[0]);
hline(buffer32, 0, (cga->displine << 1) + 1, ((cga->crtc[1] << 4) + 16) << 2, cols[0]);
}
}
timer_advance_u64(&cga->timer, cga->dispofftime);
cga->cgastat |= 1;
cga->linepos = 1;
oldsc = cga->sc;
if ((cga->crtc[8] & 3) == 3)
cga->sc = ((cga->sc << 1) + cga->oddeven) & 7;
if (cga->cgadispon) {
if (cga->displine < cga->firstline) {
cga->firstline = cga->displine;
video_wait_for_buffer();
}
cga->lastline = cga->displine;
for (c = 0; c < 8; c++) {
if ((cga->cgamode & 0x12) == 0x12) {
buffer32->line[(cga->displine << 1)][c] = buffer32->line[(cga->displine << 1) + 1][c] = 0;
if (cga->cgamode & 1) {
buffer32->line[(cga->displine << 1)][c + (cga->crtc[1] << 3) + 8] = buffer32->line[(cga->displine << 1) + 1][c + (cga->crtc[1] << 3) + 8] = 0;
} else {
buffer32->line[(cga->displine << 1)][c + (cga->crtc[1] << 4) + 8] = buffer32->line[(cga->displine << 1) + 1][c + (cga->crtc[1] << 4) + 8] = 0;
}
} else {
buffer32->line[(cga->displine << 1)][c] = buffer32->line[(cga->displine << 1) + 1][c] = (cga->cgacol & 15) + 16;
if (cga->cgamode & 1) {
buffer32->line[(cga->displine << 1)][c + (cga->crtc[1] << 3) + 8] = buffer32->line[(cga->displine << 1) + 1][c + (cga->crtc[1] << 3) + 8] = (cga->cgacol & 15) + 16;
} else {
buffer32->line[(cga->displine << 1)][c + (cga->crtc[1] << 4) + 8] = buffer32->line[(cga->displine << 1) + 1][c + (cga->crtc[1] << 4) + 8] = (cga->cgacol & 15) + 16;
}
}
}
if (cga->cgamode & 1) {
for (x = 0; x < cga->crtc[1]; x++) {
if (cga->cgamode & 8) {
chr = cga->charbuffer[x << 1];
attr = cga->charbuffer[(x << 1) + 1];
} else
chr = attr = 0;
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
cols[1] = (attr & 15) + 16;
if (cga->cgamode & 0x20) {
cols[0] = ((attr >> 4) & 7) + 16;
if ((cga->cgablink & 8) && (attr & 0x80) && !cga->drawcursor)
cols[1] = cols[0];
} else
cols[0] = (attr >> 4) + 16;
if (drawcursor) {
for (c = 0; c < 8; c++) {
buffer32->line[(cga->displine << 1)][(x << 3) + c + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
}
} else {
for (c = 0; c < 8; c++) {
buffer32->line[(cga->displine << 1)][(x << 3) + c + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
}
cga->ma++;
}
} else if (!(cga->cgamode & 2)) {
for (x = 0; x < cga->crtc[1]; x++) {
if (cga->cgamode & 8) {
chr = cga->vram[((cga->ma << 1) & 0x3fff)];
attr = cga->vram[(((cga->ma << 1) + 1) & 0x3fff)];
} else
chr = attr = 0;
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
cols[1] = (attr & 15) + 16;
if (cga->cgamode & 0x20) {
cols[0] = ((attr >> 4) & 7) + 16;
if ((cga->cgablink & 8) && (attr & 0x80))
cols[1] = cols[0];
} else
cols[0] = (attr >> 4) + 16;
cga->ma++;
if (drawcursor) {
for (c = 0; c < 8; c++) {
buffer32->line[(cga->displine << 1)][(x << 4) + (c << 1) + 8] = buffer32->line[(cga->displine << 1)][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
}
} else {
for (c = 0; c < 8; c++) {
buffer32->line[(cga->displine << 1)][(x << 4) + (c << 1) + 8] = buffer32->line[(cga->displine << 1)][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
}
}
} else if (!(cga->cgamode & 16)) {
cols[0] = (cga->cgacol & 15) | 16;
col = (cga->cgacol & 16) ? 24 : 16;
if (cga->cgamode & 4) {
cols[1] = col | 3; /* Cyan */
cols[2] = col | 4; /* Red */
cols[3] = col | 7; /* White */
} else if (cga->cgacol & 32) {
cols[1] = col | 3; /* Cyan */
cols[2] = col | 5; /* Magenta */
cols[3] = col | 7; /* White */
} else {
cols[1] = col | 2; /* Green */
cols[2] = col | 4; /* Red */
cols[3] = col | 6; /* Yellow */
}
for (x = 0; x < cga->crtc[1]; x++) {
if (cga->cgamode & 8)
dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
else
dat = 0;
cga->ma++;
for (c = 0; c < 8; c++) {
buffer32->line[(cga->displine << 1)][(x << 4) + (c << 1) + 8] = buffer32->line[(cga->displine << 1)][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14];
dat <<= 2;
}
}
} else {
cols[0] = 0;
cols[1] = (cga->cgacol & 15) + 16;
for (x = 0; x < cga->crtc[1]; x++) {
if (cga->cgamode & 8)
dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
else
dat = 0;
cga->ma++;
for (c = 0; c < 16; c++) {
buffer32->line[(cga->displine << 1)][(x << 4) + c + 8] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + c + 8] = cols[dat >> 15];
dat <<= 1;
}
}
}
} else {
cols[0] = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15) + 16;
if (cga->cgamode & 1) {
hline(buffer32, 0, (cga->displine << 1), ((cga->crtc[1] << 3) + 16) << 2, cols[0]);
hline(buffer32, 0, (cga->displine << 1) + 1, ((cga->crtc[1] << 3) + 16) << 2, cols[0]);
} else {
hline(buffer32, 0, (cga->displine << 1), ((cga->crtc[1] << 4) + 16) << 2, cols[0]);
hline(buffer32, 0, (cga->displine << 1) + 1, ((cga->crtc[1] << 4) + 16) << 2, cols[0]);
}
}
if (cga->cgamode & 1)
x = (cga->crtc[1] << 3) + 16;
else
x = (cga->crtc[1] << 4) + 16;
if (cga->cgamode & 1)
x = (cga->crtc[1] << 3) + 16;
else
x = (cga->crtc[1] << 4) + 16;
if (cga->composite) {
if (cga->cgamode & 0x10)
border = 0x00;
else
border = cga->cgacol & 0x0f;
if (cga->composite) {
if (cga->cgamode & 0x10)
border = 0x00;
else
border = cga->cgacol & 0x0f;
Composite_Process(cga->cgamode, border, x >> 2, buffer32->line[(cga->displine << 1)]);
Composite_Process(cga->cgamode, border, x >> 2, buffer32->line[(cga->displine << 1) + 1]);
}
Composite_Process(cga->cgamode, border, x >> 2, buffer32->line[(cga->displine << 1)]);
Composite_Process(cga->cgamode, border, x >> 2, buffer32->line[(cga->displine << 1) + 1]);
}
cga->sc = oldsc;
if (cga->vc == cga->crtc[7] && !cga->sc)
cga->cgastat |= 8;
cga->displine++;
if (cga->displine >= 360)
cga->displine = 0;
cga->sc = oldsc;
if (cga->vc == cga->crtc[7] && !cga->sc)
cga->cgastat |= 8;
cga->displine++;
if (cga->displine >= 360)
cga->displine = 0;
} else {
timer_advance_u64(&cga->timer, cga->dispontime);
cga->linepos = 0;
if (cga->vsynctime) {
cga->vsynctime--;
if (!cga->vsynctime)
cga->cgastat &= ~8;
}
if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[11] & 31) >> 1))) {
cga->con = 0;
cga->coff = 1;
}
if ((cga->crtc[8] & 3) == 3 && cga->sc == (cga->crtc[9] >> 1))
cga->maback = cga->ma;
if (cga->vadj) {
cga->sc++;
cga->sc &= 31;
cga->ma = cga->maback;
cga->vadj--;
if (!cga->vadj) {
cga->cgadispon = 1;
cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff;
cga->sc = 0;
}
} else if (cga->sc == cga->crtc[9]) {
cga->maback = cga->ma;
cga->sc = 0;
oldvc = cga->vc;
cga->vc++;
cga->vc &= 127;
timer_advance_u64(&cga->timer, cga->dispontime);
cga->linepos = 0;
if (cga->vsynctime) {
cga->vsynctime--;
if (!cga->vsynctime)
cga->cgastat &= ~8;
}
if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[11] & 31) >> 1))) {
cga->con = 0;
cga->coff = 1;
}
if ((cga->crtc[8] & 3) == 3 && cga->sc == (cga->crtc[9] >> 1))
cga->maback = cga->ma;
if (cga->vadj) {
cga->sc++;
cga->sc &= 31;
cga->ma = cga->maback;
cga->vadj--;
if (!cga->vadj) {
cga->cgadispon = 1;
cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff;
cga->sc = 0;
}
} else if (cga->sc == cga->crtc[9]) {
cga->maback = cga->ma;
cga->sc = 0;
oldvc = cga->vc;
cga->vc++;
cga->vc &= 127;
if (cga->vc == cga->crtc[6])
cga->cgadispon = 0;
if (cga->vc == cga->crtc[6])
cga->cgadispon = 0;
if (oldvc == cga->crtc[4]) {
cga->vc = 0;
cga->vadj = cga->crtc[5];
if (!cga->vadj) {
cga->cgadispon = 1;
cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff;
}
switch (cga->crtc[10] & 0x60) {
case 0x20:
cga->cursoron = 0;
break;
case 0x60:
cga->cursoron = cga->cgablink & 0x10;
break;
default:
cga->cursoron = cga->cgablink & 0x08;
break;
}
}
if (oldvc == cga->crtc[4]) {
cga->vc = 0;
cga->vadj = cga->crtc[5];
if (!cga->vadj) {
cga->cgadispon = 1;
cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff;
}
switch (cga->crtc[10] & 0x60) {
case 0x20:
cga->cursoron = 0;
break;
case 0x60:
cga->cursoron = cga->cgablink & 0x10;
break;
default:
cga->cursoron = cga->cgablink & 0x08;
break;
}
}
if (cga->vc == cga->crtc[7]) {
cga->cgadispon = 0;
cga->displine = 0;
cga->vsynctime = 16;
if (cga->crtc[7]) {
if (cga->cgamode & 1)
x = (cga->crtc[1] << 3) + 16;
else
x = (cga->crtc[1] << 4) + 16;
cga->lastline++;
if (cga->vc == cga->crtc[7]) {
cga->cgadispon = 0;
cga->displine = 0;
cga->vsynctime = 16;
if (cga->crtc[7]) {
if (cga->cgamode & 1)
x = (cga->crtc[1] << 3) + 16;
else
x = (cga->crtc[1] << 4) + 16;
cga->lastline++;
xs_temp = x;
ys_temp = (cga->lastline - cga->firstline) << 1;
xs_temp = x;
ys_temp = (cga->lastline - cga->firstline) << 1;
if ((xs_temp > 0) && (ys_temp > 0)) {
if (xs_temp < 64) xs_temp = 656;
if (ys_temp < 32) ys_temp = 400;
if (!enable_overscan)
xs_temp -= 16;
if ((xs_temp > 0) && (ys_temp > 0)) {
if (xs_temp < 64)
xs_temp = 656;
if (ys_temp < 32)
ys_temp = 400;
if (!enable_overscan)
xs_temp -= 16;
if ((cga->cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) {
xsize = xs_temp;
ysize = ys_temp;
set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0));
if ((cga->cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) {
xsize = xs_temp;
ysize = ys_temp;
set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0));
if (video_force_resize_get())
video_force_resize_set(0);
}
if (video_force_resize_get())
video_force_resize_set(0);
}
if (enable_overscan) {
if (cga->composite)
video_blit_memtoscreen(0, (cga->firstline - 4) << 1,
xsize, ((cga->lastline - cga->firstline) + 8) << 1);
else
video_blit_memtoscreen_8(0, (cga->firstline - 4) << 1,
xsize, ((cga->lastline - cga->firstline) + 8) << 1);
} else {
if (cga->composite)
video_blit_memtoscreen(8, cga->firstline << 1,
xsize, (cga->lastline - cga->firstline) << 1);
else
video_blit_memtoscreen_8(8, cga->firstline << 1,
xsize, (cga->lastline - cga->firstline) << 1);
}
}
if (enable_overscan) {
if (cga->composite)
video_blit_memtoscreen(0, (cga->firstline - 4) << 1,
xsize, ((cga->lastline - cga->firstline) + 8) << 1);
else
video_blit_memtoscreen_8(0, (cga->firstline - 4) << 1,
xsize, ((cga->lastline - cga->firstline) + 8) << 1);
} else {
if (cga->composite)
video_blit_memtoscreen(8, cga->firstline << 1,
xsize, (cga->lastline - cga->firstline) << 1);
else
video_blit_memtoscreen_8(8, cga->firstline << 1,
xsize, (cga->lastline - cga->firstline) << 1);
}
}
frames++;
frames++;
video_res_x = xsize;
video_res_y = ysize;
if (cga->cgamode & 1) {
video_res_x /= 8;
video_res_y /= cga->crtc[9] + 1;
video_bpp = 0;
} else if (!(cga->cgamode & 2)) {
video_res_x /= 16;
video_res_y /= cga->crtc[9] + 1;
video_bpp = 0;
} else if (!(cga->cgamode & 16)) {
video_res_x /= 2;
video_bpp = 2;
} else
video_bpp = 1;
}
cga->firstline = 1000;
cga->lastline = 0;
cga->cgablink++;
cga->oddeven ^= 1;
}
} else {
cga->sc++;
cga->sc &= 31;
cga->ma = cga->maback;
}
if (cga->cgadispon)
cga->cgastat &= ~1;
if ((cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[10] & 31) >> 1))))
cga->con = 1;
if (cga->cgadispon && (cga->cgamode & 1)) {
for (x = 0; x < (cga->crtc[1] << 1); x++)
cga->charbuffer[x] = cga->vram[(((cga->ma << 1) + x) & 0x3fff)];
}
video_res_x = xsize;
video_res_y = ysize;
if (cga->cgamode & 1) {
video_res_x /= 8;
video_res_y /= cga->crtc[9] + 1;
video_bpp = 0;
} else if (!(cga->cgamode & 2)) {
video_res_x /= 16;
video_res_y /= cga->crtc[9] + 1;
video_bpp = 0;
} else if (!(cga->cgamode & 16)) {
video_res_x /= 2;
video_bpp = 2;
} else
video_bpp = 1;
}
cga->firstline = 1000;
cga->lastline = 0;
cga->cgablink++;
cga->oddeven ^= 1;
}
} else {
cga->sc++;
cga->sc &= 31;
cga->ma = cga->maback;
}
if (cga->cgadispon)
cga->cgastat &= ~1;
if ((cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[10] & 31) >> 1))))
cga->con = 1;
if (cga->cgadispon && (cga->cgamode & 1)) {
for (x = 0; x < (cga->crtc[1] << 1); x++)
cga->charbuffer[x] = cga->vram[(((cga->ma << 1) + x) & 0x3fff)];
}
}
}
void
cga_init(cga_t *cga)
{
@@ -525,19 +494,18 @@ cga_init(cga_t *cga)
cga->composite = 0;
}
void *
cga_standalone_init(const device_t *info)
{
int display_type;
int display_type;
cga_t *cga = malloc(sizeof(cga_t));
memset(cga, 0, sizeof(cga_t));
video_inform(VIDEO_FLAG_TYPE_CGA, &timing_cga);
display_type = device_get_config_int("display_type");
cga->composite = (display_type != CGA_RGB);
cga->revision = device_get_config_int("composite_type");
display_type = device_get_config_int("display_type");
cga->composite = (display_type != CGA_RGB);
cga->revision = device_get_config_int("composite_type");
cga->snow_enabled = device_get_config_int("snow_enabled");
cga->vram = malloc(0x4000);
@@ -550,13 +518,12 @@ cga_standalone_init(const device_t *info)
overscan_x = overscan_y = 16;
cga->rgb_type = device_get_config_int("rgb_type");
cga_palette = (cga->rgb_type << 1);
cga_palette = (cga->rgb_type << 1);
cgapal_rebuild();
return cga;
}
void
cga_close(void *p)
{
@@ -566,7 +533,6 @@ cga_close(void *p)
free(cga);
}
void
cga_speed_changed(void *p)
{
@@ -659,15 +625,15 @@ const device_config_t cga_config[] = {
// clang-format on
const device_t cga_device = {
.name = "CGA",
.name = "CGA",
.internal_name = "cga",
.flags = DEVICE_ISA,
.local = 0,
.init = cga_standalone_init,
.close = cga_close,
.reset = NULL,
.flags = DEVICE_ISA,
.local = 0,
.init = cga_standalone_init,
.close = cga_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = cga_speed_changed,
.force_redraw = NULL,
.config = cga_config
.force_redraw = NULL,
.config = cga_config
};

View File

@@ -29,14 +29,12 @@
#include <86box/vid_cga.h>
#include <86box/vid_cga_comp.h>
int CGA_Composite_Table[1024];
static double brightness = 0;
static double contrast = 100;
static double contrast = 100;
static double saturation = 100;
static double sharpness = 0;
static double sharpness = 0;
static double hue_offset = 0;
/* New algorithm by reenigne
@@ -45,6 +43,7 @@ static double hue_offset = 0;
static const double tau = 6.28318531; /* == 2*pi */
static unsigned char chroma_multiplexer[256] = {
// clang-format off
2, 2, 2, 2, 114,174, 4, 3, 2, 1,133,135, 2,113,150, 4,
133, 2, 1, 99, 151,152, 2, 1, 3, 2, 96,136, 151,152,151,152,
2, 56, 62, 4, 111,250,118, 4, 0, 51,207,137, 1,171,209, 5,
@@ -60,12 +59,15 @@ static unsigned char chroma_multiplexer[256] = {
78, 4, 0, 75, 166,180, 20, 38, 78, 1,143,246, 42,113,156, 37,
252, 4, 1,188, 175,129, 1, 37, 118, 4, 88,249, 202,150,145,200,
61, 59, 60, 60, 228,252,117, 77, 60, 58,248,251, 81,212,254,107,
198, 59, 58,169, 250,251, 81, 80, 100, 58,154,250, 251,252,252,252};
198, 59, 58,169, 250,251, 81, 80, 100, 58,154,250, 251,252,252,252
// clang-format on
};
static double intensity[4] = {
77.175381, 88.654656, 166.564623, 174.228438};
77.175381, 88.654656, 166.564623, 174.228438
};
#define NEW_CGA(c,i,r,g,b) (((c)/0.72)*0.29 + ((i)/0.28)*0.32 + ((r)/0.28)*0.1 + ((g)/0.28)*0.22 + ((b)/0.28)*0.07)
#define NEW_CGA(c, i, r, g, b) (((c) / 0.72) * 0.29 + ((i) / 0.28) * 0.32 + ((r) / 0.28) * 0.1 + ((g) / 0.28) * 0.22 + ((b) / 0.28) * 0.07)
double mode_brightness;
double mode_contrast;
@@ -74,272 +76,291 @@ double min_v;
double max_v;
double video_ri, video_rq, video_gi, video_gq, video_bi, video_bq;
int video_sharpness;
int tandy_mode_control = 0;
int video_sharpness;
int tandy_mode_control = 0;
static bool new_cga = 0;
void update_cga16_color(uint8_t cgamode) {
int x;
double c, i, v;
double q, a, s, r;
double iq_adjust_i, iq_adjust_q;
double i0, i3, mode_saturation;
void
update_cga16_color(uint8_t cgamode)
{
int x;
double c, i, v;
double q, a, s, r;
double iq_adjust_i, iq_adjust_q;
double i0, i3, mode_saturation;
static const double ri = 0.9563;
static const double rq = 0.6210;
static const double gi = -0.2721;
static const double gq = -0.6474;
static const double bi = -1.1069;
static const double bq = 1.7046;
static const double ri = 0.9563;
static const double rq = 0.6210;
static const double gi = -0.2721;
static const double gq = -0.6474;
static const double bi = -1.1069;
static const double bq = 1.7046;
if (!new_cga) {
min_v = chroma_multiplexer[0] + intensity[0];
max_v = chroma_multiplexer[255] + intensity[3];
if (!new_cga) {
min_v = chroma_multiplexer[0] + intensity[0];
max_v = chroma_multiplexer[255] + intensity[3];
} else {
i0 = intensity[0];
i3 = intensity[3];
min_v = NEW_CGA(chroma_multiplexer[0], i0, i0, i0, i0);
max_v = NEW_CGA(chroma_multiplexer[255], i3, i3, i3, i3);
}
mode_contrast = 256 / (max_v - min_v);
mode_brightness = -min_v * mode_contrast;
if ((cgamode & 3) == 1)
mode_hue = 14;
else
mode_hue = 4;
mode_contrast *= contrast * (new_cga ? 1.2 : 1) / 100; /* new CGA: 120% */
mode_brightness += (new_cga ? brightness - 10 : brightness) * 5; /* new CGA: -10 */
mode_saturation = (new_cga ? 4.35 : 2.9) * saturation / 100; /* new CGA: 150% */
for (x = 0; x < 1024; ++x) {
int phase = x & 3;
int right = (x >> 2) & 15;
int left = (x >> 6) & 15;
int rc = right;
int lc = left;
if ((cgamode & 4) != 0) {
rc = (right & 8) | ((right & 7) != 0 ? 7 : 0);
lc = (left & 8) | ((left & 7) != 0 ? 7 : 0);
}
c = chroma_multiplexer[((lc & 7) << 5) | ((rc & 7) << 2) | phase];
i = intensity[(left >> 3) | ((right >> 2) & 2)];
if (!new_cga)
v = c + i;
else {
i0 = intensity[0];
i3 = intensity[3];
min_v = NEW_CGA(chroma_multiplexer[0], i0, i0, i0, i0);
max_v = NEW_CGA(chroma_multiplexer[255], i3, i3, i3, i3);
double r = intensity[((left >> 2) & 1) | ((right >> 1) & 2)];
double g = intensity[((left >> 1) & 1) | (right & 2)];
double b = intensity[(left & 1) | ((right << 1) & 2)];
v = NEW_CGA(c, i, r, g, b);
}
mode_contrast = 256/(max_v - min_v);
mode_brightness = -min_v*mode_contrast;
if ((cgamode & 3) == 1)
mode_hue = 14;
else
mode_hue = 4;
CGA_Composite_Table[x] = (int) (v * mode_contrast + mode_brightness);
}
mode_contrast *= contrast * (new_cga ? 1.2 : 1)/100; /* new CGA: 120% */
mode_brightness += (new_cga ? brightness-10 : brightness)*5; /* new CGA: -10 */
mode_saturation = (new_cga ? 4.35 : 2.9)*saturation/100; /* new CGA: 150% */
i = CGA_Composite_Table[6 * 68] - CGA_Composite_Table[6 * 68 + 2];
q = CGA_Composite_Table[6 * 68 + 1] - CGA_Composite_Table[6 * 68 + 3];
for (x = 0; x < 1024; ++x) {
int phase = x & 3;
int right = (x >> 2) & 15;
int left = (x >> 6) & 15;
int rc = right;
int lc = left;
if ((cgamode & 4) != 0) {
rc = (right & 8) | ((right & 7) != 0 ? 7 : 0);
lc = (left & 8) | ((left & 7) != 0 ? 7 : 0);
}
c = chroma_multiplexer[((lc & 7) << 5) | ((rc & 7) << 2) | phase];
i = intensity[(left >> 3) | ((right >> 2) & 2)];
if (!new_cga)
v = c + i;
else {
double r = intensity[((left >> 2) & 1) | ((right >> 1) & 2)];
double g = intensity[((left >> 1) & 1) | (right & 2)];
double b = intensity[(left & 1) | ((right << 1) & 2)];
v = NEW_CGA(c, i, r, g, b);
}
CGA_Composite_Table[x] = (int) (v*mode_contrast + mode_brightness);
}
a = tau * (33 + 90 + hue_offset + mode_hue) / 360.0;
c = cos(a);
s = sin(a);
r = 256 * mode_saturation / sqrt(i * i + q * q);
i = CGA_Composite_Table[6*68] - CGA_Composite_Table[6*68 + 2];
q = CGA_Composite_Table[6*68 + 1] - CGA_Composite_Table[6*68 + 3];
iq_adjust_i = -(i * c + q * s) * r;
iq_adjust_q = (q * c - i * s) * r;
a = tau*(33 + 90 + hue_offset + mode_hue)/360.0;
c = cos(a);
s = sin(a);
r = 256*mode_saturation/sqrt(i*i+q*q);
iq_adjust_i = -(i*c + q*s)*r;
iq_adjust_q = (q*c - i*s)*r;
video_ri = (int) (ri*iq_adjust_i + rq*iq_adjust_q);
video_rq = (int) (-ri*iq_adjust_q + rq*iq_adjust_i);
video_gi = (int) (gi*iq_adjust_i + gq*iq_adjust_q);
video_gq = (int) (-gi*iq_adjust_q + gq*iq_adjust_i);
video_bi = (int) (bi*iq_adjust_i + bq*iq_adjust_q);
video_bq = (int) (-bi*iq_adjust_q + bq*iq_adjust_i);
video_sharpness = (int) (sharpness*256/100);
video_ri = (int) (ri * iq_adjust_i + rq * iq_adjust_q);
video_rq = (int) (-ri * iq_adjust_q + rq * iq_adjust_i);
video_gi = (int) (gi * iq_adjust_i + gq * iq_adjust_q);
video_gq = (int) (-gi * iq_adjust_q + gq * iq_adjust_i);
video_bi = (int) (bi * iq_adjust_i + bq * iq_adjust_q);
video_bq = (int) (-bi * iq_adjust_q + bq * iq_adjust_i);
video_sharpness = (int) (sharpness * 256 / 100);
}
static Bit8u byte_clamp(int v) {
v >>= 13;
return v < 0 ? 0 : (v > 255 ? 255 : v);
static Bit8u
byte_clamp(int v)
{
v >>= 13;
return v < 0 ? 0 : (v > 255 ? 255 : v);
}
/* 2048x1536 is the maximum we can possibly support. */
#define SCALER_MAXWIDTH 2048
static int temp[SCALER_MAXWIDTH + 10]={0};
static int atemp[SCALER_MAXWIDTH + 2]={0};
static int btemp[SCALER_MAXWIDTH + 2]={0};
static int temp[SCALER_MAXWIDTH + 10] = { 0 };
static int atemp[SCALER_MAXWIDTH + 2] = { 0 };
static int btemp[SCALER_MAXWIDTH + 2] = { 0 };
Bit32u * Composite_Process(uint8_t cgamode, Bit8u border, Bit32u blocks/*, bool doublewidth*/, Bit32u *TempLine)
Bit32u *
Composite_Process(uint8_t cgamode, Bit8u border, Bit32u blocks /*, bool doublewidth*/, Bit32u *TempLine)
{
int x;
Bit32u x2;
int x;
Bit32u x2;
int w = blocks*4;
int w = blocks * 4;
int *o;
Bit32u *rgbi;
int *b;
int *i;
Bit32u* srgb;
int *ap, *bp;
int *o;
Bit32u *rgbi;
int *b;
int *i;
Bit32u *srgb;
int *ap, *bp;
#define COMPOSITE_CONVERT(I, Q) do { \
i[1] = (i[1]<<3) - ap[1]; \
a = ap[0]; \
b = bp[0]; \
c = i[0]+i[0]; \
d = i[-1]+i[1]; \
y = ((c+d)<<8) + video_sharpness*(c-d); \
rr = y + video_ri*(I) + video_rq*(Q); \
gg = y + video_gi*(I) + video_gq*(Q); \
bb = y + video_bi*(I) + video_bq*(Q); \
++i; \
++ap; \
++bp; \
*srgb = (byte_clamp(rr)<<16) | (byte_clamp(gg)<<8) | byte_clamp(bb); \
++srgb; \
} while (0)
#define COMPOSITE_CONVERT(I, Q) \
do { \
i[1] = (i[1] << 3) - ap[1]; \
a = ap[0]; \
b = bp[0]; \
c = i[0] + i[0]; \
d = i[-1] + i[1]; \
y = ((c + d) << 8) + video_sharpness * (c - d); \
rr = y + video_ri * (I) + video_rq * (Q); \
gg = y + video_gi * (I) + video_gq * (Q); \
bb = y + video_bi * (I) + video_bq * (Q); \
++i; \
++ap; \
++bp; \
*srgb = (byte_clamp(rr) << 16) | (byte_clamp(gg) << 8) | byte_clamp(bb); \
++srgb; \
} while (0)
#define OUT(v) do { *o = (v); ++o; } while (0)
#define OUT(v) \
do { \
*o = (v); \
++o; \
} while (0)
/* Simulate CGA composite output */
o = temp;
rgbi = TempLine;
b = &CGA_Composite_Table[border*68];
for (x = 0; x < 4; ++x)
OUT(b[(x+3)&3]);
OUT(CGA_Composite_Table[(border<<6) | ((*rgbi & 0x0f)<<2) | 3]);
for (x = 0; x < w-1; ++x) {
OUT(CGA_Composite_Table[((rgbi[0] & 0x0f)<<6) | ((rgbi[1] & 0x0f)<<2) | (x&3)]);
++rgbi;
/* Simulate CGA composite output */
o = temp;
rgbi = TempLine;
b = &CGA_Composite_Table[border * 68];
for (x = 0; x < 4; ++x)
OUT(b[(x + 3) & 3]);
OUT(CGA_Composite_Table[(border << 6) | ((*rgbi & 0x0f) << 2) | 3]);
for (x = 0; x < w - 1; ++x) {
OUT(CGA_Composite_Table[((rgbi[0] & 0x0f) << 6) | ((rgbi[1] & 0x0f) << 2) | (x & 3)]);
++rgbi;
}
OUT(CGA_Composite_Table[((*rgbi & 0x0f) << 6) | (border << 2) | 3]);
for (x = 0; x < 5; ++x)
OUT(b[x & 3]);
if ((cgamode & 4) != 0) {
/* Decode */
i = temp + 5;
srgb = (Bit32u *) TempLine;
for (x2 = 0; x2 < blocks * 4; ++x2) {
int c = (i[0] + i[0]) << 3;
int d = (i[-1] + i[1]) << 3;
int y = ((c + d) << 8) + video_sharpness * (c - d);
++i;
*srgb = byte_clamp(y) * 0x10101;
++srgb;
}
OUT(CGA_Composite_Table[((*rgbi & 0x0f)<<6) | (border<<2) | 3]);
for (x = 0; x < 5; ++x)
OUT(b[x&3]);
if ((cgamode & 4) != 0) {
/* Decode */
i = temp + 5;
srgb = (Bit32u *)TempLine;
for (x2 = 0; x2 < blocks*4; ++x2) {
int c = (i[0]+i[0])<<3;
int d = (i[-1]+i[1])<<3;
int y = ((c+d)<<8) + video_sharpness*(c-d);
++i;
*srgb = byte_clamp(y)*0x10101;
++srgb;
}
} else {
/* Store chroma */
i = temp + 4;
ap = atemp + 1;
bp = btemp + 1;
for (x = -1; x < w + 1; ++x) {
ap[x] = i[-4] - ((i[-2] - i[0] + i[2]) << 1) + i[4];
bp[x] = (i[-3] - i[-1] + i[1] - i[3]) << 1;
++i;
}
else {
/* Store chroma */
i = temp + 4;
ap = atemp + 1;
bp = btemp + 1;
for (x = -1; x < w + 1; ++x) {
ap[x] = i[-4]-((i[-2]-i[0]+i[2])<<1)+i[4];
bp[x] = (i[-3]-i[-1]+i[1]-i[3])<<1;
++i;
}
/* Decode */
i = temp + 5;
i[-1] = (i[-1]<<3) - ap[-1];
i[0] = (i[0]<<3) - ap[0];
srgb = (Bit32u *)TempLine;
for (x2 = 0; x2 < blocks; ++x2) {
int y,a,b,c,d,rr,gg,bb;
COMPOSITE_CONVERT(a, b);
COMPOSITE_CONVERT(-b, a);
COMPOSITE_CONVERT(-a, -b);
COMPOSITE_CONVERT(b, -a);
}
/* Decode */
i = temp + 5;
i[-1] = (i[-1] << 3) - ap[-1];
i[0] = (i[0] << 3) - ap[0];
srgb = (Bit32u *) TempLine;
for (x2 = 0; x2 < blocks; ++x2) {
int y, a, b, c, d, rr, gg, bb;
COMPOSITE_CONVERT(a, b);
COMPOSITE_CONVERT(-b, a);
COMPOSITE_CONVERT(-a, -b);
COMPOSITE_CONVERT(b, -a);
}
}
#undef COMPOSITE_CONVERT
#undef OUT
return TempLine;
return TempLine;
}
void IncreaseHue(uint8_t cgamode)
void
IncreaseHue(uint8_t cgamode)
{
hue_offset += 5.0;
hue_offset += 5.0;
update_cga16_color(cgamode);
update_cga16_color(cgamode);
}
void DecreaseHue(uint8_t cgamode)
void
DecreaseHue(uint8_t cgamode)
{
hue_offset -= 5.0;
hue_offset -= 5.0;
update_cga16_color(cgamode);
update_cga16_color(cgamode);
}
void IncreaseSaturation(uint8_t cgamode)
void
IncreaseSaturation(uint8_t cgamode)
{
saturation += 5;
saturation += 5;
update_cga16_color(cgamode);
update_cga16_color(cgamode);
}
void DecreaseSaturation(uint8_t cgamode)
void
DecreaseSaturation(uint8_t cgamode)
{
saturation -= 5;
saturation -= 5;
update_cga16_color(cgamode);
update_cga16_color(cgamode);
}
void IncreaseContrast(uint8_t cgamode)
void
IncreaseContrast(uint8_t cgamode)
{
contrast += 5;
contrast += 5;
update_cga16_color(cgamode);
update_cga16_color(cgamode);
}
void DecreaseContrast(uint8_t cgamode)
void
DecreaseContrast(uint8_t cgamode)
{
contrast -= 5;
contrast -= 5;
update_cga16_color(cgamode);
update_cga16_color(cgamode);
}
void IncreaseBrightness(uint8_t cgamode)
void
IncreaseBrightness(uint8_t cgamode)
{
brightness += 5;
brightness += 5;
update_cga16_color(cgamode);
update_cga16_color(cgamode);
}
void DecreaseBrightness(uint8_t cgamode)
void
DecreaseBrightness(uint8_t cgamode)
{
brightness -= 5;
brightness -= 5;
update_cga16_color(cgamode);
update_cga16_color(cgamode);
}
void IncreaseSharpness(uint8_t cgamode)
void
IncreaseSharpness(uint8_t cgamode)
{
sharpness += 10;
sharpness += 10;
update_cga16_color(cgamode);
update_cga16_color(cgamode);
}
void DecreaseSharpness(uint8_t cgamode)
void
DecreaseSharpness(uint8_t cgamode)
{
sharpness -= 10;
sharpness -= 10;
update_cga16_color(cgamode);
update_cga16_color(cgamode);
}
void cga_comp_init(int revision)
void
cga_comp_init(int revision)
{
new_cga = revision;
new_cga = revision;
/* Making sure this gets reset after reset. */
brightness = 0;
contrast = 100;
saturation = 100;
sharpness = 0;
hue_offset = 0;
/* Making sure this gets reset after reset. */
brightness = 0;
contrast = 100;
saturation = 100;
sharpness = 0;
hue_offset = 0;
update_cga16_color(0);
update_cga16_color(0);
}

File diff suppressed because it is too large Load Diff

View File

@@ -35,400 +35,350 @@
#include <86box/vid_colorplus.h>
#include <86box/vid_cga_comp.h>
/* Bits in the colorplus control register: */
#define COLORPLUS_PLANE_SWAP 0x40 /* Swap planes at 0000h and 4000h */
#define COLORPLUS_640x200_MODE 0x20 /* 640x200x4 mode active */
#define COLORPLUS_320x200_MODE 0x10 /* 320x200x16 mode active */
#define COLORPLUS_EITHER_MODE 0x30 /* Either mode active */
#define COLORPLUS_PLANE_SWAP 0x40 /* Swap planes at 0000h and 4000h */
#define COLORPLUS_640x200_MODE 0x20 /* 640x200x4 mode active */
#define COLORPLUS_320x200_MODE 0x10 /* 320x200x16 mode active */
#define COLORPLUS_EITHER_MODE 0x30 /* Either mode active */
/* Bits in the CGA graphics mode register */
#define CGA_GRAPHICS_MODE 0x02 /* CGA graphics mode selected? */
#define CGA_GRAPHICS_MODE 0x02 /* CGA graphics mode selected? */
#define CGA_RGB 0
#define CGA_COMPOSITE 1
#define CGA_RGB 0
#define CGA_COMPOSITE 1
#define COMPOSITE_OLD 0
#define COMPOSITE_NEW 1
video_timings_t timing_colorplus = {VIDEO_ISA, 8, 16, 32, 8, 16, 32};
#define COMPOSITE_OLD 0
#define COMPOSITE_NEW 1
video_timings_t timing_colorplus = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 };
void cga_recalctimings(cga_t *cga);
void colorplus_out(uint16_t addr, uint8_t val, void *p)
void
colorplus_out(uint16_t addr, uint8_t val, void *p)
{
colorplus_t *colorplus = (colorplus_t *)p;
colorplus_t *colorplus = (colorplus_t *) p;
if (addr == 0x3DD)
{
colorplus->control = val & 0x70;
}
else
{
cga_out(addr, val, &colorplus->cga);
}
if (addr == 0x3DD) {
colorplus->control = val & 0x70;
} else {
cga_out(addr, val, &colorplus->cga);
}
}
uint8_t colorplus_in(uint16_t addr, void *p)
uint8_t
colorplus_in(uint16_t addr, void *p)
{
colorplus_t *colorplus = (colorplus_t *)p;
colorplus_t *colorplus = (colorplus_t *) p;
return cga_in(addr, &colorplus->cga);
return cga_in(addr, &colorplus->cga);
}
void colorplus_write(uint32_t addr, uint8_t val, void *p)
void
colorplus_write(uint32_t addr, uint8_t val, void *p)
{
colorplus_t *colorplus = (colorplus_t *)p;
colorplus_t *colorplus = (colorplus_t *) p;
if ((colorplus->control & COLORPLUS_PLANE_SWAP) &&
(colorplus->control & COLORPLUS_EITHER_MODE) &&
(colorplus->cga.cgamode & CGA_GRAPHICS_MODE))
{
addr ^= 0x4000;
}
else if (!(colorplus->control & COLORPLUS_EITHER_MODE))
{
addr &= 0x3FFF;
}
colorplus->cga.vram[addr & 0x7fff] = val;
if (colorplus->cga.snow_enabled)
if ((colorplus->control & COLORPLUS_PLANE_SWAP) && (colorplus->control & COLORPLUS_EITHER_MODE) && (colorplus->cga.cgamode & CGA_GRAPHICS_MODE)) {
addr ^= 0x4000;
} else if (!(colorplus->control & COLORPLUS_EITHER_MODE)) {
addr &= 0x3FFF;
}
colorplus->cga.vram[addr & 0x7fff] = val;
if (colorplus->cga.snow_enabled) {
int offset = ((timer_get_remaining_u64(&colorplus->cga.timer) / CGACONST) * 2) & 0xfc;
colorplus->cga.charbuffer[offset] = colorplus->cga.vram[addr & 0x7fff];
colorplus->cga.charbuffer[offset | 1] = colorplus->cga.vram[addr & 0x7fff];
}
cycles -= 4;
}
uint8_t
colorplus_read(uint32_t addr, void *p)
{
colorplus_t *colorplus = (colorplus_t *) p;
if ((colorplus->control & COLORPLUS_PLANE_SWAP) && (colorplus->control & COLORPLUS_EITHER_MODE) && (colorplus->cga.cgamode & CGA_GRAPHICS_MODE)) {
addr ^= 0x4000;
} else if (!(colorplus->control & COLORPLUS_EITHER_MODE)) {
addr &= 0x3FFF;
}
cycles -= 4;
if (colorplus->cga.snow_enabled) {
int offset = ((timer_get_remaining_u64(&colorplus->cga.timer) / CGACONST) * 2) & 0xfc;
colorplus->cga.charbuffer[offset] = colorplus->cga.vram[addr & 0x7fff];
colorplus->cga.charbuffer[offset | 1] = colorplus->cga.vram[addr & 0x7fff];
}
return colorplus->cga.vram[addr & 0x7fff];
}
void
colorplus_recalctimings(colorplus_t *colorplus)
{
cga_recalctimings(&colorplus->cga);
}
void
colorplus_poll(void *p)
{
colorplus_t *colorplus = (colorplus_t *) p;
int x, c;
int oldvc;
uint16_t dat0, dat1;
int cols[4];
int col;
int oldsc;
static const int cols16[16] = { 0x10, 0x12, 0x14, 0x16,
0x18, 0x1A, 0x1C, 0x1E,
0x11, 0x13, 0x15, 0x17,
0x19, 0x1B, 0x1D, 0x1F };
uint8_t *plane0 = colorplus->cga.vram;
uint8_t *plane1 = colorplus->cga.vram + 0x4000;
/* If one of the extra modes is not selected, drop down to the CGA
* drawing code. */
if (!((colorplus->control & COLORPLUS_EITHER_MODE) && (colorplus->cga.cgamode & CGA_GRAPHICS_MODE))) {
cga_poll(&colorplus->cga);
return;
}
if (!colorplus->cga.linepos) {
timer_advance_u64(&colorplus->cga.timer, colorplus->cga.dispofftime);
colorplus->cga.cgastat |= 1;
colorplus->cga.linepos = 1;
oldsc = colorplus->cga.sc;
if ((colorplus->cga.crtc[8] & 3) == 3)
colorplus->cga.sc = ((colorplus->cga.sc << 1) + colorplus->cga.oddeven) & 7;
if (colorplus->cga.cgadispon) {
if (colorplus->cga.displine < colorplus->cga.firstline) {
colorplus->cga.firstline = colorplus->cga.displine;
video_wait_for_buffer();
}
colorplus->cga.lastline = colorplus->cga.displine;
/* Left / right border */
for (c = 0; c < 8; c++) {
buffer32->line[colorplus->cga.displine][c] = buffer32->line[colorplus->cga.displine][c + (colorplus->cga.crtc[1] << 4) + 8] = (colorplus->cga.cgacol & 15) + 16;
}
if (colorplus->control & COLORPLUS_320x200_MODE) {
for (x = 0; x < colorplus->cga.crtc[1]; x++) {
dat0 = (plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1];
dat1 = (plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1];
colorplus->cga.ma++;
for (c = 0; c < 8; c++) {
buffer32->line[colorplus->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[colorplus->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols16[(dat0 >> 14) | ((dat1 >> 14) << 2)];
dat0 <<= 2;
dat1 <<= 2;
}
}
} else if (colorplus->control & COLORPLUS_640x200_MODE) {
cols[0] = (colorplus->cga.cgacol & 15) | 16;
col = (colorplus->cga.cgacol & 16) ? 24 : 16;
if (colorplus->cga.cgamode & 4) {
cols[1] = col | 3;
cols[2] = col | 4;
cols[3] = col | 7;
} else if (colorplus->cga.cgacol & 32) {
cols[1] = col | 3;
cols[2] = col | 5;
cols[3] = col | 7;
} else {
cols[1] = col | 2;
cols[2] = col | 4;
cols[3] = col | 6;
}
for (x = 0; x < colorplus->cga.crtc[1]; x++) {
dat0 = (plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1];
dat1 = (plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1];
colorplus->cga.ma++;
for (c = 0; c < 16; c++) {
buffer32->line[colorplus->cga.displine][(x << 4) + c + 8] = cols[(dat0 >> 15) | ((dat1 >> 15) << 1)];
dat0 <<= 1;
dat1 <<= 1;
}
}
}
} else /* Top / bottom border */
{
int offset = ((timer_get_remaining_u64(&colorplus->cga.timer) / CGACONST) * 2) & 0xfc;
colorplus->cga.charbuffer[offset] = colorplus->cga.vram[addr & 0x7fff];
colorplus->cga.charbuffer[offset | 1] = colorplus->cga.vram[addr & 0x7fff];
cols[0] = (colorplus->cga.cgacol & 15) + 16;
hline(buffer32, 0, colorplus->cga.displine, (colorplus->cga.crtc[1] << 4) + 16, cols[0]);
}
cycles -= 4;
}
uint8_t colorplus_read(uint32_t addr, void *p)
{
colorplus_t *colorplus = (colorplus_t *)p;
x = (colorplus->cga.crtc[1] << 4) + 16;
if ((colorplus->control & COLORPLUS_PLANE_SWAP) &&
(colorplus->control & COLORPLUS_EITHER_MODE) &&
(colorplus->cga.cgamode & CGA_GRAPHICS_MODE))
{
addr ^= 0x4000;
}
else if (!(colorplus->control & COLORPLUS_EITHER_MODE))
{
addr &= 0x3FFF;
}
cycles -= 4;
if (colorplus->cga.snow_enabled)
{
int offset = ((timer_get_remaining_u64(&colorplus->cga.timer) / CGACONST) * 2) & 0xfc;
colorplus->cga.charbuffer[offset] = colorplus->cga.vram[addr & 0x7fff];
colorplus->cga.charbuffer[offset | 1] = colorplus->cga.vram[addr & 0x7fff];
if (colorplus->cga.composite)
Composite_Process(colorplus->cga.cgamode, 0, x >> 2, buffer32->line[colorplus->cga.displine]);
colorplus->cga.sc = oldsc;
if (colorplus->cga.vc == colorplus->cga.crtc[7] && !colorplus->cga.sc)
colorplus->cga.cgastat |= 8;
colorplus->cga.displine++;
if (colorplus->cga.displine >= 360)
colorplus->cga.displine = 0;
} else {
timer_advance_u64(&colorplus->cga.timer, colorplus->cga.dispontime);
colorplus->cga.linepos = 0;
if (colorplus->cga.vsynctime) {
colorplus->cga.vsynctime--;
if (!colorplus->cga.vsynctime)
colorplus->cga.cgastat &= ~8;
}
return colorplus->cga.vram[addr & 0x7fff];
}
void colorplus_recalctimings(colorplus_t *colorplus)
{
cga_recalctimings(&colorplus->cga);
}
void colorplus_poll(void *p)
{
colorplus_t *colorplus = (colorplus_t *)p;
int x, c;
int oldvc;
uint16_t dat0, dat1;
int cols[4];
int col;
int oldsc;
static const int cols16[16] = { 0x10,0x12,0x14,0x16,
0x18,0x1A,0x1C,0x1E,
0x11,0x13,0x15,0x17,
0x19,0x1B,0x1D,0x1F };
uint8_t *plane0 = colorplus->cga.vram;
uint8_t *plane1 = colorplus->cga.vram + 0x4000;
/* If one of the extra modes is not selected, drop down to the CGA
* drawing code. */
if (!((colorplus->control & COLORPLUS_EITHER_MODE) &&
(colorplus->cga.cgamode & CGA_GRAPHICS_MODE)))
{
cga_poll(&colorplus->cga);
return;
}
if (!colorplus->cga.linepos)
{
timer_advance_u64(&colorplus->cga.timer, colorplus->cga.dispofftime);
colorplus->cga.cgastat |= 1;
colorplus->cga.linepos = 1;
oldsc = colorplus->cga.sc;
if ((colorplus->cga.crtc[8] & 3) == 3)
colorplus->cga.sc = ((colorplus->cga.sc << 1) + colorplus->cga.oddeven) & 7;
if (colorplus->cga.cgadispon)
{
if (colorplus->cga.displine < colorplus->cga.firstline)
{
colorplus->cga.firstline = colorplus->cga.displine;
video_wait_for_buffer();
}
colorplus->cga.lastline = colorplus->cga.displine;
/* Left / right border */
for (c = 0; c < 8; c++)
{
buffer32->line[colorplus->cga.displine][c] =
buffer32->line[colorplus->cga.displine][c + (colorplus->cga.crtc[1] << 4) + 8] =
(colorplus->cga.cgacol & 15) + 16;
}
if (colorplus->control & COLORPLUS_320x200_MODE)
{
for (x = 0; x < colorplus->cga.crtc[1]; x++)
{
dat0 = (plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) |
plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1];
dat1 = (plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) |
plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1];
colorplus->cga.ma++;
for (c = 0; c < 8; c++)
{
buffer32->line[colorplus->cga.displine][(x << 4) + (c << 1) + 8] =
buffer32->line[colorplus->cga.displine][(x << 4) + (c << 1) + 1 + 8] =
cols16[(dat0 >> 14) | ((dat1 >> 14) << 2)];
dat0 <<= 2;
dat1 <<= 2;
}
}
}
else if (colorplus->control & COLORPLUS_640x200_MODE)
{
cols[0] = (colorplus->cga.cgacol & 15) | 16;
col = (colorplus->cga.cgacol & 16) ? 24 : 16;
if (colorplus->cga.cgamode & 4)
{
cols[1] = col | 3;
cols[2] = col | 4;
cols[3] = col | 7;
}
else if (colorplus->cga.cgacol & 32)
{
cols[1] = col | 3;
cols[2] = col | 5;
cols[3] = col | 7;
}
else
{
cols[1] = col | 2;
cols[2] = col | 4;
cols[3] = col | 6;
}
for (x = 0; x < colorplus->cga.crtc[1]; x++)
{
dat0 = (plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) |
plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1];
dat1 = (plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) |
plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1];
colorplus->cga.ma++;
for (c = 0; c < 16; c++)
{
buffer32->line[colorplus->cga.displine][(x << 4) + c + 8] =
cols[(dat0 >> 15) | ((dat1 >> 15) << 1)];
dat0 <<= 1;
dat1 <<= 1;
}
}
}
}
else /* Top / bottom border */
{
cols[0] = (colorplus->cga.cgacol & 15) + 16;
hline(buffer32, 0, colorplus->cga.displine, (colorplus->cga.crtc[1] << 4) + 16, cols[0]);
}
x = (colorplus->cga.crtc[1] << 4) + 16;
if (colorplus->cga.composite)
Composite_Process(colorplus->cga.cgamode, 0, x >> 2, buffer32->line[colorplus->cga.displine]);
colorplus->cga.sc = oldsc;
if (colorplus->cga.vc == colorplus->cga.crtc[7] && !colorplus->cga.sc)
colorplus->cga.cgastat |= 8;
colorplus->cga.displine++;
if (colorplus->cga.displine >= 360)
colorplus->cga.displine = 0;
if (colorplus->cga.sc == (colorplus->cga.crtc[11] & 31) || ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[11] & 31) >> 1))) {
colorplus->cga.con = 0;
colorplus->cga.coff = 1;
}
else
{
timer_advance_u64(&colorplus->cga.timer, colorplus->cga.dispontime);
colorplus->cga.linepos = 0;
if (colorplus->cga.vsynctime)
{
colorplus->cga.vsynctime--;
if (!colorplus->cga.vsynctime)
colorplus->cga.cgastat &= ~8;
}
if (colorplus->cga.sc == (colorplus->cga.crtc[11] & 31) || ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[11] & 31) >> 1)))
{
colorplus->cga.con = 0;
colorplus->cga.coff = 1;
}
if ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == (colorplus->cga.crtc[9] >> 1))
colorplus->cga.maback = colorplus->cga.ma;
if (colorplus->cga.vadj)
{
colorplus->cga.sc++;
colorplus->cga.sc &= 31;
colorplus->cga.ma = colorplus->cga.maback;
colorplus->cga.vadj--;
if (!colorplus->cga.vadj)
{
colorplus->cga.cgadispon = 1;
colorplus->cga.ma = colorplus->cga.maback = (colorplus->cga.crtc[13] | (colorplus->cga.crtc[12] << 8)) & 0x3fff;
colorplus->cga.sc = 0;
}
}
else if (colorplus->cga.sc == colorplus->cga.crtc[9])
{
colorplus->cga.maback = colorplus->cga.ma;
colorplus->cga.sc = 0;
oldvc = colorplus->cga.vc;
colorplus->cga.vc++;
colorplus->cga.vc &= 127;
if ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == (colorplus->cga.crtc[9] >> 1))
colorplus->cga.maback = colorplus->cga.ma;
if (colorplus->cga.vadj) {
colorplus->cga.sc++;
colorplus->cga.sc &= 31;
colorplus->cga.ma = colorplus->cga.maback;
colorplus->cga.vadj--;
if (!colorplus->cga.vadj) {
colorplus->cga.cgadispon = 1;
colorplus->cga.ma = colorplus->cga.maback = (colorplus->cga.crtc[13] | (colorplus->cga.crtc[12] << 8)) & 0x3fff;
colorplus->cga.sc = 0;
}
} else if (colorplus->cga.sc == colorplus->cga.crtc[9]) {
colorplus->cga.maback = colorplus->cga.ma;
colorplus->cga.sc = 0;
oldvc = colorplus->cga.vc;
colorplus->cga.vc++;
colorplus->cga.vc &= 127;
if (colorplus->cga.vc == colorplus->cga.crtc[6])
colorplus->cga.cgadispon = 0;
if (colorplus->cga.vc == colorplus->cga.crtc[6])
colorplus->cga.cgadispon = 0;
if (oldvc == colorplus->cga.crtc[4])
{
colorplus->cga.vc = 0;
colorplus->cga.vadj = colorplus->cga.crtc[5];
if (!colorplus->cga.vadj) colorplus->cga.cgadispon = 1;
if (!colorplus->cga.vadj) colorplus->cga.ma = colorplus->cga.maback = (colorplus->cga.crtc[13] | (colorplus->cga.crtc[12] << 8)) & 0x3fff;
if ((colorplus->cga.crtc[10] & 0x60) == 0x20) colorplus->cga.cursoron = 0;
else colorplus->cga.cursoron = colorplus->cga.cgablink & 8;
}
if (colorplus->cga.vc == colorplus->cga.crtc[7])
{
colorplus->cga.cgadispon = 0;
colorplus->cga.displine = 0;
colorplus->cga.vsynctime = 16;
if (colorplus->cga.crtc[7])
{
if (colorplus->cga.cgamode & 1) x = (colorplus->cga.crtc[1] << 3) + 16;
else x = (colorplus->cga.crtc[1] << 4) + 16;
colorplus->cga.lastline++;
if (x != xsize || (colorplus->cga.lastline - colorplus->cga.firstline) != ysize)
{
xsize = x;
ysize = colorplus->cga.lastline - colorplus->cga.firstline;
if (xsize < 64) xsize = 656;
if (ysize < 32) ysize = 200;
set_screen_size(xsize, (ysize << 1) + 16);
}
if (colorplus->cga.composite)
video_blit_memtoscreen(0, colorplus->cga.firstline - 4, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8);
else
video_blit_memtoscreen_8(0, colorplus->cga.firstline - 4, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8);
frames++;
video_res_x = xsize - 16;
video_res_y = ysize;
if (colorplus->cga.cgamode & 1)
{
video_res_x /= 8;
video_res_y /= colorplus->cga.crtc[9] + 1;
video_bpp = 0;
}
else if (!(colorplus->cga.cgamode & 2))
{
video_res_x /= 16;
video_res_y /= colorplus->cga.crtc[9] + 1;
video_bpp = 0;
}
else if (!(colorplus->cga.cgamode & 16))
{
video_res_x /= 2;
video_bpp = 2;
}
else
{
video_bpp = 1;
}
}
colorplus->cga.firstline = 1000;
colorplus->cga.lastline = 0;
colorplus->cga.cgablink++;
colorplus->cga.oddeven ^= 1;
}
}
if (oldvc == colorplus->cga.crtc[4]) {
colorplus->cga.vc = 0;
colorplus->cga.vadj = colorplus->cga.crtc[5];
if (!colorplus->cga.vadj)
colorplus->cga.cgadispon = 1;
if (!colorplus->cga.vadj)
colorplus->cga.ma = colorplus->cga.maback = (colorplus->cga.crtc[13] | (colorplus->cga.crtc[12] << 8)) & 0x3fff;
if ((colorplus->cga.crtc[10] & 0x60) == 0x20)
colorplus->cga.cursoron = 0;
else
{
colorplus->cga.sc++;
colorplus->cga.sc &= 31;
colorplus->cga.ma = colorplus->cga.maback;
}
if (colorplus->cga.cgadispon)
colorplus->cga.cgastat &= ~1;
if ((colorplus->cga.sc == (colorplus->cga.crtc[10] & 31) || ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[10] & 31) >> 1))))
colorplus->cga.con = 1;
if (colorplus->cga.cgadispon && (colorplus->cga.cgamode & 1))
{
for (x = 0; x < (colorplus->cga.crtc[1] << 1); x++)
colorplus->cga.charbuffer[x] = colorplus->cga.vram[(((colorplus->cga.ma << 1) + x) & 0x3fff)];
colorplus->cga.cursoron = colorplus->cga.cgablink & 8;
}
if (colorplus->cga.vc == colorplus->cga.crtc[7]) {
colorplus->cga.cgadispon = 0;
colorplus->cga.displine = 0;
colorplus->cga.vsynctime = 16;
if (colorplus->cga.crtc[7]) {
if (colorplus->cga.cgamode & 1)
x = (colorplus->cga.crtc[1] << 3) + 16;
else
x = (colorplus->cga.crtc[1] << 4) + 16;
colorplus->cga.lastline++;
if (x != xsize || (colorplus->cga.lastline - colorplus->cga.firstline) != ysize) {
xsize = x;
ysize = colorplus->cga.lastline - colorplus->cga.firstline;
if (xsize < 64)
xsize = 656;
if (ysize < 32)
ysize = 200;
set_screen_size(xsize, (ysize << 1) + 16);
}
if (colorplus->cga.composite)
video_blit_memtoscreen(0, colorplus->cga.firstline - 4, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8);
else
video_blit_memtoscreen_8(0, colorplus->cga.firstline - 4, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8);
frames++;
video_res_x = xsize - 16;
video_res_y = ysize;
if (colorplus->cga.cgamode & 1) {
video_res_x /= 8;
video_res_y /= colorplus->cga.crtc[9] + 1;
video_bpp = 0;
} else if (!(colorplus->cga.cgamode & 2)) {
video_res_x /= 16;
video_res_y /= colorplus->cga.crtc[9] + 1;
video_bpp = 0;
} else if (!(colorplus->cga.cgamode & 16)) {
video_res_x /= 2;
video_bpp = 2;
} else {
video_bpp = 1;
}
}
colorplus->cga.firstline = 1000;
colorplus->cga.lastline = 0;
colorplus->cga.cgablink++;
colorplus->cga.oddeven ^= 1;
}
} else {
colorplus->cga.sc++;
colorplus->cga.sc &= 31;
colorplus->cga.ma = colorplus->cga.maback;
}
if (colorplus->cga.cgadispon)
colorplus->cga.cgastat &= ~1;
if ((colorplus->cga.sc == (colorplus->cga.crtc[10] & 31) || ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[10] & 31) >> 1))))
colorplus->cga.con = 1;
if (colorplus->cga.cgadispon && (colorplus->cga.cgamode & 1)) {
for (x = 0; x < (colorplus->cga.crtc[1] << 1); x++)
colorplus->cga.charbuffer[x] = colorplus->cga.vram[(((colorplus->cga.ma << 1) + x) & 0x3fff)];
}
}
}
void colorplus_init(colorplus_t *colorplus)
void
colorplus_init(colorplus_t *colorplus)
{
cga_init(&colorplus->cga);
cga_init(&colorplus->cga);
}
void *colorplus_standalone_init(const device_t *info)
void *
colorplus_standalone_init(const device_t *info)
{
int display_type;
int display_type;
colorplus_t *colorplus = malloc(sizeof(colorplus_t));
memset(colorplus, 0, sizeof(colorplus_t));
colorplus_t *colorplus = malloc(sizeof(colorplus_t));
memset(colorplus, 0, sizeof(colorplus_t));
video_inform(VIDEO_FLAG_TYPE_CGA, &timing_colorplus);
video_inform(VIDEO_FLAG_TYPE_CGA, &timing_colorplus);
/* Copied from the CGA init. Ideally this would be done by
* calling a helper function rather than duplicating code */
display_type = device_get_config_int("display_type");
colorplus->cga.composite = (display_type != CGA_RGB);
colorplus->cga.revision = device_get_config_int("composite_type");
colorplus->cga.snow_enabled = device_get_config_int("snow_enabled");
/* Copied from the CGA init. Ideally this would be done by
* calling a helper function rather than duplicating code */
display_type = device_get_config_int("display_type");
colorplus->cga.composite = (display_type != CGA_RGB);
colorplus->cga.revision = device_get_config_int("composite_type");
colorplus->cga.snow_enabled = device_get_config_int("snow_enabled");
colorplus->cga.vram = malloc(0x8000);
colorplus->cga.vram = malloc(0x8000);
cga_comp_init(colorplus->cga.revision);
timer_add(&colorplus->cga.timer, colorplus_poll, colorplus, 1);
mem_mapping_add(&colorplus->cga.mapping, 0xb8000, 0x08000, colorplus_read, NULL, NULL, colorplus_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, colorplus);
io_sethandler(0x03d0, 0x0010, colorplus_in, NULL, NULL, colorplus_out, NULL, NULL, colorplus);
cga_comp_init(colorplus->cga.revision);
timer_add(&colorplus->cga.timer, colorplus_poll, colorplus, 1);
mem_mapping_add(&colorplus->cga.mapping, 0xb8000, 0x08000, colorplus_read, NULL, NULL, colorplus_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, colorplus);
io_sethandler(0x03d0, 0x0010, colorplus_in, NULL, NULL, colorplus_out, NULL, NULL, colorplus);
lpt3_init(0x3BC);
lpt3_init(0x3BC);
return colorplus;
return colorplus;
}
void colorplus_close(void *p)
void
colorplus_close(void *p)
{
colorplus_t *colorplus = (colorplus_t *)p;
colorplus_t *colorplus = (colorplus_t *) p;
free(colorplus->cga.vram);
free(colorplus);
free(colorplus->cga.vram);
free(colorplus);
}
void colorplus_speed_changed(void *p)
void
colorplus_speed_changed(void *p)
{
colorplus_t *colorplus = (colorplus_t *)p;
colorplus_t *colorplus = (colorplus_t *) p;
cga_recalctimings(&colorplus->cga);
cga_recalctimings(&colorplus->cga);
}
static const device_config_t colorplus_config[] = {
// clang-format off
// clang-format off
{
.name = "display_type",
.description = "Display type",
@@ -479,17 +429,16 @@ static const device_config_t colorplus_config[] = {
// clang-format on
};
const device_t colorplus_device =
{
.name = "Colorplus",
const device_t colorplus_device = {
.name = "Colorplus",
.internal_name = "plantronics",
.flags = DEVICE_ISA,
.local = 0,
.init = colorplus_standalone_init,
.close = colorplus_close,
.reset = NULL,
.flags = DEVICE_ISA,
.local = 0,
.init = colorplus_standalone_init,
.close = colorplus_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = colorplus_speed_changed,
.force_redraw = NULL,
.config = colorplus_config
.force_redraw = NULL,
.config = colorplus_config
};

View File

@@ -36,378 +36,375 @@
#include <86box/vid_cga.h>
#include <86box/vid_cga_comp.h>
#define CGA_RGB 0
#define CGA_RGB 0
#define CGA_COMPOSITE 1
static uint32_t vflags;
static uint8_t mdaattr[256][2][2];
static uint32_t vflags;
static uint8_t mdaattr[256][2][2];
typedef struct compaq_cga_t
{
typedef struct compaq_cga_t {
cga_t cga;
} compaq_cga_t;
#ifdef ENABLE_COMPAQ_CGA_LOG
int compaq_cga_do_log = ENABLE_COMPAQ_CGA_LOG;
static void
compaq_cga_log(const char *fmt, ...)
{
va_list ap;
if (compaq_cga_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define compaq_cga_log(fmt, ...)
# define compaq_cga_log(fmt, ...)
#endif
void
compaq_cga_recalctimings(compaq_cga_t *self)
{
double _dispontime, _dispofftime, disptime;
disptime = self->cga.crtc[0] + 1;
_dispontime = self->cga.crtc[1];
_dispontime = self->cga.crtc[1];
_dispofftime = disptime - _dispontime;
_dispontime *= MDACONST;
_dispofftime *= MDACONST;
self->cga.dispontime = (uint64_t)(_dispontime);
self->cga.dispofftime = (uint64_t)(_dispofftime);
self->cga.dispontime = (uint64_t) (_dispontime);
self->cga.dispofftime = (uint64_t) (_dispofftime);
}
void
compaq_cga_poll(void *p)
{
compaq_cga_t *self = (compaq_cga_t *)p;
uint16_t ca = (self->cga.crtc[15] | (self->cga.crtc[14] << 8)) & 0x3fff;
int drawcursor;
int x, c, xs_temp, ys_temp;
int oldvc;
uint8_t chr, attr;
uint8_t border;
uint8_t cols[4];
int oldsc;
int underline = 0;
int blink = 0;
compaq_cga_t *self = (compaq_cga_t *) p;
uint16_t ca = (self->cga.crtc[15] | (self->cga.crtc[14] << 8)) & 0x3fff;
int drawcursor;
int x, c, xs_temp, ys_temp;
int oldvc;
uint8_t chr, attr;
uint8_t border;
uint8_t cols[4];
int oldsc;
int underline = 0;
int blink = 0;
/* If in graphics mode or character height is not 13, behave as CGA */
if ((self->cga.cgamode & 0x12) || (self->cga.crtc[9] != 13)) {
overscan_x = overscan_y = 16;
cga_poll(&self->cga);
return;
overscan_x = overscan_y = 16;
cga_poll(&self->cga);
return;
} else
overscan_x = overscan_y = 0;
overscan_x = overscan_y = 0;
/* We are in Compaq 350-line CGA territory */
if (!self->cga.linepos) {
timer_advance_u64(&self->cga.timer, self->cga.dispofftime);
self->cga.cgastat |= 1;
self->cga.linepos = 1;
oldsc = self->cga.sc;
if ((self->cga.crtc[8] & 3) == 3)
self->cga.sc = ((self->cga.sc << 1) + self->cga.oddeven) & 7;
if (self->cga.cgadispon) {
if (self->cga.displine < self->cga.firstline) {
self->cga.firstline = self->cga.displine;
video_wait_for_buffer();
compaq_cga_log("Firstline %i\n", firstline);
}
self->cga.lastline = self->cga.displine;
timer_advance_u64(&self->cga.timer, self->cga.dispofftime);
self->cga.cgastat |= 1;
self->cga.linepos = 1;
oldsc = self->cga.sc;
if ((self->cga.crtc[8] & 3) == 3)
self->cga.sc = ((self->cga.sc << 1) + self->cga.oddeven) & 7;
if (self->cga.cgadispon) {
if (self->cga.displine < self->cga.firstline) {
self->cga.firstline = self->cga.displine;
video_wait_for_buffer();
compaq_cga_log("Firstline %i\n", firstline);
}
self->cga.lastline = self->cga.displine;
cols[0] = (self->cga.cgacol & 15) + 16;
cols[0] = (self->cga.cgacol & 15) + 16;
for (c = 0; c < 8; c++) {
buffer32->line[self->cga.displine][c] = cols[0];
if (self->cga.cgamode & 1)
buffer32->line[self->cga.displine][c + (self->cga.crtc[1] << 3) + 8] = cols[0];
else
buffer32->line[self->cga.displine][c + (self->cga.crtc[1] << 4) + 8] = cols[0];
}
for (c = 0; c < 8; c++) {
buffer32->line[self->cga.displine][c] = cols[0];
if (self->cga.cgamode & 1)
buffer32->line[self->cga.displine][c + (self->cga.crtc[1] << 3) + 8] = cols[0];
else
buffer32->line[self->cga.displine][c + (self->cga.crtc[1] << 4) + 8] = cols[0];
}
if (self->cga.cgamode & 1) {
for (x = 0; x < self->cga.crtc[1]; x++) {
chr = self->cga.charbuffer[x << 1];
attr = self->cga.charbuffer[(x << 1) + 1];
drawcursor = ((self->cga.ma == ca) && self->cga.con && self->cga.cursoron);
if (self->cga.cgamode & 1) {
for (x = 0; x < self->cga.crtc[1]; x++) {
chr = self->cga.charbuffer[x << 1];
attr = self->cga.charbuffer[(x << 1) + 1];
drawcursor = ((self->cga.ma == ca) && self->cga.con && self->cga.cursoron);
if (vflags) {
underline = 0;
blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor);
}
if (vflags) {
underline = 0;
blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor);
}
if (vflags && (self->cga.cgamode & 0x80)) {
cols[0] = mdaattr[attr][blink][0];
cols[1] = mdaattr[attr][blink][1];
if (vflags && (self->cga.cgamode & 0x80)) {
cols[0] = mdaattr[attr][blink][0];
cols[1] = mdaattr[attr][blink][1];
if ((self->cga.sc == 12) && ((attr & 7) == 1))
underline = 1;
} else if (self->cga.cgamode & 0x20) {
cols[1] = (attr & 15) + 16;
cols[0] = ((attr >> 4) & 7) + 16;
if ((self->cga.sc == 12) && ((attr & 7) == 1))
underline = 1;
} else if (self->cga.cgamode & 0x20) {
cols[1] = (attr & 15) + 16;
cols[0] = ((attr >> 4) & 7) + 16;
if (vflags) {
if (blink)
cols[1] = cols[0];
} else {
if ((self->cga.cgablink & 8) && (attr & 0x80) && !self->cga.drawcursor)
cols[1] = cols[0];
}
} else {
cols[1] = (attr & 15) + 16;
cols[0] = (attr >> 4) + 16;
}
if (vflags) {
if (blink)
cols[1] = cols[0];
} else {
if ((self->cga.cgablink & 8) && (attr & 0x80) && !self->cga.drawcursor)
cols[1] = cols[0];
}
} else {
cols[1] = (attr & 15) + 16;
cols[0] = (attr >> 4) + 16;
}
if (vflags && underline) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c + 8] = mdaattr[attr][blink][1];
} else if (drawcursor) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
} else {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0];
}
self->cga.ma++;
}
} else {
for (x = 0; x < self->cga.crtc[1]; x++) {
chr = self->cga.vram[((self->cga.ma << 1) & 0x3fff)];
attr = self->cga.vram[(((self->cga.ma << 1) + 1) & 0x3fff)];
drawcursor = ((self->cga.ma == ca) && self->cga.con && self->cga.cursoron);
if (vflags && underline) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c + 8] = mdaattr[attr][blink][1];
} else if (drawcursor) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
} else {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0];
}
self->cga.ma++;
}
} else {
for (x = 0; x < self->cga.crtc[1]; x++) {
chr = self->cga.vram[((self->cga.ma << 1) & 0x3fff)];
attr = self->cga.vram[(((self->cga.ma << 1) + 1) & 0x3fff)];
drawcursor = ((self->cga.ma == ca) && self->cga.con && self->cga.cursoron);
if (vflags) {
underline = 0;
blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor);
}
if (vflags) {
underline = 0;
blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor);
}
if (vflags && (self->cga.cgamode & 0x80)) {
cols[0] = mdaattr[attr][blink][0];
cols[1] = mdaattr[attr][blink][1];
if (self->cga.sc == 12 && (attr & 7) == 1) underline = 1;
} else if (self->cga.cgamode & 0x20) {
cols[1] = (attr & 15) + 16;
cols[0] = ((attr >> 4) & 7) + 16;
if (vflags && (self->cga.cgamode & 0x80)) {
cols[0] = mdaattr[attr][blink][0];
cols[1] = mdaattr[attr][blink][1];
if (self->cga.sc == 12 && (attr & 7) == 1)
underline = 1;
} else if (self->cga.cgamode & 0x20) {
cols[1] = (attr & 15) + 16;
cols[0] = ((attr >> 4) & 7) + 16;
if (vflags) {
if (blink)
cols[1] = cols[0];
} else {
if ((self->cga.cgablink & 8) && (attr & 0x80) && !self->cga.drawcursor)
cols[1] = cols[0];
}
} else {
cols[1] = (attr & 15) + 16;
cols[0] = (attr >> 4) + 16;
}
self->cga.ma++;
if (vflags) {
if (blink)
cols[1] = cols[0];
} else {
if ((self->cga.cgablink & 8) && (attr & 0x80) && !self->cga.drawcursor)
cols[1] = cols[0];
}
} else {
cols[1] = (attr & 15) + 16;
cols[0] = (attr >> 4) + 16;
}
self->cga.ma++;
if (vflags && underline) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4)+(c << 1) + 8] =
buffer32->line[self->cga.displine][(x << 4)+(c << 1) + 9] = mdaattr[attr][blink][1];
} else if (drawcursor) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4)+(c << 1) + 8] =
buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1 + 8] =
cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
} else {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 8] =
buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1 + 8] =
cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0];
}
}
}
} else {
cols[0] = (self->cga.cgacol & 15) + 16;
if (vflags && underline) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 9] = mdaattr[attr][blink][1];
} else if (drawcursor) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
} else {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0];
}
}
}
} else {
cols[0] = (self->cga.cgacol & 15) + 16;
if (self->cga.cgamode & 1) hline(buffer32, 0, self->cga.displine, (self->cga.crtc[1] << 3) + 16, cols[0]);
else hline(buffer32, 0, self->cga.displine, (self->cga.crtc[1] << 4) + 16, cols[0]);
}
if (self->cga.cgamode & 1)
hline(buffer32, 0, self->cga.displine, (self->cga.crtc[1] << 3) + 16, cols[0]);
else
hline(buffer32, 0, self->cga.displine, (self->cga.crtc[1] << 4) + 16, cols[0]);
}
if (self->cga.cgamode & 1) x = (self->cga.crtc[1] << 3) + 16;
else x = (self->cga.crtc[1] << 4) + 16;
if (self->cga.cgamode & 1)
x = (self->cga.crtc[1] << 3) + 16;
else
x = (self->cga.crtc[1] << 4) + 16;
if (self->cga.composite) {
if (self->cga.cgamode & 0x10)
border = 0x00;
else
border = self->cga.cgacol & 0x0f;
if (self->cga.composite) {
if (self->cga.cgamode & 0x10)
border = 0x00;
else
border = self->cga.cgacol & 0x0f;
if (vflags)
Composite_Process(self->cga.cgamode & 0x7f, border, x >> 2, buffer32->line[self->cga.displine]);
else
Composite_Process(self->cga.cgamode, border, x >> 2, buffer32->line[self->cga.displine]);
}
if (vflags)
Composite_Process(self->cga.cgamode & 0x7f, border, x >> 2, buffer32->line[self->cga.displine]);
else
Composite_Process(self->cga.cgamode, border, x >> 2, buffer32->line[self->cga.displine]);
}
self->cga.sc = oldsc;
if (self->cga.vc == self->cga.crtc[7] && !self->cga.sc)
self->cga.cgastat |= 8;
self->cga.displine++;
if (self->cga.displine >= 500)
self->cga.displine = 0;
self->cga.sc = oldsc;
if (self->cga.vc == self->cga.crtc[7] && !self->cga.sc)
self->cga.cgastat |= 8;
self->cga.displine++;
if (self->cga.displine >= 500)
self->cga.displine = 0;
} else {
timer_advance_u64(&self->cga.timer, self->cga.dispontime);
self->cga.linepos = 0;
if (self->cga.vsynctime) {
self->cga.vsynctime--;
if (!self->cga.vsynctime)
self->cga.cgastat &= ~8;
}
timer_advance_u64(&self->cga.timer, self->cga.dispontime);
self->cga.linepos = 0;
if (self->cga.vsynctime) {
self->cga.vsynctime--;
if (!self->cga.vsynctime)
self->cga.cgastat &= ~8;
}
if (self->cga.sc == (self->cga.crtc[11] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[11] & 31) >> 1))) {
self->cga.con = 0;
self->cga.coff = 1;
}
if ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == (self->cga.crtc[9] >> 1))
self->cga.maback = self->cga.ma;
if (self->cga.vadj) {
self->cga.sc++;
self->cga.sc &= 31;
self->cga.ma = self->cga.maback;
self->cga.vadj--;
if (!self->cga.vadj) {
self->cga.cgadispon = 1;
self->cga.ma = self->cga.maback = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x3fff;
self->cga.sc = 0;
}
} else if (self->cga.sc == self->cga.crtc[9]) {
self->cga.maback = self->cga.ma;
self->cga.sc = 0;
oldvc = self->cga.vc;
self->cga.vc++;
self->cga.vc &= 127;
if (self->cga.sc == (self->cga.crtc[11] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[11] & 31) >> 1))) {
self->cga.con = 0;
self->cga.coff = 1;
}
if ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == (self->cga.crtc[9] >> 1))
self->cga.maback = self->cga.ma;
if (self->cga.vadj) {
self->cga.sc++;
self->cga.sc &= 31;
self->cga.ma = self->cga.maback;
self->cga.vadj--;
if (!self->cga.vadj) {
self->cga.cgadispon = 1;
self->cga.ma = self->cga.maback = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x3fff;
self->cga.sc = 0;
}
} else if (self->cga.sc == self->cga.crtc[9]) {
self->cga.maback = self->cga.ma;
self->cga.sc = 0;
oldvc = self->cga.vc;
self->cga.vc++;
self->cga.vc &= 127;
if (self->cga.vc == self->cga.crtc[6])
self->cga.cgadispon = 0;
if (self->cga.vc == self->cga.crtc[6])
self->cga.cgadispon = 0;
if (oldvc == self->cga.crtc[4]) {
self->cga.vc = 0;
self->cga.vadj = self->cga.crtc[5];
if (oldvc == self->cga.crtc[4]) {
self->cga.vc = 0;
self->cga.vadj = self->cga.crtc[5];
if (!self->cga.vadj) self->cga.cgadispon = 1;
if (!self->cga.vadj)
self->cga.cgadispon = 1;
if (!self->cga.vadj) self->cga.ma = self->cga.maback = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x3fff;
if (!self->cga.vadj)
self->cga.ma = self->cga.maback = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x3fff;
if ((self->cga.crtc[10] & 0x60) == 0x20)
self->cga.cursoron = 0;
else
self->cga.cursoron = self->cga.cgablink & 8;
}
if ((self->cga.crtc[10] & 0x60) == 0x20)
self->cga.cursoron = 0;
else
self->cga.cursoron = self->cga.cgablink & 8;
}
if (self->cga.vc == self->cga.crtc[7]) {
self->cga.cgadispon = 0;
self->cga.displine = 0;
self->cga.vsynctime = 16;
if (self->cga.vc == self->cga.crtc[7]) {
self->cga.cgadispon = 0;
self->cga.displine = 0;
self->cga.vsynctime = 16;
if (self->cga.crtc[7]) {
compaq_cga_log("Lastline %i Firstline %i %i\n", self->cga.lastline,
self->cga.firstline ,self->cga.lastline - self->cga.firstline);
if (self->cga.crtc[7]) {
compaq_cga_log("Lastline %i Firstline %i %i\n", self->cga.lastline,
self->cga.firstline, self->cga.lastline - self->cga.firstline);
if (self->cga.cgamode & 1) x = (self->cga.crtc[1] << 3) + 16;
else x = (self->cga.crtc[1] << 4) + 16;
if (self->cga.cgamode & 1)
x = (self->cga.crtc[1] << 3) + 16;
else
x = (self->cga.crtc[1] << 4) + 16;
self->cga.lastline++;
self->cga.lastline++;
xs_temp = x;
ys_temp = (self->cga.lastline - self->cga.firstline);
xs_temp = x;
ys_temp = (self->cga.lastline - self->cga.firstline);
if ((xs_temp > 0) && (ys_temp > 0)) {
if (xs_temp < 64) xs_temp = 656;
if (ys_temp < 32) ys_temp = 400;
if (!enable_overscan)
xs_temp -= 16;
if ((xs_temp > 0) && (ys_temp > 0)) {
if (xs_temp < 64)
xs_temp = 656;
if (ys_temp < 32)
ys_temp = 400;
if (!enable_overscan)
xs_temp -= 16;
if ((self->cga.cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) {
xsize = xs_temp;
ysize = ys_temp;
set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0));
if ((self->cga.cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) {
xsize = xs_temp;
ysize = ys_temp;
set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0));
if (video_force_resize_get())
video_force_resize_set(0);
}
if (video_force_resize_get())
video_force_resize_set(0);
}
if (enable_overscan) {
if (self->cga.composite)
video_blit_memtoscreen(0, self->cga.firstline - 8, xsize, (self->cga.lastline - self->cga.firstline) + 16);
else
video_blit_memtoscreen_8(0, self->cga.firstline - 8, xsize, (self->cga.lastline - self->cga.firstline) + 16);
} else {
if (self->cga.composite)
video_blit_memtoscreen(8, self->cga.firstline, xsize, self->cga.lastline - self->cga.firstline);
else
video_blit_memtoscreen_8(8, self->cga.firstline, xsize, self->cga.lastline - self->cga.firstline);
}
}
if (enable_overscan) {
if (self->cga.composite)
video_blit_memtoscreen(0, self->cga.firstline - 8, xsize, (self->cga.lastline - self->cga.firstline) + 16);
else
video_blit_memtoscreen_8(0, self->cga.firstline - 8, xsize, (self->cga.lastline - self->cga.firstline) + 16);
} else {
if (self->cga.composite)
video_blit_memtoscreen(8, self->cga.firstline, xsize, self->cga.lastline - self->cga.firstline);
else
video_blit_memtoscreen_8(8, self->cga.firstline, xsize, self->cga.lastline - self->cga.firstline);
}
}
frames++;
frames++;
video_res_x = xsize;
if (enable_overscan)
xsize -= 16;
video_res_y = ysize;
if (self->cga.cgamode & 1) {
video_res_x /= 8;
video_res_y /= self->cga.crtc[9] + 1;
video_bpp = 0;
} else if (!(self->cga.cgamode & 2)) {
video_res_x /= 16;
video_res_y /= self->cga.crtc[9] + 1;
video_bpp = 0;
} else if (!(self->cga.cgamode & 16)) {
video_res_x /= 2;
video_bpp = 2;
} else
video_bpp = 1;
}
video_res_x = xsize;
if (enable_overscan)
xsize -= 16;
video_res_y = ysize;
if (self->cga.cgamode & 1) {
video_res_x /= 8;
video_res_y /= self->cga.crtc[9] + 1;
video_bpp = 0;
} else if (!(self->cga.cgamode & 2)) {
video_res_x /= 16;
video_res_y /= self->cga.crtc[9] + 1;
video_bpp = 0;
} else if (!(self->cga.cgamode & 16)) {
video_res_x /= 2;
video_bpp = 2;
} else
video_bpp = 1;
}
self->cga.firstline = 1000;
self->cga.lastline = 0;
self->cga.cgablink++;
self->cga.oddeven ^= 1;
}
} else {
self->cga.sc++;
self->cga.sc &= 31;
self->cga.ma = self->cga.maback;
}
self->cga.firstline = 1000;
self->cga.lastline = 0;
self->cga.cgablink++;
self->cga.oddeven ^= 1;
}
} else {
self->cga.sc++;
self->cga.sc &= 31;
self->cga.ma = self->cga.maback;
}
if (self->cga.cgadispon)
self->cga.cgastat &= ~1;
if (self->cga.cgadispon)
self->cga.cgastat &= ~1;
if ((self->cga.sc == (self->cga.crtc[10] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[10] & 31) >> 1))))
self->cga.con = 1;
if ((self->cga.sc == (self->cga.crtc[10] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[10] & 31) >> 1))))
self->cga.con = 1;
if (self->cga.cgadispon && (self->cga.cgamode & 1)) {
for (x = 0; x < (self->cga.crtc[1] << 1); x++)
self->cga.charbuffer[x] = self->cga.vram[(((self->cga.ma << 1) + x) & 0x3fff)];
}
if (self->cga.cgadispon && (self->cga.cgamode & 1)) {
for (x = 0; x < (self->cga.crtc[1] << 1); x++)
self->cga.charbuffer[x] = self->cga.vram[(((self->cga.ma << 1) + x) & 0x3fff)];
}
}
}
void *
compaq_cga_init(const device_t *info)
{
int display_type;
int c;
int display_type;
int c;
compaq_cga_t *self = malloc(sizeof(compaq_cga_t));
memset(self, 0, sizeof(compaq_cga_t));
display_type = device_get_config_int("display_type");
self->cga.composite = (display_type != CGA_RGB);
self->cga.revision = device_get_config_int("composite_type");
display_type = device_get_config_int("display_type");
self->cga.composite = (display_type != CGA_RGB);
self->cga.revision = device_get_config_int("composite_type");
self->cga.snow_enabled = device_get_config_int("snow_enabled");
self->cga.vram = malloc(0x4000);
@@ -418,24 +415,26 @@ compaq_cga_init(const device_t *info)
io_sethandler(0x03d0, 0x0010, cga_in, NULL, NULL, cga_out, NULL, NULL, self);
if (info->local) {
for (c = 0; c < 256; c++) {
mdaattr[c][0][0] = mdaattr[c][1][0] = mdaattr[c][1][1] = 16;
if (c & 8) mdaattr[c][0][1] = 15 + 16;
else mdaattr[c][0][1] = 7 + 16;
}
for (c = 0; c < 256; c++) {
mdaattr[c][0][0] = mdaattr[c][1][0] = mdaattr[c][1][1] = 16;
if (c & 8)
mdaattr[c][0][1] = 15 + 16;
else
mdaattr[c][0][1] = 7 + 16;
}
mdaattr[0x70][0][1] = 16;
mdaattr[0x70][0][0] = mdaattr[0x70][1][0] = mdaattr[0x70][1][1] = 16 + 15;
mdaattr[0xF0][0][1] = 16;
mdaattr[0xF0][0][0] = mdaattr[0xF0][1][0] = mdaattr[0xF0][1][1] = 16 + 15;
mdaattr[0x78][0][1] = 16 + 7;
mdaattr[0x78][0][0] = mdaattr[0x78][1][0] = mdaattr[0x78][1][1] = 16 + 15;
mdaattr[0xF8][0][1] = 16 + 7;
mdaattr[0xF8][0][0] = mdaattr[0xF8][1][0] = mdaattr[0xF8][1][1] = 16 + 15;
mdaattr[0x00][0][1] = mdaattr[0x00][1][1] = 16;
mdaattr[0x08][0][1] = mdaattr[0x08][1][1] = 16;
mdaattr[0x80][0][1] = mdaattr[0x80][1][1] = 16;
mdaattr[0x88][0][1] = mdaattr[0x88][1][1] = 16;
mdaattr[0x70][0][1] = 16;
mdaattr[0x70][0][0] = mdaattr[0x70][1][0] = mdaattr[0x70][1][1] = 16 + 15;
mdaattr[0xF0][0][1] = 16;
mdaattr[0xF0][0][0] = mdaattr[0xF0][1][0] = mdaattr[0xF0][1][1] = 16 + 15;
mdaattr[0x78][0][1] = 16 + 7;
mdaattr[0x78][0][0] = mdaattr[0x78][1][0] = mdaattr[0x78][1][1] = 16 + 15;
mdaattr[0xF8][0][1] = 16 + 7;
mdaattr[0xF8][0][0] = mdaattr[0xF8][1][0] = mdaattr[0xF8][1][1] = 16 + 15;
mdaattr[0x00][0][1] = mdaattr[0x00][1][1] = 16;
mdaattr[0x08][0][1] = mdaattr[0x08][1][1] = 16;
mdaattr[0x80][0][1] = mdaattr[0x80][1][1] = 16;
mdaattr[0x88][0][1] = mdaattr[0x88][1][1] = 16;
}
vflags = info->local;
@@ -443,7 +442,7 @@ compaq_cga_init(const device_t *info)
overscan_x = overscan_y = 16;
self->cga.rgb_type = device_get_config_int("rgb_type");
cga_palette = (self->cga.rgb_type << 1);
cga_palette = (self->cga.rgb_type << 1);
cgapal_rebuild();
self->cga.crtc[9] = 13;
@@ -451,55 +450,52 @@ compaq_cga_init(const device_t *info)
return self;
}
void
compaq_cga_close(void *p)
{
compaq_cga_t *self = (compaq_cga_t *)p;
compaq_cga_t *self = (compaq_cga_t *) p;
free(self->cga.vram);
free(self);
}
void
compaq_cga_speed_changed(void *p)
{
compaq_cga_t *self = (compaq_cga_t *)p;
compaq_cga_t *self = (compaq_cga_t *) p;
if (self->cga.crtc[9] == 13) /* Character height */
compaq_cga_recalctimings(self);
if (self->cga.crtc[9] == 13) /* Character height */
compaq_cga_recalctimings(self);
else
cga_recalctimings(&self->cga);
cga_recalctimings(&self->cga);
}
extern const device_config_t cga_config[];
const device_t compaq_cga_device = {
.name = "Compaq CGA",
.name = "Compaq CGA",
.internal_name = "compaq_cga",
.flags = DEVICE_ISA,
.local = 0,
.init = compaq_cga_init,
.close = compaq_cga_close,
.reset = NULL,
.flags = DEVICE_ISA,
.local = 0,
.init = compaq_cga_init,
.close = compaq_cga_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = compaq_cga_speed_changed,
.force_redraw = NULL,
.config = cga_config
.force_redraw = NULL,
.config = cga_config
};
const device_t compaq_cga_2_device = {
.name = "Compaq CGA 2",
.name = "Compaq CGA 2",
.internal_name = "compaq_cga_2",
.flags = DEVICE_ISA,
.local = 1,
.init = compaq_cga_init,
.close = compaq_cga_close,
.reset = NULL,
.flags = DEVICE_ISA,
.local = 1,
.init = compaq_cga_init,
.close = compaq_cga_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = compaq_cga_speed_changed,
.force_redraw = NULL,
.config = cga_config
.force_redraw = NULL,
.config = cga_config
};

View File

@@ -24,30 +24,30 @@
#include <86box/86box.h>
#include <86box/i2c.h>
#define PIXEL_MM(px) ((uint16_t) (((px) * 25.4) / 96))
#define STANDARD_TIMING(slot, width, aspect_ratio, refresh) do { \
edid->slot.horiz_pixels = ((width) >> 3) - 31; \
edid->slot.aspect_ratio_refresh_rate = ((aspect_ratio) << 6) | ((refresh) - 60); \
} while (0)
#define DETAILED_TIMING(slot, clk, width, height, hblank, vblank, hfp, hsp, vfp, vsp) do { \
edid->slot.pixel_clock_lsb = ((clk) / 10) & 0xff; \
edid->slot.pixel_clock_msb = ((clk) / 10) >> 8; \
edid->slot.h_active_lsb = (width) & 0xff; \
edid->slot.h_blank_lsb = (hblank) & 0xff; \
edid->slot.h_active_blank_msb = (((width) >> 4) & 0xf0) | (((hblank) >> 8) & 0x0f); \
edid->slot.v_active_lsb = (height) & 0xff; \
edid->slot.v_blank_lsb = (vblank) & 0xff; \
edid->slot.v_active_blank_msb = (((height) >> 4) & 0xf0) | (((vblank) >> 8) & 0x0f); \
edid->slot.h_front_porch_lsb = (hfp) & 0xff; \
edid->slot.h_sync_pulse_lsb = (hsp) & 0xff; \
edid->slot.v_front_porch_sync_pulse_lsb = (((vfp) & 0x0f) << 4) | ((vsp) & 0x0f); \
edid->slot.hv_front_porch_sync_pulse_msb = (((hfp) >> 2) & 0xc0) | (((hsp) >> 4) & 0x30) | (((vfp) >> 2) & 0x0c) | (((vsp) >> 4) & 0x03); \
edid->slot.h_size_lsb = horiz_mm & 0xff; \
edid->slot.v_size_lsb = vert_mm & 0xff; \
edid->slot.hv_size_msb = ((horiz_mm >> 4) & 0xf0) | ((vert_mm >> 8) & 0x0f); \
} while (0)
#define PIXEL_MM(px) ((uint16_t) (((px) *25.4) / 96))
#define STANDARD_TIMING(slot, width, aspect_ratio, refresh) \
do { \
edid->slot.horiz_pixels = ((width) >> 3) - 31; \
edid->slot.aspect_ratio_refresh_rate = ((aspect_ratio) << 6) | ((refresh) -60); \
} while (0)
#define DETAILED_TIMING(slot, clk, width, height, hblank, vblank, hfp, hsp, vfp, vsp) \
do { \
edid->slot.pixel_clock_lsb = ((clk) / 10) & 0xff; \
edid->slot.pixel_clock_msb = ((clk) / 10) >> 8; \
edid->slot.h_active_lsb = (width) &0xff; \
edid->slot.h_blank_lsb = (hblank) &0xff; \
edid->slot.h_active_blank_msb = (((width) >> 4) & 0xf0) | (((hblank) >> 8) & 0x0f); \
edid->slot.v_active_lsb = (height) &0xff; \
edid->slot.v_blank_lsb = (vblank) &0xff; \
edid->slot.v_active_blank_msb = (((height) >> 4) & 0xf0) | (((vblank) >> 8) & 0x0f); \
edid->slot.h_front_porch_lsb = (hfp) &0xff; \
edid->slot.h_sync_pulse_lsb = (hsp) &0xff; \
edid->slot.v_front_porch_sync_pulse_lsb = (((vfp) &0x0f) << 4) | ((vsp) &0x0f); \
edid->slot.hv_front_porch_sync_pulse_msb = (((hfp) >> 2) & 0xc0) | (((hsp) >> 4) & 0x30) | (((vfp) >> 2) & 0x0c) | (((vsp) >> 4) & 0x03); \
edid->slot.h_size_lsb = horiz_mm & 0xff; \
edid->slot.v_size_lsb = vert_mm & 0xff; \
edid->slot.hv_size_msb = ((horiz_mm >> 4) & 0xf0) | ((vert_mm >> 8) & 0x0f); \
} while (0)
enum {
STD_ASPECT_16_10 = 0x0,
@@ -57,76 +57,75 @@ enum {
};
typedef struct {
uint8_t horiz_pixels, aspect_ratio_refresh_rate;
uint8_t horiz_pixels, aspect_ratio_refresh_rate;
} edid_standard_timing_t;
typedef struct {
uint8_t pixel_clock_lsb, pixel_clock_msb, h_active_lsb, h_blank_lsb,
h_active_blank_msb, v_active_lsb, v_blank_lsb, v_active_blank_msb,
h_front_porch_lsb, h_sync_pulse_lsb, v_front_porch_sync_pulse_lsb,
hv_front_porch_sync_pulse_msb, h_size_lsb, v_size_lsb, hv_size_msb,
h_border, v_border, features;
uint8_t pixel_clock_lsb, pixel_clock_msb, h_active_lsb, h_blank_lsb,
h_active_blank_msb, v_active_lsb, v_blank_lsb, v_active_blank_msb,
h_front_porch_lsb, h_sync_pulse_lsb, v_front_porch_sync_pulse_lsb,
hv_front_porch_sync_pulse_msb, h_size_lsb, v_size_lsb, hv_size_msb,
h_border, v_border, features;
} edid_detailed_timing_t;
typedef struct {
uint8_t magic[2], reserved, tag, range_limit_offsets;
uint8_t magic[2], reserved, tag, range_limit_offsets;
union {
char ascii[13];
struct {
uint8_t min_v_field, max_v_field, min_h_line, max_h_line, max_pixel_clock,
timing_type;
union {
uint8_t padding[7];
struct {
uint8_t reserved, gtf_start_freq, gtf_c, gtf_m_lsb, gtf_m_msb,
gtf_k, gtf_j;
};
struct {
uint8_t cvt_version, add_clock_precision, max_active_pixels,
aspect_ratios, aspect_ratio_pref, scaling_support,
refresh_pref;
};
};
} range_limits;
struct {
edid_standard_timing_t timings[6];
uint8_t padding;
} ext_standard_timings;
struct {
uint8_t version;
struct {
uint8_t lines_lsb, lines_msb_aspect_ratio, refresh_rate;
} timings[4];
} cvt_timings;
struct {
uint8_t version, timings[6], reserved[6];
} established_timings3;
char ascii[13];
struct {
uint8_t min_v_field, max_v_field, min_h_line, max_h_line, max_pixel_clock,
timing_type;
union {
uint8_t padding[7];
struct {
uint8_t reserved, gtf_start_freq, gtf_c, gtf_m_lsb, gtf_m_msb,
gtf_k, gtf_j;
};
struct {
uint8_t cvt_version, add_clock_precision, max_active_pixels,
aspect_ratios, aspect_ratio_pref, scaling_support,
refresh_pref;
};
};
} range_limits;
struct {
edid_standard_timing_t timings[6];
uint8_t padding;
} ext_standard_timings;
struct {
uint8_t version;
struct {
uint8_t lines_lsb, lines_msb_aspect_ratio, refresh_rate;
} timings[4];
} cvt_timings;
struct {
uint8_t version, timings[6], reserved[6];
} established_timings3;
};
} edid_descriptor_t;
typedef struct {
uint8_t magic[8], mfg[2], mfg_product[2], serial[4], mfg_week, mfg_year,
edid_version, edid_rev;
uint8_t input_params, horiz_size, vert_size, gamma, features;
uint8_t red_green_lsb, blue_white_lsb, red_x_msb, red_y_msb, green_x_msb,
green_y_msb, blue_x_msb, blue_y_msb, white_x_msb, white_y_msb;
uint8_t established_timings[3];
uint8_t magic[8], mfg[2], mfg_product[2], serial[4], mfg_week, mfg_year,
edid_version, edid_rev;
uint8_t input_params, horiz_size, vert_size, gamma, features;
uint8_t red_green_lsb, blue_white_lsb, red_x_msb, red_y_msb, green_x_msb,
green_y_msb, blue_x_msb, blue_y_msb, white_x_msb, white_y_msb;
uint8_t established_timings[3];
edid_standard_timing_t standard_timings[8];
union {
edid_detailed_timing_t detailed_timings[4];
edid_descriptor_t descriptors[4];
edid_detailed_timing_t detailed_timings[4];
edid_descriptor_t descriptors[4];
};
uint8_t extensions, checksum;
uint8_t extensions, checksum;
uint8_t ext_tag, ext_rev, ext_dtd_offset, ext_native_dtds;
uint8_t ext_tag, ext_rev, ext_dtd_offset, ext_native_dtds;
union {
edid_detailed_timing_t ext_detailed_timings[6];
edid_descriptor_t ext_descriptors[6];
edid_detailed_timing_t ext_detailed_timings[6];
edid_descriptor_t ext_descriptors[6];
};
uint8_t padding[15], checksum2;
uint8_t padding[15], checksum2;
} edid_t;
void *
ddc_init(void *i2c)
{
@@ -138,60 +137,60 @@ ddc_init(void *i2c)
memset(&edid->magic[1], 0xff, sizeof(edid->magic) - 2);
edid->mfg[0] = 0x09; /* manufacturer "BOX" (apparently unassigned by UEFI) */
edid->mfg[1] = 0xf8;
edid->mfg_week = 48;
edid->mfg_year = 2020 - 1990;
edid->mfg[0] = 0x09; /* manufacturer "BOX" (apparently unassigned by UEFI) */
edid->mfg[1] = 0xf8;
edid->mfg_week = 48;
edid->mfg_year = 2020 - 1990;
edid->edid_version = 0x01;
edid->edid_rev = 0x03; /* EDID 1.3 */
edid->edid_rev = 0x03; /* EDID 1.3 */
edid->input_params = 0x0e; /* analog input; separate sync; composite sync; sync on green */
edid->horiz_size = horiz_mm / 10;
edid->vert_size = vert_mm / 10;
edid->features = 0xeb; /* DPMS standby/suspend/active-off; RGB color; first timing is preferred; GTF/CVT */
edid->horiz_size = horiz_mm / 10;
edid->vert_size = vert_mm / 10;
edid->features = 0xeb; /* DPMS standby/suspend/active-off; RGB color; first timing is preferred; GTF/CVT */
edid->red_green_lsb = 0x81;
edid->red_green_lsb = 0x81;
edid->blue_white_lsb = 0xf1;
edid->red_x_msb = 0xa3;
edid->red_y_msb = 0x57;
edid->green_x_msb = 0x53;
edid->green_y_msb = 0x9f;
edid->blue_x_msb = 0x27;
edid->blue_y_msb = 0x0a;
edid->white_x_msb = 0x50;
edid->white_y_msb = 0x00;
edid->red_x_msb = 0xa3;
edid->red_y_msb = 0x57;
edid->green_x_msb = 0x53;
edid->green_y_msb = 0x9f;
edid->blue_x_msb = 0x27;
edid->blue_y_msb = 0x0a;
edid->white_x_msb = 0x50;
edid->white_y_msb = 0x00;
memset(&edid->established_timings, 0xff, sizeof(edid->established_timings)); /* all enabled */
/* 60 Hz timings */
STANDARD_TIMING(standard_timings[0], 1280, STD_ASPECT_16_9, 60); /* 1280x720 */
STANDARD_TIMING(standard_timings[0], 1280, STD_ASPECT_16_9, 60); /* 1280x720 */
STANDARD_TIMING(standard_timings[1], 1280, STD_ASPECT_16_10, 60); /* 1280x800 */
STANDARD_TIMING(standard_timings[2], 1366, STD_ASPECT_16_9, 60); /* 1360x768 (closest to 1366x768) */
STANDARD_TIMING(standard_timings[2], 1366, STD_ASPECT_16_9, 60); /* 1360x768 (closest to 1366x768) */
STANDARD_TIMING(standard_timings[3], 1440, STD_ASPECT_16_10, 60); /* 1440x900 */
STANDARD_TIMING(standard_timings[4], 1600, STD_ASPECT_16_9, 60); /* 1600x900 */
STANDARD_TIMING(standard_timings[4], 1600, STD_ASPECT_16_9, 60); /* 1600x900 */
STANDARD_TIMING(standard_timings[5], 1680, STD_ASPECT_16_10, 60); /* 1680x1050 */
STANDARD_TIMING(standard_timings[6], 1920, STD_ASPECT_16_9, 60); /* 1920x1080 */
STANDARD_TIMING(standard_timings[7], 2048, STD_ASPECT_4_3, 60); /* 2048x1536 */
STANDARD_TIMING(standard_timings[6], 1920, STD_ASPECT_16_9, 60); /* 1920x1080 */
STANDARD_TIMING(standard_timings[7], 2048, STD_ASPECT_4_3, 60); /* 2048x1536 */
/* Detailed timing for the preferred mode of 800x600 @ 60 Hz */
DETAILED_TIMING(detailed_timings[0], 40000, 800, 600, 256, 28, 40, 128, 1, 4);
edid->descriptors[1].tag = 0xf7; /* established timings 3 */
edid->descriptors[1].tag = 0xf7; /* established timings 3 */
edid->descriptors[1].established_timings3.version = 0x0a;
memset(&edid->descriptors[1].established_timings3.timings, 0xff, sizeof(edid->descriptors[1].established_timings3.timings)); /* all enabled */
edid->descriptors[1].established_timings3.timings[5] &= 0xf0; /* reserved bits */
edid->descriptors[1].established_timings3.timings[5] &= 0xf0; /* reserved bits */
edid->descriptors[2].tag = 0xfd; /* range limits */
edid->descriptors[2].range_limits.min_v_field = 45;
edid->descriptors[2].range_limits.max_v_field = 125;
edid->descriptors[2].range_limits.min_h_line = 30; /* 640x480 = ~31.5 KHz */
edid->descriptors[2].range_limits.max_h_line = 115; /* 1920x1440 = 112.5 KHz */
edid->descriptors[2].range_limits.max_pixel_clock = 30; /* 1920x1440 = 297 MHz */
edid->descriptors[2].range_limits.timing_type = 0x00; /* default GTF */
edid->descriptors[2].range_limits.padding[0] = 0x0a;
edid->descriptors[2].tag = 0xfd; /* range limits */
edid->descriptors[2].range_limits.min_v_field = 45;
edid->descriptors[2].range_limits.max_v_field = 125;
edid->descriptors[2].range_limits.min_h_line = 30; /* 640x480 = ~31.5 KHz */
edid->descriptors[2].range_limits.max_h_line = 115; /* 1920x1440 = 112.5 KHz */
edid->descriptors[2].range_limits.max_pixel_clock = 30; /* 1920x1440 = 297 MHz */
edid->descriptors[2].range_limits.timing_type = 0x00; /* default GTF */
edid->descriptors[2].range_limits.padding[0] = 0x0a;
memset(&edid->descriptors[2].range_limits.padding[1], 0x20, sizeof(edid->descriptors[2].range_limits.padding) - 1);
edid->descriptors[3].tag = 0xfc; /* display name */
edid->descriptors[3].tag = 0xfc; /* display name */
memcpy(&edid->descriptors[3].ascii, "86Box Monitor", 13); /* exactly 13 characters (would otherwise require LF termination and space padding) */
edid->extensions = 1;
@@ -199,10 +198,10 @@ ddc_init(void *i2c)
edid->checksum += edid_bytes[c];
edid->checksum = 256 - edid->checksum;
edid->ext_tag = 0x02;
edid->ext_rev = 0x03;
edid->ext_tag = 0x02;
edid->ext_rev = 0x03;
edid->ext_native_dtds = 0x80; /* underscans IT; no native extended modes */
edid->ext_dtd_offset = 0x04;
edid->ext_dtd_offset = 0x04;
/* Detailed timing for 1366x768 */
DETAILED_TIMING(ext_detailed_timings[0], 85500, 1366, 768, 426, 30, 70, 143, 3, 3);
@@ -210,12 +209,12 @@ ddc_init(void *i2c)
/* High refresh rate timings (VGA is limited to 85 Hz) */
edid->ext_descriptors[1].tag = 0xfa; /* standard timing identifiers */
#define ext_standard_timings0 ext_descriptors[1].ext_standard_timings.timings
STANDARD_TIMING(ext_standard_timings0[0], 640, STD_ASPECT_4_3, 90); /* 640x480 @ 90 Hz */
STANDARD_TIMING(ext_standard_timings0[1], 640, STD_ASPECT_4_3, 120); /* 640x480 @ 120 Hz */
STANDARD_TIMING(ext_standard_timings0[2], 800, STD_ASPECT_4_3, 90); /* 800x600 @ 90 Hz */
STANDARD_TIMING(ext_standard_timings0[3], 800, STD_ASPECT_4_3, 120); /* 800x600 @ 120 Hz */
STANDARD_TIMING(ext_standard_timings0[4], 1024, STD_ASPECT_4_3, 90); /* 1024x768 @ 90 Hz */
STANDARD_TIMING(ext_standard_timings0[5], 1280, STD_ASPECT_5_4, 90); /* 1280x1024 @ 90 Hz */
STANDARD_TIMING(ext_standard_timings0[0], 640, STD_ASPECT_4_3, 90); /* 640x480 @ 90 Hz */
STANDARD_TIMING(ext_standard_timings0[1], 640, STD_ASPECT_4_3, 120); /* 640x480 @ 120 Hz */
STANDARD_TIMING(ext_standard_timings0[2], 800, STD_ASPECT_4_3, 90); /* 800x600 @ 90 Hz */
STANDARD_TIMING(ext_standard_timings0[3], 800, STD_ASPECT_4_3, 120); /* 800x600 @ 120 Hz */
STANDARD_TIMING(ext_standard_timings0[4], 1024, STD_ASPECT_4_3, 90); /* 1024x768 @ 90 Hz */
STANDARD_TIMING(ext_standard_timings0[5], 1280, STD_ASPECT_5_4, 90); /* 1280x1024 @ 90 Hz */
edid->ext_descriptors[1].ext_standard_timings.padding = 0x0a;
for (uint8_t c = 128; c < 255; c++)
@@ -225,7 +224,6 @@ ddc_init(void *i2c)
return i2c_eeprom_init(i2c, 0x50, edid_bytes, sizeof(edid_t), 0);
}
void
ddc_close(void *eeprom)
{

File diff suppressed because it is too large Load Diff

View File

@@ -29,174 +29,172 @@
#include <86box/vid_ega.h>
#include <86box/vid_ega_render_remap.h>
int
ega_display_line(ega_t *ega)
{
int y_add = (enable_overscan) ? (overscan_y >> 1) : 0;
unsigned int dl = ega->displine;
int y_add = (enable_overscan) ? (overscan_y >> 1) : 0;
unsigned int dl = ega->displine;
if (ega->crtc[9] & 0x1f)
dl -= (ega->crtc[8] & 0x1f);
dl -= (ega->crtc[8] & 0x1f);
dl += y_add;
dl &= 0x7ff;
return dl;
}
void
ega_render_blank(ega_t *ega)
{
int x, xx;
if ((ega->displine + ega->y_add) < 0)
return;
return;
for (x = 0; x < (ega->hdisp + ega->scrollcache); x++) {
switch (ega->seqregs[1] & 9) {
case 0:
for (xx = 0; xx < 9; xx++) buffer32->line[ega->displine + ega->y_add][ega->x_add + (x * 9) + xx] = 0;
break;
case 1:
for (xx = 0; xx < 8; xx++) buffer32->line[ega->displine + ega->y_add][ega->x_add + (x * 8) + xx] = 0;
break;
case 8:
for (xx = 0; xx < 18; xx++) buffer32->line[ega->displine + ega->y_add][ega->x_add + (x * 18) + xx] = 0;
break;
case 9:
for (xx = 0; xx < 16; xx++) buffer32->line[ega->displine + ega->y_add][ega->x_add + (x * 16) + xx] = 0;
break;
}
switch (ega->seqregs[1] & 9) {
case 0:
for (xx = 0; xx < 9; xx++)
buffer32->line[ega->displine + ega->y_add][ega->x_add + (x * 9) + xx] = 0;
break;
case 1:
for (xx = 0; xx < 8; xx++)
buffer32->line[ega->displine + ega->y_add][ega->x_add + (x * 8) + xx] = 0;
break;
case 8:
for (xx = 0; xx < 18; xx++)
buffer32->line[ega->displine + ega->y_add][ega->x_add + (x * 18) + xx] = 0;
break;
case 9:
for (xx = 0; xx < 16; xx++)
buffer32->line[ega->displine + ega->y_add][ega->x_add + (x * 16) + xx] = 0;
break;
}
}
}
void
ega_render_overscan_left(ega_t *ega)
{
int i;
if ((ega->displine + ega->y_add) < 0)
return;
return;
if (ega->scrblank || (ega->hdisp == 0))
return;
return;
for (i = 0; i < ega->x_add; i++)
buffer32->line[ega->displine + ega->y_add][i] = ega->overscan_color;
buffer32->line[ega->displine + ega->y_add][i] = ega->overscan_color;
}
void
ega_render_overscan_right(ega_t *ega)
{
int i, right;
if ((ega->displine + ega->y_add) < 0)
return;
return;
if (ega->scrblank || (ega->hdisp == 0))
return;
return;
right = (overscan_x >> 1) + ega->scrollcache;
for (i = 0; i < right; i++)
buffer32->line[ega->displine + ega->y_add][ega->x_add + ega->hdisp + i] = ega->overscan_color;
buffer32->line[ega->displine + ega->y_add][ega->x_add + ega->hdisp + i] = ega->overscan_color;
}
void
ega_render_text_40(ega_t *ega)
{
uint32_t *p;
int x, xx;
int drawcursor, xinc;
uint8_t chr, attr, dat;
uint32_t charaddr;
int fg, bg;
uint32_t addr;
int x, xx;
int drawcursor, xinc;
uint8_t chr, attr, dat;
uint32_t charaddr;
int fg, bg;
uint32_t addr;
if ((ega->displine + ega->y_add) < 0)
return;
return;
if (ega->firstline_draw == 2000)
ega->firstline_draw = ega->displine;
ega->firstline_draw = ega->displine;
ega->lastline_draw = ega->displine;
if (ega->fullchange) {
p = &buffer32->line[ega->displine + ega->y_add][ega->x_add];
xinc = (ega->seqregs[1] & 1) ? 16 : 18;
p = &buffer32->line[ega->displine + ega->y_add][ega->x_add];
xinc = (ega->seqregs[1] & 1) ? 16 : 18;
for (x = 0; x < (ega->hdisp + ega->scrollcache); x += xinc) {
addr = ega->remap_func(ega, ega->ma) & ega->vrammask;
for (x = 0; x < (ega->hdisp + ega->scrollcache); x += xinc) {
addr = ega->remap_func(ega, ega->ma) & ega->vrammask;
drawcursor = ((ega->ma == ega->ca) && ega->con && ega->cursoron);
drawcursor = ((ega->ma == ega->ca) && ega->con && ega->cursoron);
if (ega->crtc[0x17] & 0x80) {
chr = ega->vram[addr];
attr = ega->vram[addr + 1];
} else
chr = attr = 0;
if (ega->crtc[0x17] & 0x80) {
chr = ega->vram[addr];
attr = ega->vram[addr + 1];
} else
chr = attr = 0;
if (attr & 8)
charaddr = ega->charsetb + ((chr * 0x80));
else
charaddr = ega->charseta + ((chr * 0x80));
if (attr & 8)
charaddr = ega->charsetb + ((chr * 0x80));
else
charaddr = ega->charseta + ((chr * 0x80));
if (drawcursor) {
bg = ega->pallook[ega->egapal[attr & 0x0f]];
fg = ega->pallook[ega->egapal[attr >> 4]];
} else {
fg = ega->pallook[ega->egapal[attr & 0x0f]];
bg = ega->pallook[ega->egapal[attr >> 4]];
if (drawcursor) {
bg = ega->pallook[ega->egapal[attr & 0x0f]];
fg = ega->pallook[ega->egapal[attr >> 4]];
} else {
fg = ega->pallook[ega->egapal[attr & 0x0f]];
bg = ega->pallook[ega->egapal[attr >> 4]];
if ((attr & 0x80) && ega->attrregs[0x10] & 8) {
bg = ega->pallook[ega->egapal[(attr >> 4) & 7]];
if (ega->blink & 0x10)
fg = bg;
}
}
if ((attr & 0x80) && ega->attrregs[0x10] & 8) {
bg = ega->pallook[ega->egapal[(attr >> 4) & 7]];
if (ega->blink & 0x10)
fg = bg;
}
}
dat = ega->vram[charaddr + (ega->sc << 2)];
if (ega->seqregs[1] & 1) {
for (xx = 0; xx < 16; xx += 2)
p[xx] = p[xx + 1] = (dat & (0x80 >> (xx >> 1))) ? fg : bg;
} else {
for (xx = 0; xx < 16; xx += 2)
p[xx] = p[xx + 1] = (dat & (0x80 >> (xx >> 1))) ? fg : bg;
if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4))
p[16] = p[17] = bg;
else
p[16] = p[17] = (dat & 1) ? fg : bg;
}
ega->ma += 4;
p += xinc;
}
ega->ma &= ega->vrammask;
dat = ega->vram[charaddr + (ega->sc << 2)];
if (ega->seqregs[1] & 1) {
for (xx = 0; xx < 16; xx += 2)
p[xx] = p[xx + 1] = (dat & (0x80 >> (xx >> 1))) ? fg : bg;
} else {
for (xx = 0; xx < 16; xx += 2)
p[xx] = p[xx + 1] = (dat & (0x80 >> (xx >> 1))) ? fg : bg;
if ((chr & ~0x1f) != 0xc0 || !(ega->attrregs[0x10] & 4))
p[16] = p[17] = bg;
else
p[16] = p[17] = (dat & 1) ? fg : bg;
}
ega->ma += 4;
p += xinc;
}
ega->ma &= ega->vrammask;
}
}
void
ega_render_text_80(ega_t *ega)
{
uint32_t *p;
int x, xx;
int drawcursor, xinc;
uint8_t chr, attr, dat;
uint32_t charaddr;
int fg, bg;
uint32_t addr;
int x, xx;
int drawcursor, xinc;
uint8_t chr, attr, dat;
uint32_t charaddr;
int fg, bg;
uint32_t addr;
if ((ega->displine + ega->y_add) < 0)
return;
return;
if (ega->firstline_draw == 2000)
ega->firstline_draw = ega->displine;
ega->firstline_draw = ega->displine;
ega->lastline_draw = ega->displine;
if (ega->fullchange) {
p = &buffer32->line[ega->displine + ega->y_add][ega->x_add];
p = &buffer32->line[ega->displine + ega->y_add][ega->x_add];
xinc = (ega->seqregs[1] & 1) ? 8 : 9;
for (x = 0; x < (ega->hdisp + ega->scrollcache); x += xinc) {
@@ -205,8 +203,8 @@ ega_render_text_80(ega_t *ega)
drawcursor = ((ega->ma == ega->ca) && ega->con && ega->cursoron);
if (ega->crtc[0x17] & 0x80) {
chr = ega->vram[addr];
attr = ega->vram[addr + 1];
chr = ega->vram[addr];
attr = ega->vram[addr + 1];
} else
chr = attr = 0;
@@ -229,7 +227,7 @@ ega_render_text_80(ega_t *ega)
}
dat = ega->vram[charaddr + (ega->sc << 2)];
if (ega->seqregs[1] & 1) {
if (ega->seqregs[1] & 1) {
for (xx = 0; xx < 8; xx++)
p[xx] = (dat & (0x80 >> xx)) ? fg : bg;
} else {
@@ -247,16 +245,15 @@ ega_render_text_80(ega_t *ega)
}
}
void
ega_render_2bpp_lowres(ega_t *ega)
{
int x;
uint8_t dat[2];
int x;
uint8_t dat[2];
uint32_t addr, *p;
if ((ega->displine + ega->y_add) < 0)
return;
return;
p = &buffer32->line[ega->displine + ega->y_add][ega->x_add];
@@ -277,11 +274,11 @@ ega_render_2bpp_lowres(ega_t *ega)
ega->ma &= ega->vrammask;
if (ega->crtc[0x17] & 0x80) {
p[0] = p[1] = ega->pallook[ega->egapal[(dat[0] >> 6) & 3]];
p[2] = p[3] = ega->pallook[ega->egapal[(dat[0] >> 4) & 3]];
p[4] = p[5] = ega->pallook[ega->egapal[(dat[0] >> 2) & 3]];
p[6] = p[7] = ega->pallook[ega->egapal[dat[0] & 3]];
p[8] = p[9] = ega->pallook[ega->egapal[(dat[1] >> 6) & 3]];
p[0] = p[1] = ega->pallook[ega->egapal[(dat[0] >> 6) & 3]];
p[2] = p[3] = ega->pallook[ega->egapal[(dat[0] >> 4) & 3]];
p[4] = p[5] = ega->pallook[ega->egapal[(dat[0] >> 2) & 3]];
p[6] = p[7] = ega->pallook[ega->egapal[dat[0] & 3]];
p[8] = p[9] = ega->pallook[ega->egapal[(dat[1] >> 6) & 3]];
p[10] = p[11] = ega->pallook[ega->egapal[(dat[1] >> 4) & 3]];
p[12] = p[13] = ega->pallook[ega->egapal[(dat[1] >> 2) & 3]];
p[14] = p[15] = ega->pallook[ega->egapal[dat[1] & 3]];
@@ -292,16 +289,15 @@ ega_render_2bpp_lowres(ega_t *ega)
}
}
void
ega_render_2bpp_highres(ega_t *ega)
{
int x;
uint8_t dat[2];
int x;
uint8_t dat[2];
uint32_t addr, *p;
if ((ega->displine + ega->y_add) < 0)
return;
return;
p = &buffer32->line[ega->displine + ega->y_add][ega->x_add];
@@ -337,16 +333,15 @@ ega_render_2bpp_highres(ega_t *ega)
}
}
void
ega_render_4bpp_lowres(ega_t *ega)
{
int x, oddeven;
uint8_t dat, edat[4];
int x, oddeven;
uint8_t dat, edat[4];
uint32_t addr, *p;
if ((ega->displine + ega->y_add) < 0)
return;
return;
p = &buffer32->line[ega->displine + ega->y_add][ega->x_add];
@@ -355,32 +350,32 @@ ega_render_4bpp_lowres(ega_t *ega)
ega->lastline_draw = ega->displine;
for (x = 0; x <= (ega->hdisp + ega->scrollcache); x += 16) {
addr = ega->remap_func(ega, ega->ma);
addr = ega->remap_func(ega, ega->ma);
oddeven = 0;
if (ega->seqregs[1] & 4) {
oddeven = (addr & 4) ? 1 : 0;
edat[0] = ega->vram[addr | oddeven];
edat[2] = ega->vram[addr | oddeven | 0x2];
edat[1] = edat[3] = 0;
edat[1] = edat[3] = 0;
ega->ma += 2;
} else {
*(uint32_t *)(&edat[0]) = *(uint32_t *)(&ega->vram[addr]);
*(uint32_t *) (&edat[0]) = *(uint32_t *) (&ega->vram[addr]);
ega->ma += 4;
}
ega->ma &= ega->vrammask;
if (ega->crtc[0x17] & 0x80) {
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
p[0] = p[1] = ega->pallook[ega->egapal[(dat >> 4) & ega->plane_mask]];
p[2] = p[3] = ega->pallook[ega->egapal[dat & ega->plane_mask]];
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
p[4] = p[5] = ega->pallook[ega->egapal[(dat >> 4) & ega->plane_mask]];
p[6] = p[7] = ega->pallook[ega->egapal[dat & ega->plane_mask]];
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
p[8] = p[9] = ega->pallook[ega->egapal[(dat >> 4) & ega->plane_mask]];
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
p[0] = p[1] = ega->pallook[ega->egapal[(dat >> 4) & ega->plane_mask]];
p[2] = p[3] = ega->pallook[ega->egapal[dat & ega->plane_mask]];
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
p[4] = p[5] = ega->pallook[ega->egapal[(dat >> 4) & ega->plane_mask]];
p[6] = p[7] = ega->pallook[ega->egapal[dat & ega->plane_mask]];
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
p[8] = p[9] = ega->pallook[ega->egapal[(dat >> 4) & ega->plane_mask]];
p[10] = p[11] = ega->pallook[ega->egapal[dat & ega->plane_mask]];
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
p[12] = p[13] = ega->pallook[ega->egapal[(dat >> 4) & ega->plane_mask]];
p[14] = p[15] = ega->pallook[ega->egapal[dat & ega->plane_mask]];
} else
@@ -390,16 +385,15 @@ ega_render_4bpp_lowres(ega_t *ega)
}
}
void
ega_render_4bpp_highres(ega_t *ega)
{
int x, oddeven;
uint8_t dat, edat[4];
int x, oddeven;
uint8_t dat, edat[4];
uint32_t addr, *p;
if ((ega->displine + ega->y_add) < 0)
return;
return;
p = &buffer32->line[ega->displine + ega->y_add][ega->x_add];
@@ -408,32 +402,32 @@ ega_render_4bpp_highres(ega_t *ega)
ega->lastline_draw = ega->displine;
for (x = 0; x <= (ega->hdisp + ega->scrollcache); x += 8) {
addr = ega->remap_func(ega, ega->ma);
addr = ega->remap_func(ega, ega->ma);
oddeven = 0;
if (ega->seqregs[1] & 4) {
oddeven = (addr & 4) ? 1 : 0;
edat[0] = ega->vram[addr | oddeven];
edat[2] = ega->vram[addr | oddeven | 0x2];
edat[1] = edat[3] = 0;
edat[1] = edat[3] = 0;
ega->ma += 2;
} else {
*(uint32_t *)(&edat[0]) = *(uint32_t *)(&ega->vram[addr]);
*(uint32_t *) (&edat[0]) = *(uint32_t *) (&ega->vram[addr]);
ega->ma += 4;
}
ega->ma &= ega->vrammask;
if (ega->crtc[0x17] & 0x80) {
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
p[0] = ega->pallook[ega->egapal[(dat >> 4) & ega->plane_mask]];
p[1] = ega->pallook[ega->egapal[dat & ega->plane_mask]];
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
p[2] = ega->pallook[ega->egapal[(dat >> 4) & ega->plane_mask]];
p[3] = ega->pallook[ega->egapal[dat & ega->plane_mask]];
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
p[4] = ega->pallook[ega->egapal[(dat >> 4) & ega->plane_mask]];
p[5] = ega->pallook[ega->egapal[dat & ega->plane_mask]];
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
p[6] = ega->pallook[ega->egapal[(dat >> 4) & ega->plane_mask]];
p[7] = ega->pallook[ega->egapal[dat & ega->plane_mask]];
} else

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -33,9 +33,7 @@
#include <86box/video.h>
#include <86box/vid_hercules.h>
static video_timings_t timing_hercules = {VIDEO_ISA, 8, 16, 32, 8, 16, 32};
static video_timings_t timing_hercules = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 };
static void
recalc_timings(hercules_t *dev)
@@ -43,196 +41,190 @@ recalc_timings(hercules_t *dev)
double disptime;
double _dispontime, _dispofftime;
disptime = dev->crtc[0] + 1;
disptime = dev->crtc[0] + 1;
_dispontime = dev->crtc[1];
_dispofftime = disptime - _dispontime;
_dispontime *= HERCCONST;
_dispontime *= HERCCONST;
_dispofftime *= HERCCONST;
dev->dispontime = (uint64_t)(_dispontime);
dev->dispofftime = (uint64_t)(_dispofftime);
dev->dispontime = (uint64_t) (_dispontime);
dev->dispofftime = (uint64_t) (_dispofftime);
}
static uint8_t crtcmask[32] =
{
0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
static uint8_t crtcmask[32] = {
0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static void
hercules_out(uint16_t addr, uint8_t val, void *priv)
{
hercules_t *dev = (hercules_t *)priv;
uint8_t old;
hercules_t *dev = (hercules_t *) priv;
uint8_t old;
VIDEO_MONITOR_PROLOGUE()
switch (addr) {
case 0x03b0:
case 0x03b2:
case 0x03b4:
case 0x03b6:
dev->crtcreg = val & 31;
break;
case 0x03b0:
case 0x03b2:
case 0x03b4:
case 0x03b6:
dev->crtcreg = val & 31;
break;
case 0x03b1:
case 0x03b3:
case 0x03b5:
case 0x03b7:
old = dev->crtc[dev->crtcreg];
dev->crtc[dev->crtcreg] = val & crtcmask[dev->crtcreg];
case 0x03b1:
case 0x03b3:
case 0x03b5:
case 0x03b7:
old = dev->crtc[dev->crtcreg];
dev->crtc[dev->crtcreg] = val & crtcmask[dev->crtcreg];
/*
* Fix for Generic Turbo XT BIOS, which
* sets up cursor registers wrong.
*/
if (dev->crtc[10] == 6 && dev->crtc[11] == 7) {
dev->crtc[10] = 0xb;
dev->crtc[11] = 0xc;
}
/*
* Fix for Generic Turbo XT BIOS, which
* sets up cursor registers wrong.
*/
if (dev->crtc[10] == 6 && dev->crtc[11] == 7) {
dev->crtc[10] = 0xb;
dev->crtc[11] = 0xc;
}
if (old != val) {
if ((dev->crtcreg < 0xe) || (dev->crtcreg > 0x10)) {
dev->fullchange = changeframecount;
recalc_timings(dev);
}
}
break;
if (old != val) {
if ((dev->crtcreg < 0xe) || (dev->crtcreg > 0x10)) {
dev->fullchange = changeframecount;
recalc_timings(dev);
}
}
break;
case 0x03b8:
old = dev->ctrl;
case 0x03b8:
old = dev->ctrl;
/* Prevent setting of bits if they are disabled in CTRL2. */
if ((old & 0x02) && !(val & 0x02))
dev->ctrl &= 0xfd;
else if ((val & 0x02) && (dev->ctrl2 & 0x01))
dev->ctrl |= 0x02;
/* Prevent setting of bits if they are disabled in CTRL2. */
if ((old & 0x02) && !(val & 0x02))
dev->ctrl &= 0xfd;
else if ((val & 0x02) && (dev->ctrl2 & 0x01))
dev->ctrl |= 0x02;
if ((old & 0x80) && !(val & 0x80))
dev->ctrl &= 0x7f;
else if ((val & 0x80) && (dev->ctrl2 & 0x02))
dev->ctrl |= 0x80;
if ((old & 0x80) && !(val & 0x80))
dev->ctrl &= 0x7f;
else if ((val & 0x80) && (dev->ctrl2 & 0x02))
dev->ctrl |= 0x80;
dev->ctrl = (dev->ctrl & 0x82) | (val & 0x7d);
dev->ctrl = (dev->ctrl & 0x82) | (val & 0x7d);
if (old ^ val)
recalc_timings(dev);
break;
if (old ^ val)
recalc_timings(dev);
break;
case 0x03b9:
case 0x03bb:
dev->lp_ff = !(addr & 0x0002);
break;
case 0x03b9:
case 0x03bb:
dev->lp_ff = !(addr & 0x0002);
break;
case 0x03bf:
old = dev->ctrl2;
dev->ctrl2 = val;
/* According to the Programmer's guide to the Hercules graphics cars
by David B. Doty from 1988, the CTRL2 modes (bits 1,0) are as follow:
- 00: DIAG: Text mode only, only page 0 accessible;
- 01: HALF: Graphics mode allowed, only page 0 accessible;
- 11: FULL: Graphics mode allowed, both pages accessible. */
if (val & 0x01)
mem_mapping_set_exec(&dev->mapping, dev->vram);
else
mem_mapping_set_exec(&dev->mapping, NULL);
if (val & 0x02)
mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x10000);
else
mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x08000);
if (old ^ val)
recalc_timings(dev);
break;
case 0x03bf:
old = dev->ctrl2;
dev->ctrl2 = val;
/* According to the Programmer's guide to the Hercules graphics cars
by David B. Doty from 1988, the CTRL2 modes (bits 1,0) are as follow:
- 00: DIAG: Text mode only, only page 0 accessible;
- 01: HALF: Graphics mode allowed, only page 0 accessible;
- 11: FULL: Graphics mode allowed, both pages accessible. */
if (val & 0x01)
mem_mapping_set_exec(&dev->mapping, dev->vram);
else
mem_mapping_set_exec(&dev->mapping, NULL);
if (val & 0x02)
mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x10000);
else
mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x08000);
if (old ^ val)
recalc_timings(dev);
break;
default:
break;
default:
break;
}
VIDEO_MONITOR_EPILOGUE()
}
static uint8_t
hercules_in(uint16_t addr, void *priv)
{
hercules_t *dev = (hercules_t *)priv;
uint8_t ret = 0xff;
hercules_t *dev = (hercules_t *) priv;
uint8_t ret = 0xff;
switch (addr) {
case 0x03b0:
case 0x03b2:
case 0x03b4:
case 0x03b6:
ret = dev->crtcreg;
break;
case 0x03b0:
case 0x03b2:
case 0x03b4:
case 0x03b6:
ret = dev->crtcreg;
break;
case 0x03b1:
case 0x03b3:
case 0x03b5:
case 0x03b7:
if (dev->crtcreg == 0x0c)
ret = (dev->ma >> 8) & 0x3f;
else if (dev->crtcreg == 0x0d)
ret = dev->ma & 0xff;
else
ret = dev->crtc[dev->crtcreg];
break;
case 0x03b1:
case 0x03b3:
case 0x03b5:
case 0x03b7:
if (dev->crtcreg == 0x0c)
ret = (dev->ma >> 8) & 0x3f;
else if (dev->crtcreg == 0x0d)
ret = dev->ma & 0xff;
else
ret = dev->crtc[dev->crtcreg];
break;
case 0x03ba:
ret = 0x70; /* Hercules ident */
ret |= (dev->lp_ff ? 2 : 0);
ret |= (dev->stat & 0x01);
if (dev->stat & 0x08)
ret |= 0x80;
if ((ret & 0x81) == 0x80)
ret |= 0x08;
break;
case 0x03ba:
ret = 0x70; /* Hercules ident */
ret |= (dev->lp_ff ? 2 : 0);
ret |= (dev->stat & 0x01);
if (dev->stat & 0x08)
ret |= 0x80;
if ((ret & 0x81) == 0x80)
ret |= 0x08;
break;
default:
break;
default:
break;
}
return(ret);
return (ret);
}
static void
hercules_waitstates(void *p)
{
int ws_array[16] = {3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8};
int ws_array[16] = { 3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8 };
int ws;
ws = ws_array[cycles & 0xf];
cycles -= ws;
}
static void
hercules_write(uint32_t addr, uint8_t val, void *priv)
{
hercules_t *dev = (hercules_t *)priv;
hercules_t *dev = (hercules_t *) priv;
if (dev->ctrl2 & 0x01)
addr &= 0xffff;
addr &= 0xffff;
else
addr &= 0x0fff;
addr &= 0x0fff;
dev->vram[addr] = val;
hercules_waitstates(dev);
}
static uint8_t
hercules_read(uint32_t addr, void *priv)
{
hercules_t *dev = (hercules_t *)priv;
uint8_t ret = 0xff;
hercules_t *dev = (hercules_t *) priv;
uint8_t ret = 0xff;
if (dev->ctrl2 & 0x01)
addr &= 0xffff;
addr &= 0xffff;
else
addr &= 0x0fff;
addr &= 0x0fff;
hercules_waitstates(dev);
@@ -241,333 +233,325 @@ hercules_read(uint32_t addr, void *priv)
return ret;
}
static void
hercules_render_overscan_left(hercules_t *dev)
{
int i;
int i;
uint32_t width;
if (dev->ctrl & 0x02)
width = (((uint32_t) dev->crtc[1]) << 4);
width = (((uint32_t) dev->crtc[1]) << 4);
else
width = (((uint32_t) dev->crtc[1]) * 9);
width = (((uint32_t) dev->crtc[1]) * 9);
if ((dev->displine + 14) < 0)
return;
return;
if (width == 0)
return;
return;
for (i = 0; i < 8; i++)
buffer32->line[dev->displine + 14][i] = 0x00000000;
buffer32->line[dev->displine + 14][i] = 0x00000000;
}
static void
hercules_render_overscan_right(hercules_t *dev)
{
int i;
int i;
uint32_t width;
if (dev->ctrl & 0x02)
width = (((uint32_t) dev->crtc[1]) << 4);
width = (((uint32_t) dev->crtc[1]) << 4);
else
width = (((uint32_t) dev->crtc[1]) * 9);
width = (((uint32_t) dev->crtc[1]) * 9);
if ((dev->displine + 14) < 0)
return;
return;
if (width == 0)
return;
return;
for (i = 0; i < 8; i++)
buffer32->line[dev->displine + 14][8 + width + i] = 0x00000000;
buffer32->line[dev->displine + 14][8 + width + i] = 0x00000000;
}
static void
hercules_poll(void *priv)
{
hercules_t *dev = (hercules_t *)priv;
uint8_t chr, attr;
uint16_t ca, dat;
uint16_t pa;
int oldsc, blink;
int x, xx, y, yy, c, oldvc;
int drawcursor;
uint32_t *p;
hercules_t *dev = (hercules_t *) priv;
uint8_t chr, attr;
uint16_t ca, dat;
uint16_t pa;
int oldsc, blink;
int x, xx, y, yy, c, oldvc;
int drawcursor;
uint32_t *p;
VIDEO_MONITOR_PROLOGUE()
ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff;
if (! dev->linepos) {
timer_advance_u64(&dev->timer, dev->dispofftime);
dev->stat |= 1;
dev->linepos = 1;
oldsc = dev->sc;
if (!dev->linepos) {
timer_advance_u64(&dev->timer, dev->dispofftime);
dev->stat |= 1;
dev->linepos = 1;
oldsc = dev->sc;
if ((dev->crtc[8] & 3) == 3)
dev->sc = (dev->sc << 1) & 7;
if ((dev->crtc[8] & 3) == 3)
dev->sc = (dev->sc << 1) & 7;
if (dev->dispon) {
if (dev->displine < dev->firstline) {
dev->firstline = dev->displine;
video_wait_for_buffer();
}
dev->lastline = dev->displine;
if (dev->dispon) {
if (dev->displine < dev->firstline) {
dev->firstline = dev->displine;
video_wait_for_buffer();
}
dev->lastline = dev->displine;
hercules_render_overscan_left(dev);
hercules_render_overscan_left(dev);
if (dev->ctrl & 0x02) {
ca = (dev->sc & 3) * 0x2000;
if (dev->ctrl & 0x80)
ca += 0x8000;
if (dev->ctrl & 0x02) {
ca = (dev->sc & 3) * 0x2000;
if (dev->ctrl & 0x80)
ca += 0x8000;
for (x = 0; x < dev->crtc[1]; x++) {
if (dev->ctrl & 8)
dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ca] << 8) | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 1];
else
dat = 0;
dev->ma++;
for (c = 0; c < 16; c++)
buffer32->line[dev->displine + 14][(x << 4) + c + 8] = (dat & (32768 >> c)) ? 7 : 0;
for (c = 0; c < 16; c += 8)
video_blend((x << 4) + c + 8, dev->displine + 14);
}
} else {
for (x = 0; x < dev->crtc[1]; x++) {
if (dev->ctrl & 8) {
/* Undocumented behavior: page 1 in text mode means characters are read
from page 1 and attributes from page 0. */
chr = dev->charbuffer[x << 1];
attr = dev->charbuffer[(x << 1) + 1];
} else
chr = attr = 0;
drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron);
blink = ((dev->blink & 16) && (dev->ctrl & 0x20) && (attr & 0x80) && !drawcursor);
for (x = 0; x < dev->crtc[1]; x++) {
if (dev->ctrl & 8)
dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ca] << 8) | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 1];
else
dat = 0;
dev->ma++;
for (c = 0; c < 16; c++)
buffer32->line[dev->displine + 14][(x << 4) + c + 8] = (dat & (32768 >> c)) ? 7 : 0;
for (c = 0; c < 16; c += 8)
video_blend((x << 4) + c + 8, dev->displine + 14);
}
} else {
for (x = 0; x < dev->crtc[1]; x++) {
if (dev->ctrl & 8) {
/* Undocumented behavior: page 1 in text mode means characters are read
from page 1 and attributes from page 0. */
chr = dev->charbuffer[x << 1];
attr = dev->charbuffer[(x << 1) + 1];
} else
chr = attr = 0;
drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron);
blink = ((dev->blink & 16) && (dev->ctrl & 0x20) && (attr & 0x80) && !drawcursor);
if (dev->sc == 12 && ((attr & 7) == 1)) {
for (c = 0; c < 9; c++)
buffer32->line[dev->displine + 14][(x * 9) + c + 8] = dev->cols[attr][blink][1];
} else {
for (c = 0; c < 8; c++)
buffer32->line[dev->displine + 14][(x * 9) + c + 8] = dev->cols[attr][blink][(fontdatm[chr][dev->sc] & (1 << (c ^ 7))) ? 1 : 0];
if (dev->sc == 12 && ((attr & 7) == 1)) {
for (c = 0; c < 9; c++)
buffer32->line[dev->displine + 14][(x * 9) + c + 8] = dev->cols[attr][blink][1];
} else {
for (c = 0; c < 8; c++)
buffer32->line[dev->displine + 14][(x * 9) + c + 8] = dev->cols[attr][blink][(fontdatm[chr][dev->sc] & (1 << (c ^ 7))) ? 1 : 0];
if ((chr & ~0x1f) == 0xc0)
buffer32->line[dev->displine + 14][(x * 9) + 8 + 8] = dev->cols[attr][blink][fontdatm[chr][dev->sc] & 1];
else
buffer32->line[dev->displine + 14][(x * 9) + 8 + 8] = dev->cols[attr][blink][0];
}
if (dev->ctrl2 & 0x01)
dev->ma = (dev->ma + 1) & 0x3fff;
else
dev->ma = (dev->ma + 1) & 0x7ff;
if ((chr & ~0x1f) == 0xc0)
buffer32->line[dev->displine + 14][(x * 9) + 8 + 8] = dev->cols[attr][blink][fontdatm[chr][dev->sc] & 1];
else
buffer32->line[dev->displine + 14][(x * 9) + 8 + 8] = dev->cols[attr][blink][0];
}
if (dev->ctrl2 & 0x01)
dev->ma = (dev->ma + 1) & 0x3fff;
else
dev->ma = (dev->ma + 1) & 0x7ff;
if (drawcursor) {
for (c = 0; c < 9; c++)
buffer32->line[dev->displine + 14][(x * 9) + c + 8] ^= dev->cols[attr][0][1];
}
}
}
if (drawcursor) {
for (c = 0; c < 9; c++)
buffer32->line[dev->displine + 14][(x * 9) + c + 8] ^= dev->cols[attr][0][1];
}
}
}
hercules_render_overscan_right(dev);
}
dev->sc = oldsc;
hercules_render_overscan_right(dev);
}
dev->sc = oldsc;
if (dev->vc == dev->crtc[7] && !dev->sc)
dev->stat |= 8;
dev->displine++;
if (dev->displine >= 500)
dev->displine = 0;
if (dev->vc == dev->crtc[7] && !dev->sc)
dev->stat |= 8;
dev->displine++;
if (dev->displine >= 500)
dev->displine = 0;
} else {
timer_advance_u64(&dev->timer, dev->dispontime);
timer_advance_u64(&dev->timer, dev->dispontime);
if (dev->dispon)
dev->stat &= ~1;
if (dev->dispon)
dev->stat &= ~1;
dev->linepos = 0;
if (dev->vsynctime) {
dev->vsynctime--;
if (! dev->vsynctime)
dev->stat &= ~8;
}
dev->linepos = 0;
if (dev->vsynctime) {
dev->vsynctime--;
if (!dev->vsynctime)
dev->stat &= ~8;
}
if (dev->sc == (dev->crtc[11] & 31) ||
((dev->crtc[8] & 3)==3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) {
dev->con = 0;
dev->coff = 1;
}
if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) {
dev->con = 0;
dev->coff = 1;
}
if (dev->vadj) {
dev->sc++;
dev->sc &= 31;
dev->ma = dev->maback;
dev->vadj--;
if (! dev->vadj) {
dev->dispon = 1;
dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff;
dev->sc = 0;
}
} else if (((dev->crtc[8] & 3) != 3 && dev->sc == dev->crtc[9]) || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) {
dev->maback = dev->ma;
dev->sc = 0;
oldvc = dev->vc;
dev->vc++;
dev->vc &= 127;
if (dev->vadj) {
dev->sc++;
dev->sc &= 31;
dev->ma = dev->maback;
dev->vadj--;
if (!dev->vadj) {
dev->dispon = 1;
dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff;
dev->sc = 0;
}
} else if (((dev->crtc[8] & 3) != 3 && dev->sc == dev->crtc[9]) || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) {
dev->maback = dev->ma;
dev->sc = 0;
oldvc = dev->vc;
dev->vc++;
dev->vc &= 127;
if (dev->vc == dev->crtc[6])
dev->dispon = 0;
if (dev->vc == dev->crtc[6])
dev->dispon = 0;
if (oldvc == dev->crtc[4]) {
dev->vc = 0;
dev->vadj = dev->crtc[5];
if (! dev->vadj) {
dev->dispon = 1;
dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff;
}
switch (dev->crtc[10] & 0x60) {
case 0x20:
dev->cursoron = 0;
break;
case 0x60:
dev->cursoron = dev->blink & 0x10;
break;
default:
dev->cursoron = dev->blink & 0x08;
break;
}
}
if (oldvc == dev->crtc[4]) {
dev->vc = 0;
dev->vadj = dev->crtc[5];
if (!dev->vadj) {
dev->dispon = 1;
dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff;
}
switch (dev->crtc[10] & 0x60) {
case 0x20:
dev->cursoron = 0;
break;
case 0x60:
dev->cursoron = dev->blink & 0x10;
break;
default:
dev->cursoron = dev->blink & 0x08;
break;
}
}
if (dev->vc == dev->crtc[7]) {
dev->dispon = 0;
dev->displine = 0;
if ((dev->crtc[8] & 3) == 3)
dev->vsynctime = ((int32_t)dev->crtc[4] * ((dev->crtc[9] >> 1) + 1)) + dev->crtc[5] - dev->crtc[7] + 1;
else
dev->vsynctime = ((int32_t)dev->crtc[4] * (dev->crtc[9] + 1)) + dev->crtc[5] - dev->crtc[7] + 1;
if (dev->crtc[7]) {
if (dev->ctrl & 0x02)
x = dev->crtc[1] << 4;
else
x = dev->crtc[1] * 9;
if (dev->vc == dev->crtc[7]) {
dev->dispon = 0;
dev->displine = 0;
if ((dev->crtc[8] & 3) == 3)
dev->vsynctime = ((int32_t) dev->crtc[4] * ((dev->crtc[9] >> 1) + 1)) + dev->crtc[5] - dev->crtc[7] + 1;
else
dev->vsynctime = ((int32_t) dev->crtc[4] * (dev->crtc[9] + 1)) + dev->crtc[5] - dev->crtc[7] + 1;
if (dev->crtc[7]) {
if (dev->ctrl & 0x02)
x = dev->crtc[1] << 4;
else
x = dev->crtc[1] * 9;
dev->lastline++;
y = (dev->lastline - dev->firstline);
dev->lastline++;
y = (dev->lastline - dev->firstline);
if ((dev->ctrl & 8) && x && y && ((x != xsize) || (y != ysize) || video_force_resize_get())) {
xsize = x;
ysize = y;
if (xsize < 64) xsize = enable_overscan ? 640 : 656;
if (ysize < 32) ysize = 200;
if ((dev->ctrl & 8) && x && y && ((x != xsize) || (y != ysize) || video_force_resize_get())) {
xsize = x;
ysize = y;
if (xsize < 64)
xsize = enable_overscan ? 640 : 656;
if (ysize < 32)
ysize = 200;
set_screen_size(xsize + (enable_overscan ? 16 : 0), ysize + (enable_overscan ? 28 : 0));
set_screen_size(xsize + (enable_overscan ? 16 : 0), ysize + (enable_overscan ? 28 : 0));
if (video_force_resize_get())
video_force_resize_set(0);
}
if (video_force_resize_get())
video_force_resize_set(0);
}
if ((x >= 160) && ((y + 1) >= 120)) {
/* Draw (overscan_size) lines of overscan on top and bottom. */
for (yy = 0; yy < 14; yy++) {
p = &(buffer32->line[(dev->firstline + yy) & 0x7ff][0]);
if ((x >= 160) && ((y + 1) >= 120)) {
/* Draw (overscan_size) lines of overscan on top and bottom. */
for (yy = 0; yy < 14; yy++) {
p = &(buffer32->line[(dev->firstline + yy) & 0x7ff][0]);
for (xx = 0; xx < (x + 16); xx++)
p[xx] = 0x00000000;
}
for (xx = 0; xx < (x + 16); xx++)
p[xx] = 0x00000000;
}
for (yy = 0; yy < 14; yy++) {
p = &(buffer32->line[(dev->firstline + 14 + y + yy) & 0x7ff][0]);
for (yy = 0; yy < 14; yy++) {
p = &(buffer32->line[(dev->firstline + 14 + y + yy) & 0x7ff][0]);
for (xx = 0; xx < (x + 16); xx++)
p[xx] = 0x00000000;
}
}
for (xx = 0; xx < (x + 16); xx++)
p[xx] = 0x00000000;
}
}
if (enable_overscan)
video_blit_memtoscreen_8(0, dev->firstline, xsize + 16, ysize + 28);
else
video_blit_memtoscreen_8(8, dev->firstline + 14, xsize, ysize);
frames++;
// if ((dev->ctrl & 2) && (dev->ctrl2 & 1)) {
if (dev->ctrl & 0x02) {
video_res_x = dev->crtc[1] * 16;
video_res_y = dev->crtc[6] * 4;
video_bpp = 1;
} else {
video_res_x = dev->crtc[1];
video_res_y = dev->crtc[6];
video_bpp = 0;
}
}
dev->firstline = 1000;
dev->lastline = 0;
dev->blink++;
}
} else {
dev->sc++;
dev->sc &= 31;
dev->ma = dev->maback;
}
if (enable_overscan)
video_blit_memtoscreen_8(0, dev->firstline, xsize + 16, ysize + 28);
else
video_blit_memtoscreen_8(8, dev->firstline + 14, xsize, ysize);
frames++;
// if ((dev->ctrl & 2) && (dev->ctrl2 & 1)) {
if (dev->ctrl & 0x02) {
video_res_x = dev->crtc[1] * 16;
video_res_y = dev->crtc[6] * 4;
video_bpp = 1;
} else {
video_res_x = dev->crtc[1];
video_res_y = dev->crtc[6];
video_bpp = 0;
}
}
dev->firstline = 1000;
dev->lastline = 0;
dev->blink++;
}
} else {
dev->sc++;
dev->sc &= 31;
dev->ma = dev->maback;
}
if ((dev->sc == (dev->crtc[10] & 31) ||
((dev->crtc[8] & 3)==3 && dev->sc == ((dev->crtc[10] & 31) >> 1))))
dev->con = 1;
if (dev->dispon && !(dev->ctrl & 0x02)) {
for (x = 0; x < (dev->crtc[1] << 1); x++) {
pa = (dev->ctrl & 0x80) ? ((x & 1) ? 0x0000 : 0x8000) : 0x0000;
dev->charbuffer[x] = dev->vram[(((dev->ma << 1) + x) & 0x3fff) + pa];
}
}
if ((dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1))))
dev->con = 1;
if (dev->dispon && !(dev->ctrl & 0x02)) {
for (x = 0; x < (dev->crtc[1] << 1); x++) {
pa = (dev->ctrl & 0x80) ? ((x & 1) ? 0x0000 : 0x8000) : 0x0000;
dev->charbuffer[x] = dev->vram[(((dev->ma << 1) + x) & 0x3fff) + pa];
}
}
}
VIDEO_MONITOR_EPILOGUE()
}
static void *
hercules_init(const device_t *info)
{
hercules_t *dev;
int c;
int c;
dev = (hercules_t *)malloc(sizeof(hercules_t));
dev = (hercules_t *) malloc(sizeof(hercules_t));
memset(dev, 0x00, sizeof(hercules_t));
dev->monitor_index = monitor_index_global;
overscan_x = 16;
overscan_y = 28;
dev->vram = (uint8_t *)malloc(0x10000);
dev->vram = (uint8_t *) malloc(0x10000);
timer_add(&dev->timer, hercules_poll, dev, 1);
mem_mapping_add(&dev->mapping, 0xb0000, 0x08000,
hercules_read,NULL,NULL, hercules_write,NULL,NULL,
NULL /*dev->vram*/, MEM_MAPPING_EXTERNAL, dev);
hercules_read, NULL, NULL, hercules_write, NULL, NULL,
NULL /*dev->vram*/, MEM_MAPPING_EXTERNAL, dev);
io_sethandler(0x03b0, 16,
hercules_in,NULL,NULL, hercules_out,NULL,NULL, dev);
hercules_in, NULL, NULL, hercules_out, NULL, NULL, dev);
for (c = 0; c < 256; c++) {
dev->cols[c][0][0] = dev->cols[c][1][0] = dev->cols[c][1][1] = 16;
dev->cols[c][0][0] = dev->cols[c][1][0] = dev->cols[c][1][1] = 16;
if (c & 0x08)
dev->cols[c][0][1] = 15 + 16;
else
dev->cols[c][0][1] = 7 + 16;
if (c & 0x08)
dev->cols[c][0][1] = 15 + 16;
else
dev->cols[c][0][1] = 7 + 16;
}
dev->cols[0x70][0][1] = 16;
dev->cols[0x70][0][0] = dev->cols[0x70][1][0] =
dev->cols[0x70][1][1] = 16 + 15;
dev->cols[0xF0][0][1] = 16;
dev->cols[0xF0][0][0] = dev->cols[0xF0][1][0] =
dev->cols[0xF0][1][1] = 16 + 15;
dev->cols[0x78][0][1] = 16 + 7;
dev->cols[0x78][0][0] = dev->cols[0x78][1][0] =
dev->cols[0x78][1][1] = 16 + 15;
dev->cols[0xF8][0][1] = 16 + 7;
dev->cols[0xF8][0][0] = dev->cols[0xF8][1][0] =
dev->cols[0xF8][1][1] = 16 + 15;
dev->cols[0x70][0][0] = dev->cols[0x70][1][0] = dev->cols[0x70][1][1] = 16 + 15;
dev->cols[0xF0][0][1] = 16;
dev->cols[0xF0][0][0] = dev->cols[0xF0][1][0] = dev->cols[0xF0][1][1] = 16 + 15;
dev->cols[0x78][0][1] = 16 + 7;
dev->cols[0x78][0][0] = dev->cols[0x78][1][0] = dev->cols[0x78][1][1] = 16 + 15;
dev->cols[0xF8][0][1] = 16 + 7;
dev->cols[0xF8][0][0] = dev->cols[0xF8][1][0] = dev->cols[0xF8][1][1] = 16 + 15;
dev->cols[0x00][0][1] = dev->cols[0x00][1][1] = 16;
dev->cols[0x08][0][1] = dev->cols[0x08][1][1] = 16;
dev->cols[0x80][0][1] = dev->cols[0x80][1][1] = 16;
@@ -577,7 +561,7 @@ hercules_init(const device_t *info)
cga_palette = device_get_config_int("rgb_type") << 1;
if (cga_palette > 6)
cga_palette = 0;
cga_palette = 0;
cgapal_rebuild();
herc_blend = device_get_config_int("blend");
@@ -587,35 +571,33 @@ hercules_init(const device_t *info)
/* Force the LPT3 port to be enabled. */
lpt3_init(0x3BC);
return(dev);
return (dev);
}
static void
hercules_close(void *priv)
{
hercules_t *dev = (hercules_t *)priv;
hercules_t *dev = (hercules_t *) priv;
if (!dev)
return;
return;
if (dev->vram)
free(dev->vram);
free(dev->vram);
free(dev);
}
static void
speed_changed(void *priv)
{
hercules_t *dev = (hercules_t *)priv;
hercules_t *dev = (hercules_t *) priv;
recalc_timings(dev);
}
static const device_config_t hercules_config[] = {
// clang-format off
// clang-format off
{
.name = "rgb_type",
.description = "Display type",
@@ -656,15 +638,15 @@ static const device_config_t hercules_config[] = {
};
const device_t hercules_device = {
.name = "Hercules",
.name = "Hercules",
.internal_name = "hercules",
.flags = DEVICE_ISA,
.local = 0,
.init = hercules_init,
.close = hercules_close,
.reset = NULL,
.flags = DEVICE_ISA,
.local = 0,
.init = hercules_init,
.close = hercules_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = speed_changed,
.force_redraw = NULL,
.config = hercules_config
.force_redraw = NULL,
.config = hercules_config
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -28,37 +28,32 @@
#include <86box/86box.h>
#include <86box/device.h>
typedef struct icd2061_t
{
typedef struct icd2061_t {
float freq[3];
int count, bit_count,
unlocked, state;
unlocked, state;
uint32_t data, ctrl;
} icd2061_t;
#ifdef ENABLE_ICD2061_LOG
int icd2061_do_log = ENABLE_ICD2061_LOG;
static void
icd2061_log(const char *fmt, ...)
{
va_list ap;
if (icd2061_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define icd2061_log(fmt, ...)
# define icd2061_log(fmt, ...)
#endif
void
icd2061_write(void *p, int val)
{
@@ -67,81 +62,79 @@ icd2061_write(void *p, int val)
int nd, oc, nc;
int a, qa, q, pa, p_, m, ps;
nd = (val & 2) >> 1; /* Old data. */
oc = icd2061->state & 1; /* Old clock. */
nc = val & 1; /* New clock. */
nd = (val & 2) >> 1; /* Old data. */
oc = icd2061->state & 1; /* Old clock. */
nc = val & 1; /* New clock. */
icd2061->state = val;
if (nc && !oc) { /* Low-to-high transition of CLK. */
if (!icd2061->unlocked) {
if (nd) { /* DATA high. */
icd2061->count++;
icd2061_log("Low-to-high transition of CLK with DATA high, %i total\n", icd2061->count);
} else { /* DATA low. */
if (icd2061->count >= 5) {
icd2061->unlocked = 1;
icd2061->bit_count = icd2061->data = 0;
if (nc && !oc) { /* Low-to-high transition of CLK. */
if (!icd2061->unlocked) {
if (nd) { /* DATA high. */
icd2061->count++;
icd2061_log("Low-to-high transition of CLK with DATA high, %i total\n", icd2061->count);
} else { /* DATA low. */
if (icd2061->count >= 5) {
icd2061->unlocked = 1;
icd2061->bit_count = icd2061->data = 0;
#ifdef ENABLE_ICD2061_LOG
icd2061_log("ICD2061 unlocked\n");
icd2061_log("ICD2061 unlocked\n");
#endif
} else {
icd2061->count = 0;
} else {
icd2061->count = 0;
#ifdef ENABLE_ICD2061_LOG
icd2061_log("ICD2061 locked\n");
icd2061_log("ICD2061 locked\n");
#endif
}
}
} else if (nc) {
icd2061->data |= (nd << icd2061->bit_count);
icd2061->bit_count++;
}
}
} else if (nc) {
icd2061->data |= (nd << icd2061->bit_count);
icd2061->bit_count++;
if (icd2061->bit_count == 26) {
icd2061_log("26 bits received, data = %08X\n", icd2061->data);
if (icd2061->bit_count == 26) {
icd2061_log("26 bits received, data = %08X\n", icd2061->data);
a = ((icd2061->data >> 22) & 0x07); /* A */
icd2061_log("A = %01X\n", a);
a = ((icd2061->data >> 22) & 0x07); /* A */
icd2061_log("A = %01X\n", a);
if (a < 3) {
pa = ((icd2061->data >> 11) & 0x7f); /* P' (ICD2061) / N' (ICS9161) */
m = ((icd2061->data >> 8) & 0x07); /* M (ICD2061) / R (ICS9161) */
qa = ((icd2061->data >> 1) & 0x7f); /* Q' (ICD2061) / M' (ICS9161) */
if (a < 3) {
pa = ((icd2061->data >> 11) & 0x7f); /* P' (ICD2061) / N' (ICS9161) */
m = ((icd2061->data >> 8) & 0x07); /* M (ICD2061) / R (ICS9161) */
qa = ((icd2061->data >> 1) & 0x7f); /* Q' (ICD2061) / M' (ICS9161) */
p_ = pa + 3; /* P (ICD2061) / N (ICS9161) */
m = 1 << m;
q = qa + 2; /* Q (ICD2061) / M (ICS9161) */
ps = (icd2061->ctrl & (1 << a)) ? 4 : 2; /* Prescale */
p_ = pa + 3; /* P (ICD2061) / N (ICS9161) */
m = 1 << m;
q = qa + 2; /* Q (ICD2061) / M (ICS9161) */
ps = (icd2061->ctrl & (1 << a)) ? 4 : 2; /* Prescale */
icd2061->freq[a] = ((float)(p_ * ps) / (float)(q * m)) * 14318184.0f;
icd2061->freq[a] = ((float) (p_ * ps) / (float) (q * m)) * 14318184.0f;
icd2061_log("P = %02X, M = %01X, Q = %02X, freq[%i] = %f\n", p_, m, q, a, icd2061->freq[a]);
} else if (a == 6) {
icd2061->ctrl = ((icd2061->data >> 13) & 0xff);
icd2061_log("ctrl = %02X\n", icd2061->ctrl);
}
icd2061->count = icd2061->bit_count = icd2061->data = 0;
icd2061->unlocked = 0;
icd2061_log("P = %02X, M = %01X, Q = %02X, freq[%i] = %f\n", p_, m, q, a, icd2061->freq[a]);
} else if (a == 6) {
icd2061->ctrl = ((icd2061->data >> 13) & 0xff);
icd2061_log("ctrl = %02X\n", icd2061->ctrl);
}
icd2061->count = icd2061->bit_count = icd2061->data = 0;
icd2061->unlocked = 0;
#ifdef ENABLE_ICD2061_LOG
icd2061_log("ICD2061 locked\n");
icd2061_log("ICD2061 locked\n");
#endif
}
}
}
}
}
}
float
icd2061_getclock(int clock, void *p)
{
icd2061_t *icd2061 = (icd2061_t *) p;
if (clock > 2)
clock = 2;
clock = 2;
return icd2061->freq[clock];
}
static void *
icd2061_init(const device_t *info)
{
@@ -155,40 +148,39 @@ icd2061_init(const device_t *info)
return icd2061;
}
static void
icd2061_close(void *priv)
{
icd2061_t *icd2061 = (icd2061_t *) priv;
if (icd2061)
free(icd2061);
free(icd2061);
}
const device_t icd2061_device = {
.name = "ICD2061 Clock Generator",
.name = "ICD2061 Clock Generator",
.internal_name = "icd2061",
.flags = 0,
.local = 0,
.init = icd2061_init,
.close = icd2061_close,
.reset = NULL,
.flags = 0,
.local = 0,
.init = icd2061_init,
.close = icd2061_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
const device_t ics9161_device = {
.name = "ICS9161 Clock Generator",
.name = "ICS9161 Clock Generator",
.internal_name = "ics9161",
.flags = 0,
.local = 0,
.init = icd2061_init,
.close = icd2061_close,
.reset = NULL,
.flags = 0,
.local = 0,
.init = icd2061_init,
.close = icd2061_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};

View File

@@ -24,45 +24,39 @@
#include <86box/86box.h>
#include <86box/device.h>
typedef struct ics2494_t
{
typedef struct ics2494_t {
float freq[16];
} ics2494_t;
#ifdef ENABLE_ics2494_LOG
int ics2494_do_log = ENABLE_ics2494_LOG;
static void
ics2494_log(const char *fmt, ...)
{
va_list ap;
if (ics2494_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define ics2494_log(fmt, ...)
# define ics2494_log(fmt, ...)
#endif
float
ics2494_getclock(int clock, void *p)
{
ics2494_t *ics2494 = (ics2494_t *) p;
if (clock > 16)
clock = 16;
clock = 16;
return ics2494->freq[clock];
}
static void *
ics2494_init(const device_t *info)
{
@@ -70,50 +64,49 @@ ics2494_init(const device_t *info)
memset(ics2494, 0, sizeof(ics2494_t));
switch (info->local) {
case 305:
/* ICS2494A(N)-205 for S3 86C924 */
ics2494->freq[0x0] = 25175000.0;
ics2494->freq[0x1] = 28322000.0;
ics2494->freq[0x2] = 40000000.0;
ics2494->freq[0x3] = 0.0;
ics2494->freq[0x4] = 50000000.0;
ics2494->freq[0x5] = 77000000.0;
ics2494->freq[0x6] = 36000000.0;
ics2494->freq[0x7] = 44889000.0;
ics2494->freq[0x8] = 130000000.0;
ics2494->freq[0x9] = 120000000.0;
ics2494->freq[0xa] = 80000000.0;
ics2494->freq[0xb] = 31500000.0;
ics2494->freq[0xc] = 110000000.0;
ics2494->freq[0xd] = 65000000.0;
ics2494->freq[0xe] = 75000000.0;
ics2494->freq[0xf] = 94500000.0;
break;
case 305:
/* ICS2494A(N)-205 for S3 86C924 */
ics2494->freq[0x0] = 25175000.0;
ics2494->freq[0x1] = 28322000.0;
ics2494->freq[0x2] = 40000000.0;
ics2494->freq[0x3] = 0.0;
ics2494->freq[0x4] = 50000000.0;
ics2494->freq[0x5] = 77000000.0;
ics2494->freq[0x6] = 36000000.0;
ics2494->freq[0x7] = 44889000.0;
ics2494->freq[0x8] = 130000000.0;
ics2494->freq[0x9] = 120000000.0;
ics2494->freq[0xa] = 80000000.0;
ics2494->freq[0xb] = 31500000.0;
ics2494->freq[0xc] = 110000000.0;
ics2494->freq[0xd] = 65000000.0;
ics2494->freq[0xe] = 75000000.0;
ics2494->freq[0xf] = 94500000.0;
break;
}
return ics2494;
}
static void
ics2494_close(void *priv)
{
ics2494_t *ics2494 = (ics2494_t *) priv;
if (ics2494)
free(ics2494);
free(ics2494);
}
const device_t ics2494an_305_device = {
.name = "ICS2494AN-305 Clock Generator",
.name = "ICS2494AN-305 Clock Generator",
.internal_name = "ics2494an_305",
.flags = 0,
.local = 305,
.init = ics2494_init,
.close = ics2494_close,
.reset = NULL,
.flags = 0,
.local = 305,
.init = ics2494_init,
.close = ics2494_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};

View File

@@ -24,9 +24,7 @@
#include <86box/86box.h>
#include <86box/device.h>
typedef struct ics2595_t
{
typedef struct ics2595_t {
int oldfs3, oldfs2;
int dat;
int pos, state;
@@ -35,57 +33,52 @@ typedef struct ics2595_t
double output_clock;
} ics2595_t;
enum
{
ICS2595_IDLE = 0,
ICS2595_WRITE,
ICS2595_READ
enum {
ICS2595_IDLE = 0,
ICS2595_WRITE,
ICS2595_READ
};
static int ics2595_div[4] = {8, 4, 2, 1};
static int ics2595_div[4] = { 8, 4, 2, 1 };
void
ics2595_write(void *p, int strobe, int dat)
{
ics2595_t *ics2595 = (ics2595_t *) p;
int d, n;
int l;
int d, n;
int l;
if (strobe) {
if ((dat & 8) && !ics2595->oldfs3) { /*Data clock*/
switch (ics2595->state) {
case ICS2595_IDLE:
ics2595->state = (dat & 4) ? ICS2595_WRITE : ICS2595_IDLE;
ics2595->pos = 0;
break;
case ICS2595_WRITE:
ics2595->dat = (ics2595->dat >> 1);
if (dat & 4)
ics2595->dat |= (1 << 19);
ics2595->pos++;
if (ics2595->pos == 20) {
l = (ics2595->dat >> 2) & 0xf;
n = ((ics2595->dat >> 7) & 255) + 257;
d = ics2595_div[(ics2595->dat >> 16) & 3];
if ((dat & 8) && !ics2595->oldfs3) { /*Data clock*/
switch (ics2595->state) {
case ICS2595_IDLE:
ics2595->state = (dat & 4) ? ICS2595_WRITE : ICS2595_IDLE;
ics2595->pos = 0;
break;
case ICS2595_WRITE:
ics2595->dat = (ics2595->dat >> 1);
if (dat & 4)
ics2595->dat |= (1 << 19);
ics2595->pos++;
if (ics2595->pos == 20) {
l = (ics2595->dat >> 2) & 0xf;
n = ((ics2595->dat >> 7) & 255) + 257;
d = ics2595_div[(ics2595->dat >> 16) & 3];
ics2595->clocks[l] = (14318181.8 * ((double)n / 46.0)) / (double)d;
ics2595->state = ICS2595_IDLE;
}
break;
}
}
ics2595->clocks[l] = (14318181.8 * ((double) n / 46.0)) / (double) d;
ics2595->state = ICS2595_IDLE;
}
break;
}
}
ics2595->oldfs2 = dat & 4;
ics2595->oldfs3 = dat & 8;
ics2595->oldfs2 = dat & 4;
ics2595->oldfs3 = dat & 8;
}
ics2595->output_clock = ics2595->clocks[dat];
}
static void *
ics2595_init(const device_t *info)
{
@@ -95,17 +88,15 @@ ics2595_init(const device_t *info)
return ics2595;
}
static void
ics2595_close(void *priv)
{
ics2595_t *ics2595 = (ics2595_t *) priv;
if (ics2595)
free(ics2595);
free(ics2595);
}
double
ics2595_getclock(void *p)
{
@@ -114,7 +105,6 @@ ics2595_getclock(void *p)
return ics2595->output_clock;
}
void
ics2595_setclock(void *p, double clock)
{
@@ -124,15 +114,15 @@ ics2595_setclock(void *p, double clock)
}
const device_t ics2595_device = {
.name = "ICS2595 clock chip",
.name = "ICS2595 clock chip",
.internal_name = "ics2595",
.flags = 0,
.local = 0,
.init = ics2595_init,
.close = ics2595_close,
.reset = NULL,
.flags = 0,
.local = 0,
.init = ics2595_init,
.close = ics2595_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -34,305 +34,310 @@
static int mdacols[256][2][2];
static video_timings_t timing_mda = {VIDEO_ISA, 8, 16, 32, 8, 16, 32};
static video_timings_t timing_mda = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 };
void mda_recalctimings(mda_t *mda);
void mda_out(uint16_t addr, uint8_t val, void *p)
void
mda_out(uint16_t addr, uint8_t val, void *p)
{
mda_t *mda = (mda_t *)p;
switch (addr)
{
case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6:
mda->crtcreg = val & 31;
return;
case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7:
mda->crtc[mda->crtcreg] = val;
if (mda->crtc[10] == 6 && mda->crtc[11] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/
{
mda->crtc[10] = 0xb;
mda->crtc[11] = 0xc;
mda_t *mda = (mda_t *) p;
switch (addr) {
case 0x3b0:
case 0x3b2:
case 0x3b4:
case 0x3b6:
mda->crtcreg = val & 31;
return;
case 0x3b1:
case 0x3b3:
case 0x3b5:
case 0x3b7:
mda->crtc[mda->crtcreg] = val;
if (mda->crtc[10] == 6 && mda->crtc[11] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/
{
mda->crtc[10] = 0xb;
mda->crtc[11] = 0xc;
}
mda_recalctimings(mda);
return;
case 0x3b8:
mda->ctrl = val;
return;
}
}
uint8_t
mda_in(uint16_t addr, void *p)
{
mda_t *mda = (mda_t *) p;
switch (addr) {
case 0x3b0:
case 0x3b2:
case 0x3b4:
case 0x3b6:
return mda->crtcreg;
case 0x3b1:
case 0x3b3:
case 0x3b5:
case 0x3b7:
return mda->crtc[mda->crtcreg];
case 0x3ba:
return mda->stat | 0xF0;
}
return 0xff;
}
void
mda_write(uint32_t addr, uint8_t val, void *p)
{
mda_t *mda = (mda_t *) p;
mda->vram[addr & 0xfff] = val;
}
uint8_t
mda_read(uint32_t addr, void *p)
{
mda_t *mda = (mda_t *) p;
return mda->vram[addr & 0xfff];
}
void
mda_recalctimings(mda_t *mda)
{
double _dispontime, _dispofftime, disptime;
disptime = mda->crtc[0] + 1;
_dispontime = mda->crtc[1];
_dispofftime = disptime - _dispontime;
_dispontime *= MDACONST;
_dispofftime *= MDACONST;
mda->dispontime = (uint64_t) (_dispontime);
mda->dispofftime = (uint64_t) (_dispofftime);
}
void
mda_poll(void *p)
{
mda_t *mda = (mda_t *) p;
uint16_t ca = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff;
int drawcursor;
int x, c;
int oldvc;
uint8_t chr, attr;
int oldsc;
int blink;
VIDEO_MONITOR_PROLOGUE()
if (!mda->linepos) {
timer_advance_u64(&mda->timer, mda->dispofftime);
mda->stat |= 1;
mda->linepos = 1;
oldsc = mda->sc;
if ((mda->crtc[8] & 3) == 3)
mda->sc = (mda->sc << 1) & 7;
if (mda->dispon) {
if (mda->displine < mda->firstline) {
mda->firstline = mda->displine;
video_wait_for_buffer();
}
mda->lastline = mda->displine;
for (x = 0; x < mda->crtc[1]; x++) {
chr = mda->vram[(mda->ma << 1) & 0xfff];
attr = mda->vram[((mda->ma << 1) + 1) & 0xfff];
drawcursor = ((mda->ma == ca) && mda->con && mda->cursoron);
blink = ((mda->blink & 16) && (mda->ctrl & 0x20) && (attr & 0x80) && !drawcursor);
if (mda->sc == 12 && ((attr & 7) == 1)) {
for (c = 0; c < 9; c++)
buffer32->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][1];
} else {
for (c = 0; c < 8; c++)
buffer32->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][(fontdatm[chr][mda->sc] & (1 << (c ^ 7))) ? 1 : 0];
if ((chr & ~0x1f) == 0xc0)
buffer32->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][fontdatm[chr][mda->sc] & 1];
else
buffer32->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][0];
}
mda_recalctimings(mda);
return;
case 0x3b8:
mda->ctrl = val;
return;
mda->ma++;
if (drawcursor) {
for (c = 0; c < 9; c++)
buffer32->line[mda->displine][(x * 9) + c] ^= mdacols[attr][0][1];
}
}
}
}
uint8_t mda_in(uint16_t addr, void *p)
{
mda_t *mda = (mda_t *)p;
switch (addr)
{
case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6:
return mda->crtcreg;
case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7:
return mda->crtc[mda->crtcreg];
case 0x3ba:
return mda->stat | 0xF0;
mda->sc = oldsc;
if (mda->vc == mda->crtc[7] && !mda->sc) {
mda->stat |= 8;
}
return 0xff;
}
void mda_write(uint32_t addr, uint8_t val, void *p)
{
mda_t *mda = (mda_t *)p;
mda->vram[addr & 0xfff] = val;
}
uint8_t mda_read(uint32_t addr, void *p)
{
mda_t *mda = (mda_t *)p;
return mda->vram[addr & 0xfff];
}
void mda_recalctimings(mda_t *mda)
{
double _dispontime, _dispofftime, disptime;
disptime = mda->crtc[0] + 1;
_dispontime = mda->crtc[1];
_dispofftime = disptime - _dispontime;
_dispontime *= MDACONST;
_dispofftime *= MDACONST;
mda->dispontime = (uint64_t)(_dispontime);
mda->dispofftime = (uint64_t)(_dispofftime);
}
void mda_poll(void *p)
{
mda_t *mda = (mda_t *)p;
uint16_t ca = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff;
int drawcursor;
int x, c;
int oldvc;
uint8_t chr, attr;
int oldsc;
int blink;
VIDEO_MONITOR_PROLOGUE()
if (!mda->linepos)
{
timer_advance_u64(&mda->timer, mda->dispofftime);
mda->stat |= 1;
mda->linepos = 1;
oldsc = mda->sc;
if ((mda->crtc[8] & 3) == 3)
mda->sc = (mda->sc << 1) & 7;
if (mda->dispon)
{
if (mda->displine < mda->firstline)
{
mda->firstline = mda->displine;
video_wait_for_buffer();
}
mda->lastline = mda->displine;
for (x = 0; x < mda->crtc[1]; x++)
{
chr = mda->vram[(mda->ma << 1) & 0xfff];
attr = mda->vram[((mda->ma << 1) + 1) & 0xfff];
drawcursor = ((mda->ma == ca) && mda->con && mda->cursoron);
blink = ((mda->blink & 16) && (mda->ctrl & 0x20) && (attr & 0x80) && !drawcursor);
if (mda->sc == 12 && ((attr & 7) == 1))
{
for (c = 0; c < 9; c++)
buffer32->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][1];
}
else
{
for (c = 0; c < 8; c++)
buffer32->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][(fontdatm[chr][mda->sc] & (1 << (c ^ 7))) ? 1 : 0];
if ((chr & ~0x1f) == 0xc0) buffer32->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][fontdatm[chr][mda->sc] & 1];
else buffer32->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][0];
}
mda->ma++;
if (drawcursor)
{
for (c = 0; c < 9; c++)
buffer32->line[mda->displine][(x * 9) + c] ^= mdacols[attr][0][1];
}
}
}
mda->sc = oldsc;
if (mda->vc == mda->crtc[7] && !mda->sc)
{
mda->stat |= 8;
}
mda->displine++;
if (mda->displine >= 500)
mda->displine=0;
mda->displine++;
if (mda->displine >= 500)
mda->displine = 0;
} else {
timer_advance_u64(&mda->timer, mda->dispontime);
if (mda->dispon)
mda->stat &= ~1;
mda->linepos = 0;
if (mda->vsynctime) {
mda->vsynctime--;
if (!mda->vsynctime) {
mda->stat &= ~8;
}
}
else
{
timer_advance_u64(&mda->timer, mda->dispontime);
if (mda->dispon) mda->stat&=~1;
mda->linepos=0;
if (mda->vsynctime)
{
mda->vsynctime--;
if (!mda->vsynctime)
{
mda->stat&=~8;
}
}
if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1)))
{
mda->con = 0;
mda->coff = 1;
}
if (mda->vadj)
{
mda->sc++;
mda->sc &= 31;
mda->ma = mda->maback;
mda->vadj--;
if (!mda->vadj)
{
mda->dispon = 1;
mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff;
mda->sc = 0;
}
}
else if (mda->sc == mda->crtc[9] || ((mda->crtc[8] & 3) == 3 && mda->sc == (mda->crtc[9] >> 1)))
{
mda->maback = mda->ma;
mda->sc = 0;
oldvc = mda->vc;
mda->vc++;
mda->vc &= 127;
if (mda->vc == mda->crtc[6])
mda->dispon=0;
if (oldvc == mda->crtc[4])
{
mda->vc = 0;
mda->vadj = mda->crtc[5];
if (!mda->vadj) mda->dispon = 1;
if (!mda->vadj) mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff;
if ((mda->crtc[10] & 0x60) == 0x20) mda->cursoron = 0;
else mda->cursoron = mda->blink & 16;
}
if (mda->vc == mda->crtc[7])
{
mda->dispon = 0;
mda->displine = 0;
mda->vsynctime = 16;
if (mda->crtc[7])
{
x = mda->crtc[1] * 9;
mda->lastline++;
if ((x != xsize) || ((mda->lastline - mda->firstline) != ysize) || video_force_resize_get())
{
xsize = x;
ysize = mda->lastline - mda->firstline;
if (xsize < 64) xsize = 656;
if (ysize < 32) ysize = 200;
set_screen_size(xsize, ysize);
if (video_force_resize_get())
video_force_resize_set(0);
}
video_blit_memtoscreen_8(0, mda->firstline, xsize, ysize);
frames++;
video_res_x = mda->crtc[1];
video_res_y = mda->crtc[6];
video_bpp = 0;
}
mda->firstline = 1000;
mda->lastline = 0;
mda->blink++;
}
}
if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1))) {
mda->con = 0;
mda->coff = 1;
}
if (mda->vadj) {
mda->sc++;
mda->sc &= 31;
mda->ma = mda->maback;
mda->vadj--;
if (!mda->vadj) {
mda->dispon = 1;
mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff;
mda->sc = 0;
}
} else if (mda->sc == mda->crtc[9] || ((mda->crtc[8] & 3) == 3 && mda->sc == (mda->crtc[9] >> 1))) {
mda->maback = mda->ma;
mda->sc = 0;
oldvc = mda->vc;
mda->vc++;
mda->vc &= 127;
if (mda->vc == mda->crtc[6])
mda->dispon = 0;
if (oldvc == mda->crtc[4]) {
mda->vc = 0;
mda->vadj = mda->crtc[5];
if (!mda->vadj)
mda->dispon = 1;
if (!mda->vadj)
mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff;
if ((mda->crtc[10] & 0x60) == 0x20)
mda->cursoron = 0;
else
{
mda->sc++;
mda->sc &= 31;
mda->ma = mda->maback;
}
if ((mda->sc == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[10] & 31) >> 1))))
{
mda->con = 1;
mda->cursoron = mda->blink & 16;
}
if (mda->vc == mda->crtc[7]) {
mda->dispon = 0;
mda->displine = 0;
mda->vsynctime = 16;
if (mda->crtc[7]) {
x = mda->crtc[1] * 9;
mda->lastline++;
if ((x != xsize) || ((mda->lastline - mda->firstline) != ysize) || video_force_resize_get()) {
xsize = x;
ysize = mda->lastline - mda->firstline;
if (xsize < 64)
xsize = 656;
if (ysize < 32)
ysize = 200;
set_screen_size(xsize, ysize);
if (video_force_resize_get())
video_force_resize_set(0);
}
video_blit_memtoscreen_8(0, mda->firstline, xsize, ysize);
frames++;
video_res_x = mda->crtc[1];
video_res_y = mda->crtc[6];
video_bpp = 0;
}
mda->firstline = 1000;
mda->lastline = 0;
mda->blink++;
}
} else {
mda->sc++;
mda->sc &= 31;
mda->ma = mda->maback;
}
VIDEO_MONITOR_EPILOGUE();
}
void mda_init(mda_t *mda)
{
int c;
for (c = 0; c < 256; c++)
{
mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16;
if (c & 8) mdacols[c][0][1] = 15 + 16;
else mdacols[c][0][1] = 7 + 16;
if ((mda->sc == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[10] & 31) >> 1)))) {
mda->con = 1;
}
mdacols[0x70][0][1] = 16;
mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15;
mdacols[0xF0][0][1] = 16;
mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15;
mdacols[0x78][0][1] = 16 + 7;
mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15;
mdacols[0xF8][0][1] = 16 + 7;
mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15;
mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16;
mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16;
mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16;
mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16;
overscan_x = overscan_y = 0;
mda->monitor_index = monitor_index_global;
cga_palette = device_get_config_int("rgb_type") << 1;
if (cga_palette > 6)
{
cga_palette = 0;
}
cgapal_rebuild();
timer_add(&mda->timer, mda_poll, mda, 1);
}
VIDEO_MONITOR_EPILOGUE();
}
void *mda_standalone_init(const device_t *info)
void
mda_init(mda_t *mda)
{
mda_t *mda = malloc(sizeof(mda_t));
memset(mda, 0, sizeof(mda_t));
video_inform(VIDEO_FLAG_TYPE_MDA, &timing_mda);
int c;
mda->vram = malloc(0x1000);
for (c = 0; c < 256; c++) {
mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16;
if (c & 8)
mdacols[c][0][1] = 15 + 16;
else
mdacols[c][0][1] = 7 + 16;
}
mdacols[0x70][0][1] = 16;
mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15;
mdacols[0xF0][0][1] = 16;
mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15;
mdacols[0x78][0][1] = 16 + 7;
mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15;
mdacols[0xF8][0][1] = 16 + 7;
mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15;
mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16;
mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16;
mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16;
mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16;
mem_mapping_add(&mda->mapping, 0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, mda);
io_sethandler(0x03b0, 0x0010, mda_in, NULL, NULL, mda_out, NULL, NULL, mda);
overscan_x = overscan_y = 0;
mda->monitor_index = monitor_index_global;
mda_init(mda);
cga_palette = device_get_config_int("rgb_type") << 1;
if (cga_palette > 6) {
cga_palette = 0;
}
cgapal_rebuild();
lpt3_init(0x3BC);
return mda;
timer_add(&mda->timer, mda_poll, mda, 1);
}
void mda_setcol(int chr, int blink, int fg, uint8_t cga_ink)
void *
mda_standalone_init(const device_t *info)
{
mdacols[chr][blink][fg] = 16 + cga_ink;
mda_t *mda = malloc(sizeof(mda_t));
memset(mda, 0, sizeof(mda_t));
video_inform(VIDEO_FLAG_TYPE_MDA, &timing_mda);
mda->vram = malloc(0x1000);
mem_mapping_add(&mda->mapping, 0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, mda);
io_sethandler(0x03b0, 0x0010, mda_in, NULL, NULL, mda_out, NULL, NULL, mda);
mda_init(mda);
lpt3_init(0x3BC);
return mda;
}
void mda_close(void *p)
void
mda_setcol(int chr, int blink, int fg, uint8_t cga_ink)
{
mda_t *mda = (mda_t *)p;
free(mda->vram);
free(mda);
mdacols[chr][blink][fg] = 16 + cga_ink;
}
void mda_speed_changed(void *p)
void
mda_close(void *p)
{
mda_t *mda = (mda_t *)p;
mda_t *mda = (mda_t *) p;
mda_recalctimings(mda);
free(mda->vram);
free(mda);
}
void
mda_speed_changed(void *p)
{
mda_t *mda = (mda_t *) p;
mda_recalctimings(mda);
}
static const device_config_t mda_config[] = {
// clang-format off
// clang-format off
{
.name = "rgb_type",
.description = "Display type",
@@ -367,15 +372,15 @@ static const device_config_t mda_config[] = {
};
const device_t mda_device = {
.name = "MDA",
.name = "MDA",
.internal_name = "mda",
.flags = DEVICE_ISA,
.local = 0,
.init = mda_standalone_init,
.close = mda_close,
.reset = NULL,
.flags = DEVICE_ISA,
.local = 0,
.init = mda_standalone_init,
.close = mda_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = mda_speed_changed,
.force_redraw = NULL,
.config = mda_config
.force_redraw = NULL,
.config = mda_config
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -30,19 +30,18 @@
#include <86box/vid_svga.h>
#include <86box/vid_svga_render.h>
#define BIOS_037C_PATH "roms/video/oti/bios.bin"
#define BIOS_067_AMA932J_PATH "roms/machines/ama932j/OTI067.BIN"
#define BIOS_067_M300_08_PATH "roms/machines/m30008/EVC_BIOS.ROM"
#define BIOS_067_M300_15_PATH "roms/machines/m30015/EVC_BIOS.ROM"
#define BIOS_077_PATH "roms/video/oti/oti077.vbi"
#define BIOS_037C_PATH "roms/video/oti/bios.bin"
#define BIOS_067_AMA932J_PATH "roms/machines/ama932j/OTI067.BIN"
#define BIOS_067_M300_08_PATH "roms/machines/m30008/EVC_BIOS.ROM"
#define BIOS_067_M300_15_PATH "roms/machines/m30015/EVC_BIOS.ROM"
#define BIOS_077_PATH "roms/video/oti/oti077.vbi"
enum {
OTI_037C,
OTI_067 = 2,
OTI_067_AMA932J,
OTI_067_M300 = 4,
OTI_077 = 5
OTI_077 = 5
};
typedef struct {
@@ -50,7 +49,7 @@ typedef struct {
rom_t bios_rom;
int index;
int index;
uint8_t regs[32];
uint8_t chip_id;
@@ -62,396 +61,400 @@ typedef struct {
uint32_t vram_mask;
} oti_t;
static video_timings_t timing_oti = {VIDEO_ISA, 6, 8,16, 6, 8,16};
static video_timings_t timing_oti = { .type = VIDEO_ISA, .write_b = 6, .write_w = 8, .write_l = 16, .read_b = 6, .read_w = 8, .read_l = 16 };
static void
oti_out(uint16_t addr, uint8_t val, void *p)
{
oti_t *oti = (oti_t *)p;
oti_t *oti = (oti_t *) p;
svga_t *svga = &oti->svga;
uint8_t old;
uint8_t idx, enable;
if (!oti->chip_id && !(oti->enable_register & 1) && (addr != 0x3C3))
return;
return;
if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) &&
!(svga->miscout & 1)) addr ^= 0x60;
if ((((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1))
addr ^= 0x60;
switch (addr) {
case 0x3C3:
if (!oti->chip_id) {
oti->enable_register = val & 1;
return;
} else
break;
break;
case 0x3C3:
if (!oti->chip_id) {
oti->enable_register = val & 1;
return;
} else
break;
break;
case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9:
if (oti->chip_id == OTI_077)
sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga);
else
svga_out(addr, val, svga);
return;
case 0x3c6:
case 0x3c7:
case 0x3c8:
case 0x3c9:
if (oti->chip_id == OTI_077)
sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga);
else
svga_out(addr, val, svga);
return;
case 0x3D4:
if (oti->chip_id)
svga->crtcreg = val & 0x3f;
else
svga->crtcreg = val; /* FIXME: The BIOS wants to set the test bit? */
return;
case 0x3D4:
if (oti->chip_id)
svga->crtcreg = val & 0x3f;
else
svga->crtcreg = val; /* FIXME: The BIOS wants to set the test bit? */
return;
case 0x3D5:
if (oti->chip_id && (svga->crtcreg & 0x20))
return;
idx = svga->crtcreg;
if (!oti->chip_id)
idx &= 0x1f;
if ((idx < 7) && (svga->crtc[0x11] & 0x80))
return;
if ((idx == 7) && (svga->crtc[0x11] & 0x80))
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
old = svga->crtc[idx];
svga->crtc[idx] = val;
if (old != val) {
if ((idx < 0x0e) || (idx > 0x10)) {
if (idx == 0x0c || idx == 0x0d) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
}
}
}
break;
case 0x3D5:
if (oti->chip_id && (svga->crtcreg & 0x20))
return;
idx = svga->crtcreg;
if (!oti->chip_id)
idx &= 0x1f;
if ((idx < 7) && (svga->crtc[0x11] & 0x80))
return;
if ((idx == 7) && (svga->crtc[0x11] & 0x80))
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
old = svga->crtc[idx];
svga->crtc[idx] = val;
if (old != val) {
if ((idx < 0x0e) || (idx > 0x10)) {
if (idx == 0x0c || idx == 0x0d) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
}
}
}
break;
case 0x3DE:
if (oti->chip_id)
oti->index = val & 0x1f;
else
oti->index = val;
return;
case 0x3DE:
if (oti->chip_id)
oti->index = val & 0x1f;
else
oti->index = val;
return;
case 0x3DF:
idx = oti->index;
if (!oti->chip_id)
idx &= 0x1f;
oti->regs[idx] = val;
switch (idx) {
case 0xD:
if (oti->chip_id == OTI_067) {
svga->vram_display_mask = (val & 0x0c) ? oti->vram_mask : 0x3ffff;
if (!(val & 0x80))
svga->vram_display_mask = 0x3ffff;
case 0x3DF:
idx = oti->index;
if (!oti->chip_id)
idx &= 0x1f;
oti->regs[idx] = val;
switch (idx) {
case 0xD:
if (oti->chip_id == OTI_067) {
svga->vram_display_mask = (val & 0x0c) ? oti->vram_mask : 0x3ffff;
if (!(val & 0x80))
svga->vram_display_mask = 0x3ffff;
if ((val & 0x80) && oti->vram_size == 256)
mem_mapping_disable(&svga->mapping);
else
mem_mapping_enable(&svga->mapping);
} else if (oti->chip_id == OTI_077) {
svga->vram_display_mask = (val & 0x0c) ? oti->vram_mask : 0x3ffff;
if ((val & 0x80) && oti->vram_size == 256)
mem_mapping_disable(&svga->mapping);
else
mem_mapping_enable(&svga->mapping);
} else if (oti->chip_id == OTI_077) {
svga->vram_display_mask = (val & 0x0c) ? oti->vram_mask : 0x3ffff;
switch ((val & 0xc0) >> 6) {
case 0x00: /* 256 kB of memory */
default:
enable = (oti->vram_size >= 256);
if (val & 0x0c)
svga->vram_display_mask = MIN(oti->vram_mask, 0x3ffff);
break;
case 0x01: /* 1 MB of memory */
case 0x03:
enable = (oti->vram_size >= 1024);
if (val & 0x0c)
svga->vram_display_mask = MIN(oti->vram_mask, 0xfffff);
break;
case 0x02: /* 512 kB of memory */
enable = (oti->vram_size >= 512);
if (val & 0x0c)
svga->vram_display_mask = MIN(oti->vram_mask, 0x7ffff);
break;
}
switch ((val & 0xc0) >> 6) {
case 0x00: /* 256 kB of memory */
default:
enable = (oti->vram_size >= 256);
if (val & 0x0c)
svga->vram_display_mask = MIN(oti->vram_mask, 0x3ffff);
break;
case 0x01: /* 1 MB of memory */
case 0x03:
enable = (oti->vram_size >= 1024);
if (val & 0x0c)
svga->vram_display_mask = MIN(oti->vram_mask, 0xfffff);
break;
case 0x02: /* 512 kB of memory */
enable = (oti->vram_size >= 512);
if (val & 0x0c)
svga->vram_display_mask = MIN(oti->vram_mask, 0x7ffff);
break;
}
if (enable)
mem_mapping_enable(&svga->mapping);
else
mem_mapping_disable(&svga->mapping);
} else {
if (val & 0x80)
mem_mapping_disable(&svga->mapping);
else
mem_mapping_enable(&svga->mapping);
}
break;
if (enable)
mem_mapping_enable(&svga->mapping);
else
mem_mapping_disable(&svga->mapping);
} else {
if (val & 0x80)
mem_mapping_disable(&svga->mapping);
else
mem_mapping_enable(&svga->mapping);
}
break;
case 0x11:
svga->read_bank = (val & 0xf) * 65536;
svga->write_bank = (val >> 4) * 65536;
break;
}
return;
case 0x11:
svga->read_bank = (val & 0xf) * 65536;
svga->write_bank = (val >> 4) * 65536;
break;
}
return;
}
svga_out(addr, val, svga);
}
static uint8_t
oti_in(uint16_t addr, void *p)
{
oti_t *oti = (oti_t *)p;
oti_t *oti = (oti_t *) p;
svga_t *svga = &oti->svga;
uint8_t idx, temp;
if (!oti->chip_id && !(oti->enable_register & 1) && (addr != 0x3C3))
return 0xff;
return 0xff;
if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) &&
!(svga->miscout & 1)) addr ^= 0x60;
if ((((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1))
addr ^= 0x60;
switch (addr) {
case 0x3C2:
if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x50)
temp = 0;
else
temp = 0x10;
break;
case 0x3C2:
if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x50)
temp = 0;
else
temp = 0x10;
break;
case 0x3C3:
if (oti->chip_id)
temp = svga_in(addr, svga);
else
temp = oti->enable_register;
break;
case 0x3C3:
if (oti->chip_id)
temp = svga_in(addr, svga);
else
temp = oti->enable_register;
break;
case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9:
if (oti->chip_id == OTI_077)
return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga);
return svga_in(addr, svga);
case 0x3c6:
case 0x3c7:
case 0x3c8:
case 0x3c9:
if (oti->chip_id == OTI_077)
return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga);
return svga_in(addr, svga);
case 0x3CF:
return svga->gdcreg[svga->gdcaddr & 0xf];
case 0x3CF:
return svga->gdcreg[svga->gdcaddr & 0xf];
case 0x3D4:
temp = svga->crtcreg;
break;
case 0x3D4:
temp = svga->crtcreg;
break;
case 0x3D5:
if (oti->chip_id) {
if (svga->crtcreg & 0x20)
temp = 0xff;
else
temp = svga->crtc[svga->crtcreg];
} else
temp = svga->crtc[svga->crtcreg & 0x1f];
break;
case 0x3D5:
if (oti->chip_id) {
if (svga->crtcreg & 0x20)
temp = 0xff;
else
temp = svga->crtc[svga->crtcreg];
} else
temp = svga->crtc[svga->crtcreg & 0x1f];
break;
case 0x3DA:
if (oti->chip_id) {
temp = svga_in(addr, svga);
break;
}
case 0x3DA:
if (oti->chip_id) {
temp = svga_in(addr, svga);
break;
}
svga->attrff = 0;
/*The OTI-037C BIOS waits for bits 0 and 3 in 0x3da to go low, then reads 0x3da again
and expects the diagnostic bits to equal the current border colour. As I understand
it, the 0x3da active enable status does not include the border time, so this may be
an area where OTI-037C is not entirely VGA compatible.*/
svga->cgastat &= ~0x30;
/* copy color diagnostic info from the overscan color register */
switch (svga->attrregs[0x12] & 0x30)
{
case 0x00: /* P0 and P2 */
if (svga->attrregs[0x11] & 0x01)
svga->cgastat |= 0x10;
if (svga->attrregs[0x11] & 0x04)
svga->cgastat |= 0x20;
break;
case 0x10: /* P4 and P5 */
if (svga->attrregs[0x11] & 0x10)
svga->cgastat |= 0x10;
if (svga->attrregs[0x11] & 0x20)
svga->cgastat |= 0x20;
break;
case 0x20: /* P1 and P3 */
if (svga->attrregs[0x11] & 0x02)
svga->cgastat |= 0x10;
if (svga->attrregs[0x11] & 0x08)
svga->cgastat |= 0x20;
break;
case 0x30: /* P6 and P7 */
if (svga->attrregs[0x11] & 0x40)
svga->cgastat |= 0x10;
if (svga->attrregs[0x11] & 0x80)
svga->cgastat |= 0x20;
break;
}
temp = svga->cgastat;
break;
svga->attrff = 0;
/*The OTI-037C BIOS waits for bits 0 and 3 in 0x3da to go low, then reads 0x3da again
and expects the diagnostic bits to equal the current border colour. As I understand
it, the 0x3da active enable status does not include the border time, so this may be
an area where OTI-037C is not entirely VGA compatible.*/
svga->cgastat &= ~0x30;
/* copy color diagnostic info from the overscan color register */
switch (svga->attrregs[0x12] & 0x30) {
case 0x00: /* P0 and P2 */
if (svga->attrregs[0x11] & 0x01)
svga->cgastat |= 0x10;
if (svga->attrregs[0x11] & 0x04)
svga->cgastat |= 0x20;
break;
case 0x10: /* P4 and P5 */
if (svga->attrregs[0x11] & 0x10)
svga->cgastat |= 0x10;
if (svga->attrregs[0x11] & 0x20)
svga->cgastat |= 0x20;
break;
case 0x20: /* P1 and P3 */
if (svga->attrregs[0x11] & 0x02)
svga->cgastat |= 0x10;
if (svga->attrregs[0x11] & 0x08)
svga->cgastat |= 0x20;
break;
case 0x30: /* P6 and P7 */
if (svga->attrregs[0x11] & 0x40)
svga->cgastat |= 0x10;
if (svga->attrregs[0x11] & 0x80)
svga->cgastat |= 0x20;
break;
}
temp = svga->cgastat;
break;
case 0x3DE:
temp = oti->index;
if (oti->chip_id)
temp |= (oti->chip_id << 5);
break;
case 0x3DE:
temp = oti->index;
if (oti->chip_id)
temp |= (oti->chip_id << 5);
break;
case 0x3DF:
idx = oti->index;
if (!oti->chip_id)
idx &= 0x1f;
if (idx == 0x10)
temp = oti->dipswitch_val;
else
temp = oti->regs[idx];
break;
case 0x3DF:
idx = oti->index;
if (!oti->chip_id)
idx &= 0x1f;
if (idx == 0x10)
temp = oti->dipswitch_val;
else
temp = oti->regs[idx];
break;
default:
temp = svga_in(addr, svga);
break;
default:
temp = svga_in(addr, svga);
break;
}
return(temp);
return (temp);
}
static void
oti_pos_out(uint16_t addr, uint8_t val, void *p)
{
oti_t *oti = (oti_t *)p;
oti_t *oti = (oti_t *) p;
if ((val ^ oti->pos) & 8) {
if (val & 8)
io_sethandler(0x03c0, 32, oti_in, NULL, NULL,
oti_out, NULL, NULL, oti);
else
io_removehandler(0x03c0, 32, oti_in, NULL, NULL,
oti_out, NULL, NULL, oti);
if (val & 8)
io_sethandler(0x03c0, 32, oti_in, NULL, NULL,
oti_out, NULL, NULL, oti);
else
io_removehandler(0x03c0, 32, oti_in, NULL, NULL,
oti_out, NULL, NULL, oti);
}
oti->pos = val;
}
static uint8_t
oti_pos_in(uint16_t addr, void *p)
{
oti_t *oti = (oti_t *)p;
oti_t *oti = (oti_t *) p;
return(oti->pos);
return (oti->pos);
}
static float
oti_getclock(int clock)
{
float ret = 0.0;
switch (clock) {
case 0:
default:
ret = 25175000.0;
break;
case 1:
ret = 28322000.0;
break;
case 4:
ret = 14318000.0;
break;
case 5:
ret = 16257000.0;
break;
case 7:
ret = 35500000.0;
break;
case 0:
default:
ret = 25175000.0;
break;
case 1:
ret = 28322000.0;
break;
case 4:
ret = 14318000.0;
break;
case 5:
ret = 16257000.0;
break;
case 7:
ret = 35500000.0;
break;
}
return ret;
}
static void
oti_recalctimings(svga_t *svga)
{
oti_t *oti = (oti_t *)svga->p;
int clk_sel = ((svga->miscout >> 2) & 3) | ((oti->regs[0x0d] & 0x20) >> 3);
oti_t *oti = (oti_t *) svga->p;
int clk_sel = ((svga->miscout >> 2) & 3) | ((oti->regs[0x0d] & 0x20) >> 3);
svga->clock = (cpuclock * (double)(1ull << 32)) / oti_getclock(clk_sel);
svga->clock = (cpuclock * (double) (1ull << 32)) / oti_getclock(clk_sel);
if (oti->chip_id > 0) {
if (oti->regs[0x14] & 0x08) svga->ma_latch |= 0x10000;
if (oti->regs[0x16] & 0x08) svga->ma_latch |= 0x20000;
if (oti->regs[0x14] & 0x08)
svga->ma_latch |= 0x10000;
if (oti->regs[0x16] & 0x08)
svga->ma_latch |= 0x20000;
if (oti->regs[0x14] & 0x01) svga->vtotal += 0x400;
if (oti->regs[0x14] & 0x02) svga->dispend += 0x400;
if (oti->regs[0x14] & 0x04) svga->vsyncstart += 0x400;
if (oti->regs[0x14] & 0x01)
svga->vtotal += 0x400;
if (oti->regs[0x14] & 0x02)
svga->dispend += 0x400;
if (oti->regs[0x14] & 0x04)
svga->vsyncstart += 0x400;
svga->interlace = oti->regs[0x14] & 0x80;
svga->interlace = oti->regs[0x14] & 0x80;
}
if ((oti->regs[0x0d] & 0x0c) && !(oti->regs[0x0d] & 0x10)) svga->rowoffset <<= 1;
if ((oti->regs[0x0d] & 0x0c) && !(oti->regs[0x0d] & 0x10))
svga->rowoffset <<= 1;
if (svga->bpp == 16) {
svga->render = svga_render_16bpp_highres;
svga->hdisp >>= 1;
svga->render = svga_render_16bpp_highres;
svga->hdisp >>= 1;
} else if (svga->bpp == 15) {
svga->render = svga_render_15bpp_highres;
svga->hdisp >>= 1;
svga->render = svga_render_15bpp_highres;
svga->hdisp >>= 1;
}
}
static void *
oti_init(const device_t *info)
{
oti_t *oti = malloc(sizeof(oti_t));
char *romfn = NULL;
oti_t *oti = malloc(sizeof(oti_t));
char *romfn = NULL;
memset(oti, 0x00, sizeof(oti_t));
oti->chip_id = info->local;
oti->dipswitch_val = 0x18;
switch(oti->chip_id) {
case OTI_037C:
romfn = BIOS_037C_PATH;
oti->vram_size = 256;
oti->regs[0] = 0x08; /* FIXME: The BIOS wants to read this at index 0? This index is undocumented. */
/* io_sethandler(0x03c0, 32,
oti_in, NULL, NULL, oti_out, NULL, NULL, oti); */
break;
switch (oti->chip_id) {
case OTI_037C:
romfn = BIOS_037C_PATH;
oti->vram_size = 256;
oti->regs[0] = 0x08; /* FIXME: The BIOS wants to read this at index 0? This index is undocumented. */
/* io_sethandler(0x03c0, 32,
oti_in, NULL, NULL, oti_out, NULL, NULL, oti); */
break;
case OTI_067_AMA932J:
romfn = BIOS_067_AMA932J_PATH;
oti->chip_id = 2;
oti->vram_size = device_get_config_int("memory");
oti->dipswitch_val |= 0x20;
oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */
io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti);
break;
case OTI_067_AMA932J:
romfn = BIOS_067_AMA932J_PATH;
oti->chip_id = 2;
oti->vram_size = device_get_config_int("memory");
oti->dipswitch_val |= 0x20;
oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */
io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti);
break;
case OTI_067_M300:
if (rom_present(BIOS_067_M300_15_PATH))
romfn = BIOS_067_M300_15_PATH;
else
romfn = BIOS_067_M300_08_PATH;
oti->vram_size = device_get_config_int("memory");
oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */
io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti);
break;
case OTI_067_M300:
if (rom_present(BIOS_067_M300_15_PATH))
romfn = BIOS_067_M300_15_PATH;
else
romfn = BIOS_067_M300_08_PATH;
oti->vram_size = device_get_config_int("memory");
oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */
io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti);
break;
case OTI_067:
case OTI_077:
romfn = BIOS_077_PATH;
oti->vram_size = device_get_config_int("memory");
oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */
io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti);
break;
case OTI_067:
case OTI_077:
romfn = BIOS_077_PATH;
oti->vram_size = device_get_config_int("memory");
oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */
io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti);
break;
}
if (romfn != NULL) {
rom_init(&oti->bios_rom, romfn,
0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
rom_init(&oti->bios_rom, romfn,
0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
}
oti->vram_mask = (oti->vram_size << 10) - 1;
@@ -459,78 +462,71 @@ oti_init(const device_t *info)
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_oti);
svga_init(info, &oti->svga, oti, oti->vram_size << 10,
oti_recalctimings, oti_in, oti_out, NULL, NULL);
oti_recalctimings, oti_in, oti_out, NULL, NULL);
if (oti->chip_id == OTI_077)
oti->svga.ramdac = device_add(&sc11487_ramdac_device); /*Actually a 82c487, probably a clone.*/
if (oti->chip_id == OTI_077)
oti->svga.ramdac = device_add(&sc11487_ramdac_device); /*Actually a 82c487, probably a clone.*/
io_sethandler(0x03c0, 32,
oti_in, NULL, NULL, oti_out, NULL, NULL, oti);
oti_in, NULL, NULL, oti_out, NULL, NULL, oti);
oti->svga.miscout = 1;
oti->svga.packed_chain4 = 1;
oti->svga.miscout = 1;
oti->svga.packed_chain4 = 1;
return(oti);
return (oti);
}
static void
oti_close(void *p)
{
oti_t *oti = (oti_t *)p;
oti_t *oti = (oti_t *) p;
svga_close(&oti->svga);
free(oti);
}
static void
oti_speed_changed(void *p)
{
oti_t *oti = (oti_t *)p;
oti_t *oti = (oti_t *) p;
svga_recalctimings(&oti->svga);
}
static void
oti_force_redraw(void *p)
{
oti_t *oti = (oti_t *)p;
oti_t *oti = (oti_t *) p;
oti->svga.fullchange = changeframecount;
}
static int
oti037c_available(void)
{
return(rom_present(BIOS_037C_PATH));
return (rom_present(BIOS_037C_PATH));
}
static int
oti067_ama932j_available(void)
{
return(rom_present(BIOS_067_AMA932J_PATH));
return (rom_present(BIOS_067_AMA932J_PATH));
}
static int
oti067_077_available(void)
{
return(rom_present(BIOS_077_PATH));
return (rom_present(BIOS_077_PATH));
}
static int
oti067_m300_available(void)
{
if (rom_present(BIOS_067_M300_15_PATH))
return(rom_present(BIOS_067_M300_15_PATH));
return (rom_present(BIOS_067_M300_15_PATH));
else
return(rom_present(BIOS_067_M300_08_PATH));
return (rom_present(BIOS_067_M300_08_PATH));
}
// clang-format off
@@ -615,71 +611,71 @@ static const device_config_t oti077_config[] = {
// clang-format on
const device_t oti037c_device = {
.name = "Oak OTI-037C",
.name = "Oak OTI-037C",
.internal_name = "oti037c",
.flags = DEVICE_ISA,
.local = 0,
.init = oti_init,
.close = oti_close,
.reset = NULL,
.flags = DEVICE_ISA,
.local = 0,
.init = oti_init,
.close = oti_close,
.reset = NULL,
{ .available = oti037c_available },
.speed_changed = oti_speed_changed,
.force_redraw = oti_force_redraw,
.config = NULL
.force_redraw = oti_force_redraw,
.config = NULL
};
const device_t oti067_device = {
.name = "Oak OTI-067",
.name = "Oak OTI-067",
.internal_name = "oti067",
.flags = DEVICE_ISA,
.local = 2,
.init = oti_init,
.close = oti_close,
.reset = NULL,
.flags = DEVICE_ISA,
.local = 2,
.init = oti_init,
.close = oti_close,
.reset = NULL,
{ .available = oti067_077_available },
.speed_changed = oti_speed_changed,
.force_redraw = oti_force_redraw,
.config = oti067_config
.force_redraw = oti_force_redraw,
.config = oti067_config
};
const device_t oti067_m300_device = {
.name = "Oak OTI-067 (Olivetti M300-08/15)",
.name = "Oak OTI-067 (Olivetti M300-08/15)",
.internal_name = "oti067_m300",
.flags = DEVICE_ISA,
.local = 4,
.init = oti_init,
.close = oti_close,
.reset = NULL,
.flags = DEVICE_ISA,
.local = 4,
.init = oti_init,
.close = oti_close,
.reset = NULL,
{ .available = oti067_m300_available },
.speed_changed = oti_speed_changed,
.force_redraw = oti_force_redraw,
.config = oti067_config
.force_redraw = oti_force_redraw,
.config = oti067_config
};
const device_t oti067_ama932j_device = {
.name = "Oak OTI-067 (AMA-932J)",
.name = "Oak OTI-067 (AMA-932J)",
.internal_name = "oti067_ama932j",
.flags = DEVICE_ISA,
.local = 3,
.init = oti_init,
.close = oti_close,
.reset = NULL,
.flags = DEVICE_ISA,
.local = 3,
.init = oti_init,
.close = oti_close,
.reset = NULL,
{ .available = oti067_ama932j_available },
.speed_changed = oti_speed_changed,
.force_redraw = oti_force_redraw,
.config = oti067_ama932j_config
.force_redraw = oti_force_redraw,
.config = oti067_ama932j_config
};
const device_t oti077_device = {
.name = "Oak OTI-077",
.name = "Oak OTI-077",
.internal_name = "oti077",
.flags = DEVICE_ISA,
.local = 5,
.init = oti_init,
.close = oti_close,
.reset = NULL,
.flags = DEVICE_ISA,
.local = 5,
.init = oti_init,
.close = oti_close,
.reset = NULL,
{ .available = oti067_077_available },
.speed_changed = oti_speed_changed,
.force_redraw = oti_force_redraw,
.config = oti077_config
.force_redraw = oti_force_redraw,
.config = oti077_config
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -29,86 +29,84 @@
#include <86box/vid_svga.h>
#include <86box/vid_svga_render.h>
#define BIOS_ROM_PATH "roms/video/rtg/realtekrtg3106.BIN"
#define BIOS_ROM_PATH "roms/video/rtg/realtekrtg3106.BIN"
typedef struct {
const char *name;
int type;
const char *name;
int type;
svga_t svga;
svga_t svga;
rom_t bios_rom;
rom_t bios_rom;
uint8_t bank3d6,
bank3d7;
uint8_t bank3d6,
bank3d7;
uint32_t vram_size,
vram_mask;
uint32_t vram_size,
vram_mask;
} rtg_t;
static video_timings_t timing_rtg_isa = { .type = VIDEO_ISA, .write_b = 3, .write_w = 3, .write_l = 6, .read_b = 5, .read_w = 5, .read_l = 10 };
static video_timings_t timing_rtg_isa = {VIDEO_ISA, 3, 3, 6, 5, 5, 10};
static void rtg_recalcbanking(rtg_t *dev)
static void
rtg_recalcbanking(rtg_t *dev)
{
svga_t *svga = &dev->svga;
svga_t *svga = &dev->svga;
svga->write_bank = (dev->bank3d7 & 0x0f) * 65536;
svga->write_bank = (dev->bank3d7 & 0x0f) * 65536;
if (svga->gdcreg[0x0f] & 4)
svga->read_bank = (dev->bank3d6 & 0x0f) * 65536;
else
svga->read_bank = svga->write_bank;
if (svga->gdcreg[0x0f] & 4)
svga->read_bank = (dev->bank3d6 & 0x0f) * 65536;
else
svga->read_bank = svga->write_bank;
}
static uint8_t
rtg_in(uint16_t addr, void *priv)
{
rtg_t *dev = (rtg_t *)priv;
rtg_t *dev = (rtg_t *) priv;
svga_t *svga = &dev->svga;
uint8_t ret = 0;
uint8_t ret = 0;
if (((addr & 0xfff0) == 0x3d0 ||
(addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60;
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
switch (addr) {
case 0x3ce:
return svga->gdcaddr;
case 0x3ce:
return svga->gdcaddr;
case 0x3cf:
if (svga->gdcaddr == 0x0c)
return svga->gdcreg[0x0c] | 4;
else if ((svga->gdcaddr > 8) && (svga->gdcaddr != 0x0c))
return svga->gdcreg[svga->gdcaddr];
break;
case 0x3cf:
if (svga->gdcaddr == 0x0c)
return svga->gdcreg[0x0c] | 4;
else if ((svga->gdcaddr > 8) && (svga->gdcaddr != 0x0c))
return svga->gdcreg[svga->gdcaddr];
break;
case 0x3d4:
return svga->crtcreg;
case 0x3d4:
return svga->crtcreg;
case 0x3d5:
if (!(svga->crtc[0x1e] & 0x80) && (svga->crtcreg > 0x18))
return 0xff;
if (svga->crtcreg == 0x1a)
return dev->type << 6;
if (svga->crtcreg == 0x1e) {
if (dev->vram_size == 1024)
ret = 2;
else if (dev->vram_size == 512)
ret = 1;
else
ret = 0;
return svga->crtc[0x1e] | ret;
}
return svga->crtc[svga->crtcreg];
case 0x3d5:
if (!(svga->crtc[0x1e] & 0x80) && (svga->crtcreg > 0x18))
return 0xff;
if (svga->crtcreg == 0x1a)
return dev->type << 6;
if (svga->crtcreg == 0x1e) {
if (dev->vram_size == 1024)
ret = 2;
else if (dev->vram_size == 512)
ret = 1;
else
ret = 0;
return svga->crtc[0x1e] | ret;
}
return svga->crtc[svga->crtcreg];
case 0x3d6:
return dev->bank3d6;
case 0x3d6:
return dev->bank3d6;
case 0x3d7:
return dev->bank3d7;
}
case 0x3d7:
return dev->bank3d7;
}
return svga_in(addr, svga);
}
@@ -116,81 +114,80 @@ rtg_in(uint16_t addr, void *priv)
static void
rtg_out(uint16_t addr, uint8_t val, void *priv)
{
rtg_t *dev = (rtg_t *)priv;
rtg_t *dev = (rtg_t *) priv;
svga_t *svga = &dev->svga;
uint8_t old;
if (((addr & 0xfff0) == 0x3d0 ||
(addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60;
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
switch (addr) {
case 0x3ce:
svga->gdcaddr = val;
return;
case 0x3ce:
svga->gdcaddr = val;
return;
case 0x3cf:
if (svga->gdcaddr > 8) {
svga->gdcreg[svga->gdcaddr] = val;
case 0x3cf:
if (svga->gdcaddr > 8) {
svga->gdcreg[svga->gdcaddr] = val;
switch (svga->gdcaddr) {
case 0x0b:
case 0x0c:
svga->fullchange = changeframecount;
svga_recalctimings(svga);
break;
switch (svga->gdcaddr) {
case 0x0b:
case 0x0c:
svga->fullchange = changeframecount;
svga_recalctimings(svga);
break;
case 0x0f:
rtg_recalcbanking(dev);
return;
}
}
break;
case 0x0f:
rtg_recalcbanking(dev);
return;
}
}
break;
case 0x3d4:
svga->crtcreg = val & 0x3f;
return;
case 0x3d4:
svga->crtcreg = val & 0x3f;
return;
case 0x3d5:
if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80))
return;
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
old = svga->crtc[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
case 0x3d5:
if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80))
return;
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
old = svga->crtc[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
if (svga->crtc[0x1e] & 0x80) {
switch (svga->crtcreg) {
case 0x19:
svga->vram_display_mask = (val & 0x20) ? dev->vram_mask : 0x3ffff;
svga->fullchange = changeframecount;
svga_recalctimings(svga);
break;
}
}
if (svga->crtc[0x1e] & 0x80) {
switch (svga->crtcreg) {
case 0x19:
svga->vram_display_mask = (val & 0x20) ? dev->vram_mask : 0x3ffff;
svga->fullchange = changeframecount;
svga_recalctimings(svga);
break;
}
}
if (old != val) {
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
{
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
}
}
}
break;
if (old != val) {
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
}
}
}
break;
case 0x3d6:
dev->bank3d6 = val;
rtg_recalcbanking(dev);
return;
case 0x3d6:
dev->bank3d6 = val;
rtg_recalcbanking(dev);
return;
case 0x3d7:
dev->bank3d7 = val;
rtg_recalcbanking(dev);
return;
case 0x3d7:
dev->bank3d7 = val;
rtg_recalcbanking(dev);
return;
}
svga_out(addr, val, svga);
@@ -199,159 +196,156 @@ rtg_out(uint16_t addr, uint8_t val, void *priv)
static void
rtg_recalctimings(svga_t *svga)
{
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
svga->ma_latch |= ((svga->crtc[0x19] & 0x10) << 16) | ((svga->crtc[0x19] & 0x40) << 17);
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
svga->ma_latch |= ((svga->crtc[0x19] & 0x10) << 16) | ((svga->crtc[0x19] & 0x40) << 17);
svga->interlace = (svga->crtc[0x19] & 1);
svga->interlace = (svga->crtc[0x19] & 1);
svga->lowres = svga->attrregs[0x10] & 0x40;
svga->lowres = svga->attrregs[0x10] & 0x40;
/*Clock table not available, currently a guesswork*/
switch (((svga->miscout >> 2) & 3) | ((svga->gdcreg[0x0c] & 0x20) >> 3)) {
case 0:
case 1:
break;
case 2:
svga->clock = (cpuclock * (double)(1ull << 32)) / 36000000.0;
break;
case 3:
svga->clock = (cpuclock * (double)(1ull << 32)) / 65100000.0;
break;
case 4:
svga->clock = (cpuclock * (double)(1ull << 32)) / 44900000.0;
break;
case 5:
svga->clock = (cpuclock * (double)(1ull << 32)) / 50000000.0;
break;
case 6:
svga->clock = (cpuclock * (double)(1ull << 32)) / 80000000.0;
break;
case 7:
svga->clock = (cpuclock * (double)(1ull << 32)) / 75000000.0;
break;
}
/*Clock table not available, currently a guesswork*/
switch (((svga->miscout >> 2) & 3) | ((svga->gdcreg[0x0c] & 0x20) >> 3)) {
case 0:
case 1:
break;
case 2:
svga->clock = (cpuclock * (double) (1ull << 32)) / 36000000.0;
break;
case 3:
svga->clock = (cpuclock * (double) (1ull << 32)) / 65100000.0;
break;
case 4:
svga->clock = (cpuclock * (double) (1ull << 32)) / 44900000.0;
break;
case 5:
svga->clock = (cpuclock * (double) (1ull << 32)) / 50000000.0;
break;
case 6:
svga->clock = (cpuclock * (double) (1ull << 32)) / 80000000.0;
break;
case 7:
svga->clock = (cpuclock * (double) (1ull << 32)) / 75000000.0;
break;
}
switch (svga->gdcreg[0x0c] & 3) {
case 1:
svga->clock /= 1.5;
break;
case 2:
svga->clock /= 2;
break;
case 3:
svga->clock /= 4;
break;
}
switch (svga->gdcreg[0x0c] & 3) {
case 1:
svga->clock /= 1.5;
break;
case 2:
svga->clock /= 2;
break;
case 3:
svga->clock /= 4;
break;
}
if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
switch (svga->gdcreg[5] & 0x60) {
case 0x00:
if (svga->seqregs[1] & 8) /*Low res (320)*/
svga->render = svga_render_4bpp_lowres;
else {
svga->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5);
svga->hdisp++;
svga->hdisp *= 8;
if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
switch (svga->gdcreg[5] & 0x60) {
case 0x00:
if (svga->seqregs[1] & 8) /*Low res (320)*/
svga->render = svga_render_4bpp_lowres;
else {
svga->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5);
svga->hdisp++;
svga->hdisp *= 8;
if (svga->hdisp == 1280)
svga->rowoffset >>= 1;
if (svga->hdisp == 1280)
svga->rowoffset >>= 1;
svga->render = svga_render_4bpp_highres;
}
break;
case 0x20: /*4 colours*/
if (svga->seqregs[1] & 8) /*Low res (320)*/
svga->render = svga_render_2bpp_lowres;
else
svga->render = svga_render_2bpp_highres;
break;
case 0x40: case 0x60:
svga->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5);
svga->hdisp++;
svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8;
if (svga->crtc[0x19] & 2) {
if (svga->hdisp == 1280) {
svga->hdisp >>= 1;
} else
svga->rowoffset <<= 1;
svga->render = svga_render_4bpp_highres;
}
break;
case 0x20: /*4 colours*/
if (svga->seqregs[1] & 8) /*Low res (320)*/
svga->render = svga_render_2bpp_lowres;
else
svga->render = svga_render_2bpp_highres;
break;
case 0x40:
case 0x60:
svga->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5);
svga->hdisp++;
svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8;
if (svga->crtc[0x19] & 2) {
if (svga->hdisp == 1280) {
svga->hdisp >>= 1;
} else
svga->rowoffset <<= 1;
svga->render = svga_render_8bpp_highres;
} else {
if (svga->lowres)
svga->render = svga_render_8bpp_lowres;
else
svga->render = svga_render_8bpp_highres;
}
break;
}
}
svga->render = svga_render_8bpp_highres;
} else {
if (svga->lowres)
svga->render = svga_render_8bpp_lowres;
else
svga->render = svga_render_8bpp_highres;
}
break;
}
}
}
static void *
rtg_init(const device_t *info)
{
const char *fn;
rtg_t *dev;
rtg_t *dev;
dev = (rtg_t *)malloc(sizeof(rtg_t));
dev = (rtg_t *) malloc(sizeof(rtg_t));
memset(dev, 0x00, sizeof(rtg_t));
dev->name = info->name;
dev->type = info->local;
fn = BIOS_ROM_PATH;
fn = BIOS_ROM_PATH;
switch(dev->type) {
case 2: /* ISA RTG3106 */
dev->vram_size = device_get_config_int("memory") << 10;
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_rtg_isa);
svga_init(info, &dev->svga, dev, dev->vram_size,
rtg_recalctimings, rtg_in, rtg_out,
NULL, NULL);
io_sethandler(0x03c0, 32,
rtg_in,NULL,NULL, rtg_out,NULL,NULL, dev);
break;
switch (dev->type) {
case 2: /* ISA RTG3106 */
dev->vram_size = device_get_config_int("memory") << 10;
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_rtg_isa);
svga_init(info, &dev->svga, dev, dev->vram_size,
rtg_recalctimings, rtg_in, rtg_out,
NULL, NULL);
io_sethandler(0x03c0, 32,
rtg_in, NULL, NULL, rtg_out, NULL, NULL, dev);
break;
}
dev->svga.bpp = 8;
dev->svga.miscout = 1;
dev->svga.bpp = 8;
dev->svga.miscout = 1;
dev->vram_mask = dev->vram_size - 1;
rom_init(&dev->bios_rom, (char *) fn,
0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
return(dev);
return (dev);
}
static void
rtg_close(void *priv)
{
rtg_t *dev = (rtg_t *)priv;
rtg_t *dev = (rtg_t *) priv;
svga_close(&dev->svga);
free(dev);
}
static void
rtg_speed_changed(void *priv)
{
rtg_t *dev = (rtg_t *)priv;
rtg_t *dev = (rtg_t *) priv;
svga_recalctimings(&dev->svga);
}
static void
rtg_force_redraw(void *priv)
{
rtg_t *dev = (rtg_t *)priv;
rtg_t *dev = (rtg_t *) priv;
dev->svga.fullchange = changeframecount;
}
static int
rtg_available(void)
{
@@ -359,7 +353,7 @@ rtg_available(void)
}
static const device_config_t rtg_config[] = {
// clang-format off
// clang-format off
{
.name = "memory",
.description = "Memory size",
@@ -390,15 +384,15 @@ static const device_config_t rtg_config[] = {
};
const device_t realtek_rtg3106_device = {
.name = "Realtek RTG3106 (ISA)",
.name = "Realtek RTG3106 (ISA)",
.internal_name = "rtg3106",
.flags = DEVICE_ISA | DEVICE_AT,
.local = 2,
.init = rtg_init,
.close = rtg_close,
.reset = NULL,
.flags = DEVICE_ISA | DEVICE_AT,
.local = 2,
.init = rtg_init,
.close = rtg_close,
.reset = NULL,
{ .available = rtg_available },
.speed_changed = rtg_speed_changed,
.force_redraw = rtg_force_redraw,
.config = rtg_config
.force_redraw = rtg_force_redraw,
.config = rtg_config
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -28,104 +28,103 @@
#include <86box/video.h>
#include <86box/vid_svga.h>
typedef struct
{
int type;
int state;
int rs2;
int type;
int state;
int rs2;
uint8_t ctrl;
} sc1148x_ramdac_t;
void
sc1148x_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga)
{
sc1148x_ramdac_t *ramdac = (sc1148x_ramdac_t *) p;
uint8_t rs = (addr & 0x03) | ((!!rs2) << 2);
int oldbpp = 0;
uint8_t rs = (addr & 0x03) | ((!!rs2) << 2);
int oldbpp = 0;
switch (rs) {
case 2: case 6:
switch (ramdac->state) {
case 4:
ramdac->state = 0;
if (val == 0xff)
break;
ramdac->ctrl = val;
ramdac->ctrl = (ramdac->ctrl & ~1) | ((((val >> 2) ^ val) & (val & 0x20)) >> 5);
oldbpp = svga->bpp;
switch (ramdac->type) {
case 0: /* Sierra Mark 2 (11483)*/
case 2: /* Sierra Mark 2 (11484)*/
case 3: /* Sierra Mark 1 (11486)*/
if (val & 0xa0) {
svga->bpp = 15;
} else if (val == 0x00)
svga->bpp = 8;
break;
case 1: /* Sierra Mark 3 (11487)*/
if (val & 0xa0) {
if (val & 0x40)
svga->bpp = 16;
else
svga->bpp = 15;
} else if (val == 0x00)
svga->bpp = 8;
break;
}
if (oldbpp != svga->bpp)
svga_recalctimings(svga);
return;
default:
svga_out(addr, val, svga);
break;
}
break;
case 2:
case 6:
switch (ramdac->state) {
case 4:
ramdac->state = 0;
if (val == 0xff)
break;
ramdac->ctrl = val;
ramdac->ctrl = (ramdac->ctrl & ~1) | ((((val >> 2) ^ val) & (val & 0x20)) >> 5);
oldbpp = svga->bpp;
switch (ramdac->type) {
case 0: /* Sierra Mark 2 (11483)*/
case 2: /* Sierra Mark 2 (11484)*/
case 3: /* Sierra Mark 1 (11486)*/
if (val & 0xa0) {
svga->bpp = 15;
} else if (val == 0x00)
svga->bpp = 8;
break;
case 1: /* Sierra Mark 3 (11487)*/
if (val & 0xa0) {
if (val & 0x40)
svga->bpp = 16;
else
svga->bpp = 15;
} else if (val == 0x00)
svga->bpp = 8;
break;
}
if (oldbpp != svga->bpp)
svga_recalctimings(svga);
return;
default:
svga_out(addr, val, svga);
break;
}
break;
default:
ramdac->state = 0;
svga_out(addr, val, svga);
break;
default:
ramdac->state = 0;
svga_out(addr, val, svga);
break;
}
}
uint8_t
sc1148x_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga)
{
sc1148x_ramdac_t *ramdac = (sc1148x_ramdac_t *) p;
uint8_t ret = 0xff, rs = (addr & 0x03) | ((!!rs2) << 2);
uint8_t ret = 0xff, rs = (addr & 0x03) | ((!!rs2) << 2);
switch (rs) {
case 2: case 6:
switch (ramdac->state) {
case 1:
case 2: case 3:
ret = 0x00;
ramdac->state++;
break;
case 4:
ret = ramdac->ctrl;
ret = (ret & ~0x18) | (svga->dac_mask & 0x18);
break;
default:
ret = svga_in(addr, svga);
ramdac->state++;
break;
}
break;
case 2:
case 6:
switch (ramdac->state) {
case 1:
case 2:
case 3:
ret = 0x00;
ramdac->state++;
break;
case 4:
ret = ramdac->ctrl;
ret = (ret & ~0x18) | (svga->dac_mask & 0x18);
break;
default:
ret = svga_in(addr, svga);
ramdac->state++;
break;
}
break;
default:
ret = svga_in(addr, svga);
ramdac->state = 0;
break;
default:
ret = svga_in(addr, svga);
ramdac->state = 0;
break;
}
return ret;
}
static void *
sc1148x_ramdac_init(const device_t *info)
{
@@ -137,68 +136,67 @@ sc1148x_ramdac_init(const device_t *info)
return ramdac;
}
static void
sc1148x_ramdac_close(void *priv)
{
sc1148x_ramdac_t *ramdac = (sc1148x_ramdac_t *) priv;
if (ramdac)
free(ramdac);
free(ramdac);
}
const device_t sc11483_ramdac_device = {
.name = "Sierra SC11483 RAMDAC",
.name = "Sierra SC11483 RAMDAC",
.internal_name = "sc11483_ramdac",
.flags = 0,
.local = 0,
.init = sc1148x_ramdac_init,
.close = sc1148x_ramdac_close,
.reset = NULL,
.flags = 0,
.local = 0,
.init = sc1148x_ramdac_init,
.close = sc1148x_ramdac_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
const device_t sc11487_ramdac_device = {
.name = "Sierra SC11487 RAMDAC",
.name = "Sierra SC11487 RAMDAC",
.internal_name = "sc11487_ramdac",
.flags = 0,
.local = 1,
.init = sc1148x_ramdac_init,
.close = sc1148x_ramdac_close,
.reset = NULL,
.flags = 0,
.local = 1,
.init = sc1148x_ramdac_init,
.close = sc1148x_ramdac_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
const device_t sc11484_nors2_ramdac_device = {
.name = "Sierra SC11484 RAMDAC (no RS2 signal)",
.name = "Sierra SC11484 RAMDAC (no RS2 signal)",
.internal_name = "sc11484_nors2_ramdac",
.flags = 0,
.local = 2,
.init = sc1148x_ramdac_init,
.close = sc1148x_ramdac_close,
.reset = NULL,
.flags = 0,
.local = 2,
.init = sc1148x_ramdac_init,
.close = sc1148x_ramdac_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
const device_t sc11486_ramdac_device = {
.name = "Sierra SC11486 RAMDAC",
.name = "Sierra SC11486 RAMDAC",
.internal_name = "sc11486_ramdac",
.flags = 0,
.local = 3,
.init = sc1148x_ramdac_init,
.close = sc1148x_ramdac_close,
.reset = NULL,
.flags = 0,
.local = 3,
.init = sc1148x_ramdac_init,
.close = sc1148x_ramdac_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};

View File

@@ -30,110 +30,106 @@
#include <86box/video.h>
#include <86box/vid_svga.h>
typedef struct
{
int state;
int state;
uint8_t ctrl;
} sc1502x_ramdac_t;
void
sc1502x_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga)
{
sc1502x_ramdac_t *ramdac = (sc1502x_ramdac_t *) p;
int oldbpp = 0;
int oldbpp = 0;
switch (addr) {
case 0x3C6:
if (ramdac->state == 4) {
ramdac->state = 0;
if (val == 0xFF)
break;
ramdac->ctrl = val;
oldbpp = svga->bpp;
switch ((val & 1) | ((val & 0xc0) >> 5)) {
case 0:
svga->bpp = 8;
break;
case 2:
case 3:
switch (val & 0x20) {
case 0x00:
svga->bpp = 32;
break;
case 0x20:
svga->bpp = 24;
break;
}
break;
case 4:
case 5:
svga->bpp = 15;
break;
case 6:
svga->bpp = 16;
break;
case 7:
if (val & 4) {
switch (val & 0x20) {
case 0x00:
svga->bpp = 32;
break;
case 0x20:
svga->bpp = 24;
break;
}
break;
} else {
svga->bpp = 16;
break;
}
break;
}
if (oldbpp != svga->bpp)
svga_recalctimings(svga);
return;
}
ramdac->state = 0;
break;
case 0x3C7:
case 0x3C8:
case 0x3C9:
ramdac->state = 0;
break;
case 0x3C6:
if (ramdac->state == 4) {
ramdac->state = 0;
if (val == 0xFF)
break;
ramdac->ctrl = val;
oldbpp = svga->bpp;
switch ((val & 1) | ((val & 0xc0) >> 5)) {
case 0:
svga->bpp = 8;
break;
case 2:
case 3:
switch (val & 0x20) {
case 0x00:
svga->bpp = 32;
break;
case 0x20:
svga->bpp = 24;
break;
}
break;
case 4:
case 5:
svga->bpp = 15;
break;
case 6:
svga->bpp = 16;
break;
case 7:
if (val & 4) {
switch (val & 0x20) {
case 0x00:
svga->bpp = 32;
break;
case 0x20:
svga->bpp = 24;
break;
}
break;
} else {
svga->bpp = 16;
break;
}
break;
}
if (oldbpp != svga->bpp)
svga_recalctimings(svga);
return;
}
ramdac->state = 0;
break;
case 0x3C7:
case 0x3C8:
case 0x3C9:
ramdac->state = 0;
break;
}
svga_out(addr, val, svga);
}
uint8_t
sc1502x_ramdac_in(uint16_t addr, void *p, svga_t *svga)
{
sc1502x_ramdac_t *ramdac = (sc1502x_ramdac_t *) p;
uint8_t temp = svga_in(addr, svga);
uint8_t temp = svga_in(addr, svga);
switch (addr) {
case 0x3C6:
if (ramdac->state == 4) {
ramdac->state = 0;
temp = ramdac->ctrl;
break;
}
ramdac->state++;
break;
case 0x3C7:
case 0x3C8:
case 0x3C9:
ramdac->state = 0;
break;
case 0x3C6:
if (ramdac->state == 4) {
ramdac->state = 0;
temp = ramdac->ctrl;
break;
}
ramdac->state++;
break;
case 0x3C7:
case 0x3C8:
case 0x3C9:
ramdac->state = 0;
break;
}
return temp;
}
static void *
sc1502x_ramdac_init(const device_t *info)
{
@@ -143,26 +139,25 @@ sc1502x_ramdac_init(const device_t *info)
return ramdac;
}
static void
sc1502x_ramdac_close(void *priv)
{
sc1502x_ramdac_t *ramdac = (sc1502x_ramdac_t *) priv;
if (ramdac)
free(ramdac);
free(ramdac);
}
const device_t sc1502x_ramdac_device = {
.name = "Sierra SC1502x RAMDAC",
.name = "Sierra SC1502x RAMDAC",
.internal_name = "sc1502x_ramdac",
.flags = 0,
.local = 0,
.init = sc1502x_ramdac_init,
.close = sc1502x_ramdac_close,
.reset = NULL,
.flags = 0,
.local = 0,
.init = sc1502x_ramdac_init,
.close = sc1502x_ramdac_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};

View File

@@ -28,9 +28,7 @@
#include <86box/video.h>
#include <86box/vid_svga.h>
enum
{
enum {
ICS_5300 = 0,
ICS_5301,
ICS_5340,
@@ -38,247 +36,238 @@ enum
ICS_5342
};
#define ICS_S3_MASK 7
#define ICS_S3 8
#define ICS_S3_MASK 7
#define ICS_S3 8
#define S3_86C708 (ICS_5300 | ICS_S3)
#define S3_86C716 (ICS_5342 | ICS_S3)
#define S3_86C708 (ICS_5300 | ICS_S3)
#define S3_86C716 (ICS_5342 | ICS_S3)
typedef struct sdac_ramdac_t
{
typedef struct sdac_ramdac_t {
uint16_t regs[256];
int magic_count,
windex, rindex,
reg_ff, rs2;
int magic_count,
windex, rindex,
reg_ff, rs2;
uint8_t type, command;
} sdac_ramdac_t;
static void
sdac_control_write(sdac_ramdac_t *ramdac, svga_t *svga, uint8_t val)
{
ramdac->command = val;
switch (ramdac->type & ICS_S3_MASK) {
case ICS_5300:
case ICS_5301:
switch (val >> 5) {
case 0x00:
default:
svga->bpp = 8;
break;
case 0x01:
case 0x04:
case 0x05:
svga->bpp = 15;
break;
case 0x03:
case 0x06:
svga->bpp = 16;
break;
case 0x02:
case 0x07:
svga->bpp = 24;
break;
}
break;
case ICS_5340:
case ICS_5341:
case ICS_5342:
switch (val >> 4) {
case 0x00:
case 0x01: /* This is actually 8bpp with two pixels read at a time. */
default:
svga->bpp = 8;
break;
case 0x02:
case 0x03:
case 0x08:
case 0x0a:
svga->bpp = 15;
break;
case 0x05:
case 0x06:
case 0x0c:
svga->bpp = 16;
break;
case 0x04:
case 0x09:
case 0x0e:
svga->bpp = 24;
break;
case 0x07:
svga->bpp = 32;
break;
}
break;
case ICS_5300:
case ICS_5301:
switch (val >> 5) {
case 0x00:
default:
svga->bpp = 8;
break;
case 0x01:
case 0x04:
case 0x05:
svga->bpp = 15;
break;
case 0x03:
case 0x06:
svga->bpp = 16;
break;
case 0x02:
case 0x07:
svga->bpp = 24;
break;
}
break;
case ICS_5340:
case ICS_5341:
case ICS_5342:
switch (val >> 4) {
case 0x00:
case 0x01: /* This is actually 8bpp with two pixels read at a time. */
default:
svga->bpp = 8;
break;
case 0x02:
case 0x03:
case 0x08:
case 0x0a:
svga->bpp = 15;
break;
case 0x05:
case 0x06:
case 0x0c:
svga->bpp = 16;
break;
case 0x04:
case 0x09:
case 0x0e:
svga->bpp = 24;
break;
case 0x07:
svga->bpp = 32;
break;
}
break;
}
svga_recalctimings(svga);
}
static void
sdac_reg_write(sdac_ramdac_t *ramdac, int reg, uint8_t val)
{
if ((reg >= 2 && reg <= 7) || (reg == 0xa) || (reg == 0xe)) {
if (!ramdac->reg_ff)
ramdac->regs[reg] = (ramdac->regs[reg] & 0xff00) | val;
else
ramdac->regs[reg] = (ramdac->regs[reg] & 0x00ff) | (val << 8);
if (!ramdac->reg_ff)
ramdac->regs[reg] = (ramdac->regs[reg] & 0xff00) | val;
else
ramdac->regs[reg] = (ramdac->regs[reg] & 0x00ff) | (val << 8);
}
ramdac->reg_ff = !ramdac->reg_ff;
if (!ramdac->reg_ff)
ramdac->windex++;
ramdac->windex++;
}
static uint8_t
sdac_reg_read(sdac_ramdac_t *ramdac, int reg)
{
uint8_t temp;
if (!ramdac->reg_ff)
temp = ramdac->regs[reg] & 0xff;
temp = ramdac->regs[reg] & 0xff;
else
temp = ramdac->regs[reg] >> 8;
temp = ramdac->regs[reg] >> 8;
ramdac->reg_ff = !ramdac->reg_ff;
if (!ramdac->reg_ff)
ramdac->rindex++;
ramdac->rindex++;
return temp;
}
void
sdac_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga)
{
sdac_ramdac_t *ramdac = (sdac_ramdac_t *) p;
uint8_t rs = (addr & 0x03);
uint8_t rs = (addr & 0x03);
rs |= ((!!rs2) << 2);
if (rs != 0x02)
ramdac->magic_count = 0;
ramdac->magic_count = 0;
switch (rs) {
case 0x02:
switch (ramdac->magic_count) {
case 4:
sdac_control_write(ramdac, svga, val);
ramdac->magic_count = 0;
break;
default:
svga_out(addr, val, svga);
break;
}
break;
case 0x00:
case 0x01:
case 0x03:
svga_out(addr, val, svga);
break;
case 0x04:
ramdac->windex = val;
ramdac->reg_ff = 0;
break;
case 0x05:
sdac_reg_write(ramdac, ramdac->windex & 0xff, val);
break;
case 0x06:
sdac_control_write(ramdac, svga, val);
break;
case 0x07:
ramdac->rindex = val;
ramdac->reg_ff = 0;
break;
case 0x02:
switch (ramdac->magic_count) {
case 4:
sdac_control_write(ramdac, svga, val);
ramdac->magic_count = 0;
break;
default:
svga_out(addr, val, svga);
break;
}
break;
case 0x00:
case 0x01:
case 0x03:
svga_out(addr, val, svga);
break;
case 0x04:
ramdac->windex = val;
ramdac->reg_ff = 0;
break;
case 0x05:
sdac_reg_write(ramdac, ramdac->windex & 0xff, val);
break;
case 0x06:
sdac_control_write(ramdac, svga, val);
break;
case 0x07:
ramdac->rindex = val;
ramdac->reg_ff = 0;
break;
}
}
uint8_t
sdac_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga)
{
sdac_ramdac_t *ramdac = (sdac_ramdac_t *) p;
uint8_t temp = 0xff;
uint8_t rs = (addr & 0x03);
uint8_t temp = 0xff;
uint8_t rs = (addr & 0x03);
rs |= ((!!rs2) << 2);
if (rs != 0x02)
ramdac->magic_count = 0;
ramdac->magic_count = 0;
switch (rs) {
case 0x02:
switch (ramdac->magic_count) {
case 1: case 2:
temp = 0x00;
ramdac->magic_count++;
break;
case 3:
temp = (ramdac->type & ICS_S3) ? 0x70 : 0x00;
ramdac->magic_count++;
break;
case 4:
temp = ramdac->command;
ramdac->magic_count = 0;
break;
default:
temp = svga_in(addr, svga);
ramdac->magic_count++;
break;
}
break;
case 0x00:
case 0x01:
case 0x03:
temp = svga_in(addr, svga);
break;
case 0x04:
temp = ramdac->windex;
break;
case 0x05:
temp = sdac_reg_read(ramdac, ramdac->rindex & 0xff);
break;
case 0x06:
temp = ramdac->command;
break;
case 0x07:
temp = ramdac->rindex;
break;
case 0x02:
switch (ramdac->magic_count) {
case 1:
case 2:
temp = 0x00;
ramdac->magic_count++;
break;
case 3:
temp = (ramdac->type & ICS_S3) ? 0x70 : 0x00;
ramdac->magic_count++;
break;
case 4:
temp = ramdac->command;
ramdac->magic_count = 0;
break;
default:
temp = svga_in(addr, svga);
ramdac->magic_count++;
break;
}
break;
case 0x00:
case 0x01:
case 0x03:
temp = svga_in(addr, svga);
break;
case 0x04:
temp = ramdac->windex;
break;
case 0x05:
temp = sdac_reg_read(ramdac, ramdac->rindex & 0xff);
break;
case 0x06:
temp = ramdac->command;
break;
case 0x07:
temp = ramdac->rindex;
break;
}
return temp;
}
float
sdac_getclock(int clock, void *p)
{
sdac_ramdac_t *ramdac = (sdac_ramdac_t *)p;
float t;
int m, n1, n2;
sdac_ramdac_t *ramdac = (sdac_ramdac_t *) p;
float t;
int m, n1, n2;
if (ramdac->regs[0xe] & (1 << 5))
clock = ramdac->regs[0xe] & 7;
clock = ramdac->regs[0xe] & 7;
clock &= 7;
if (clock == 0)
return 25175000.0;
return 25175000.0;
if (clock == 1)
return 28322000.0;
return 28322000.0;
m = (ramdac->regs[clock] & 0x7f) + 2;
n1 = ((ramdac->regs[clock] >> 8) & 0x1f) + 2;
m = (ramdac->regs[clock] & 0x7f) + 2;
n1 = ((ramdac->regs[clock] >> 8) & 0x1f) + 2;
n2 = ((ramdac->regs[clock] >> 13) & 0x07);
n2 = (1 << n2);
t = (14318184.0f * (float)m) / (float)(n1 * n2);
t = (14318184.0f * (float) m) / (float) (n1 * n2);
return t;
}
void *
sdac_ramdac_init(const device_t *info)
{
@@ -293,68 +282,67 @@ sdac_ramdac_init(const device_t *info)
return ramdac;
}
static void
sdac_ramdac_close(void *priv)
{
sdac_ramdac_t *ramdac = (sdac_ramdac_t *) priv;
if (ramdac)
free(ramdac);
free(ramdac);
}
const device_t gendac_ramdac_device = {
.name = "S3 GENDAC 86c708 RAMDAC",
.name = "S3 GENDAC 86c708 RAMDAC",
.internal_name = "gendac_ramdac",
.flags = 0,
.local = S3_86C708,
.init = sdac_ramdac_init,
.close = sdac_ramdac_close,
.reset = NULL,
.flags = 0,
.local = S3_86C708,
.init = sdac_ramdac_init,
.close = sdac_ramdac_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
const device_t tseng_ics5301_ramdac_device = {
.name = "Tseng ICS5301 GENDAC RAMDAC",
.name = "Tseng ICS5301 GENDAC RAMDAC",
.internal_name = "tseng_ics5301_ramdac",
.flags = 0,
.local = ICS_5301,
.init = sdac_ramdac_init,
.close = sdac_ramdac_close,
.reset = NULL,
.flags = 0,
.local = ICS_5301,
.init = sdac_ramdac_init,
.close = sdac_ramdac_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
const device_t tseng_ics5341_ramdac_device = {
.name = "Tseng ICS5341 GENDAC RAMDAC",
.name = "Tseng ICS5341 GENDAC RAMDAC",
.internal_name = "tseng_ics5341_ramdac",
.flags = 0,
.local = ICS_5341,
.init = sdac_ramdac_init,
.close = sdac_ramdac_close,
.reset = NULL,
.flags = 0,
.local = ICS_5341,
.init = sdac_ramdac_init,
.close = sdac_ramdac_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
const device_t sdac_ramdac_device = {
.name = "S3 SDAC 86c716 RAMDAC",
.name = "S3 SDAC 86c716 RAMDAC",
.internal_name = "sdac_ramdac",
.flags = 0,
.local = S3_86C716,
.init = sdac_ramdac_init,
.close = sdac_ramdac_close,
.reset = NULL,
.flags = 0,
.local = S3_86C716,
.init = sdac_ramdac_init,
.close = sdac_ramdac_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};

File diff suppressed because it is too large Load Diff

View File

@@ -28,205 +28,199 @@
#include <86box/video.h>
#include <86box/vid_svga.h>
typedef struct stg_ramdac_t
{
int magic_count, index;
typedef struct stg_ramdac_t {
int magic_count, index;
uint8_t regs[256];
uint8_t command;
} stg_ramdac_t;
static int stg_state_read[2][8] = {{1,2,3,4,0,0,0,0}, {1,2,3,4,5,6,7,7}};
static int stg_state_write[8] = {0,0,0,0,0,6,7,7};
static int stg_state_read[2][8] = {
{1, 2, 3, 4, 0, 0, 0, 0},
{ 1, 2, 3, 4, 5, 6, 7, 7}
};
static int stg_state_write[8] = { 0, 0, 0, 0, 0, 6, 7, 7 };
void
stg_ramdac_set_bpp(svga_t *svga, stg_ramdac_t *ramdac)
{
if (ramdac->command & 0x8) {
switch (ramdac->regs[3]) {
case 0:
case 5:
case 7:
default:
svga->bpp = 8;
break;
case 1:
case 2:
case 8:
svga->bpp = 15;
break;
case 3:
case 6:
svga->bpp = 16;
break;
case 4:
case 9:
svga->bpp = 24;
break;
}
case 0:
case 5:
case 7:
default:
svga->bpp = 8;
break;
case 1:
case 2:
case 8:
svga->bpp = 15;
break;
case 3:
case 6:
svga->bpp = 16;
break;
case 4:
case 9:
svga->bpp = 24;
break;
}
} else {
switch (ramdac->command >> 5) {
case 0:
default:
svga->bpp = 8;
break;
case 5:
svga->bpp = 15;
break;
case 6:
svga->bpp = 16;
break;
case 7:
svga->bpp = 24;
break;
}
switch (ramdac->command >> 5) {
case 0:
default:
svga->bpp = 8;
break;
case 5:
svga->bpp = 15;
break;
case 6:
svga->bpp = 16;
break;
case 7:
svga->bpp = 24;
break;
}
}
svga_recalctimings(svga);
}
void
stg_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga)
{
stg_ramdac_t *ramdac = (stg_ramdac_t *) p;
int didwrite, old;
int didwrite, old;
switch (addr) {
case 0x3c6:
switch (ramdac->magic_count) {
/* 0 = PEL mask register */
case 0:
case 1:
case 2:
case 3:
break;
case 4: /* REG06 */
old = ramdac->command;
ramdac->command = val;
if ((old ^ val) & 8)
stg_ramdac_set_bpp(svga, ramdac);
else {
if ((old ^ val) & 0xE0)
stg_ramdac_set_bpp(svga, ramdac);
}
break;
case 5:
ramdac->index = (ramdac->index & 0xff00) | val;
break;
case 6:
ramdac->index = (ramdac->index & 0xff) | (val << 8);
break;
case 7:
if (ramdac->index < 0x100)
ramdac->regs[ramdac->index] = val;
if ((ramdac->index == 3) && (ramdac->command & 8))
stg_ramdac_set_bpp(svga, ramdac);
ramdac->index++;
break;
}
didwrite = (ramdac->magic_count >= 4);
ramdac->magic_count = stg_state_write[ramdac->magic_count & 7];
if (didwrite)
return;
break;
case 0x3c7:
case 0x3c8:
case 0x3c9:
ramdac->magic_count=0;
break;
case 0x3c6:
switch (ramdac->magic_count) {
/* 0 = PEL mask register */
case 0:
case 1:
case 2:
case 3:
break;
case 4: /* REG06 */
old = ramdac->command;
ramdac->command = val;
if ((old ^ val) & 8)
stg_ramdac_set_bpp(svga, ramdac);
else {
if ((old ^ val) & 0xE0)
stg_ramdac_set_bpp(svga, ramdac);
}
break;
case 5:
ramdac->index = (ramdac->index & 0xff00) | val;
break;
case 6:
ramdac->index = (ramdac->index & 0xff) | (val << 8);
break;
case 7:
if (ramdac->index < 0x100)
ramdac->regs[ramdac->index] = val;
if ((ramdac->index == 3) && (ramdac->command & 8))
stg_ramdac_set_bpp(svga, ramdac);
ramdac->index++;
break;
}
didwrite = (ramdac->magic_count >= 4);
ramdac->magic_count = stg_state_write[ramdac->magic_count & 7];
if (didwrite)
return;
break;
case 0x3c7:
case 0x3c8:
case 0x3c9:
ramdac->magic_count = 0;
break;
}
svga_out(addr, val, svga);
}
uint8_t
stg_ramdac_in(uint16_t addr, void *p, svga_t *svga)
{
stg_ramdac_t *ramdac = (stg_ramdac_t *) p;
uint8_t temp = 0xff;
uint8_t temp = 0xff;
switch (addr) {
case 0x3c6:
switch (ramdac->magic_count) {
case 0:
case 1:
case 2:
case 3:
temp = 0xff;
break;
case 4:
temp = ramdac->command;
break;
case 5:
temp = ramdac->index & 0xff;
break;
case 6:
temp = ramdac->index >> 8;
break;
case 7:
switch (ramdac->index) {
case 0:
temp = 0x44;
break;
case 1:
temp = 0x03;
break;
case 7:
temp = 0x88;
break;
default:
if (ramdac->index < 0x100)
temp = ramdac->regs[ramdac->index];
else
temp = 0xff;
break;
}
ramdac->index++;
break;
}
ramdac->magic_count = stg_state_read[(ramdac->command & 0x10) ? 1 : 0][ramdac->magic_count & 7];
return temp;
case 0x3c7:
case 0x3c8:
case 0x3c9:
ramdac->magic_count=0;
break;
case 0x3c6:
switch (ramdac->magic_count) {
case 0:
case 1:
case 2:
case 3:
temp = 0xff;
break;
case 4:
temp = ramdac->command;
break;
case 5:
temp = ramdac->index & 0xff;
break;
case 6:
temp = ramdac->index >> 8;
break;
case 7:
switch (ramdac->index) {
case 0:
temp = 0x44;
break;
case 1:
temp = 0x03;
break;
case 7:
temp = 0x88;
break;
default:
if (ramdac->index < 0x100)
temp = ramdac->regs[ramdac->index];
else
temp = 0xff;
break;
}
ramdac->index++;
break;
}
ramdac->magic_count = stg_state_read[(ramdac->command & 0x10) ? 1 : 0][ramdac->magic_count & 7];
return temp;
case 0x3c7:
case 0x3c8:
case 0x3c9:
ramdac->magic_count = 0;
break;
}
return svga_in(addr, svga);
}
float
stg_getclock(int clock, void *p)
{
stg_ramdac_t *ramdac = (stg_ramdac_t *)p;
float t;
int m, n, n2;
uint16_t *c;
stg_ramdac_t *ramdac = (stg_ramdac_t *) p;
float t;
int m, n, n2;
uint16_t *c;
if (clock == 0)
return 25175000.0;
return 25175000.0;
if (clock == 1)
return 28322000.0;
return 28322000.0;
clock ^= 1; /*Clocks 2 and 3 seem to be reversed*/
c = (uint16_t *) &ramdac->regs[0x20 + (clock << 1)];
m = (*c & 0xff) + 2; /* B+2 */
n = ((*c >> 8) & 0x1f) + 2; /* N1+2 */
n2 = ((*c >> 13) & 0x07); /* D */
clock ^= 1; /*Clocks 2 and 3 seem to be reversed*/
c = (uint16_t *) &ramdac->regs[0x20 + (clock << 1)];
m = (*c & 0xff) + 2; /* B+2 */
n = ((*c >> 8) & 0x1f) + 2; /* N1+2 */
n2 = ((*c >> 13) & 0x07); /* D */
n2 = (1 << n2);
t = (14318184.0f * (float)m) / (float)(n * n2);
t = (14318184.0f * (float) m) / (float) (n * n2);
return t;
}
static void *
stg_ramdac_init(const device_t *info)
{
@@ -236,26 +230,25 @@ stg_ramdac_init(const device_t *info)
return ramdac;
}
static void
stg_ramdac_close(void *priv)
{
stg_ramdac_t *ramdac = (stg_ramdac_t *) priv;
if (ramdac)
free(ramdac);
free(ramdac);
}
const device_t stg_ramdac_device = {
.name = "SGS-Thompson STG170x RAMDAC",
.name = "SGS-Thompson STG170x RAMDAC",
.internal_name = "stg_ramdac",
.flags = 0,
.local = 0,
.init = stg_ramdac_init,
.close = stg_ramdac_close,
.reset = NULL,
.flags = 0,
.local = 0,
.init = stg_ramdac_init,
.close = stg_ramdac_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -37,47 +37,45 @@
#include <86box/vid_colorplus.h>
#include <86box/vid_mda.h>
typedef struct {
const device_t *device;
int flags;
const device_t *device;
int flags;
} VIDEO_CARD;
static video_timings_t timing_default = {VIDEO_ISA, 8, 16, 32, 8, 16, 32};
static video_timings_t timing_default = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 };
static int was_reset = 0;
static const device_t vid_none_device = {
.name = "None",
.name = "None",
.internal_name = "none",
.flags = 0,
.local = 0,
.init = NULL,
.close = NULL,
.reset = NULL,
.flags = 0,
.local = 0,
.init = NULL,
.close = NULL,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
static const device_t vid_internal_device = {
.name = "Internal",
.name = "Internal",
.internal_name = "internal",
.flags = 0,
.local = 0,
.init = NULL,
.close = NULL,
.reset = NULL,
.flags = 0,
.local = 0,
.init = NULL,
.close = NULL,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};
// clang-format off
static const VIDEO_CARD
video_cards[] = {
// clang-format off
{ &vid_none_device },
{ &vid_internal_device },
{ &atiega_device },
@@ -252,30 +250,27 @@ video_cards[] = {
{ &voodoo_3_2000_agp_device },
{ &voodoo_3_3000_agp_device },
{ NULL }
// clang-format off
};
// clang-format on
#ifdef ENABLE_VID_TABLE_LOG
int vid_table_do_log = ENABLE_VID_TABLE_LOG;
static void
vid_table_log(const char *fmt, ...)
{
va_list ap;
if (vid_table_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define vid_table_log(fmt, ...)
# define vid_table_log(fmt, ...)
#endif
void
video_reset_close(void)
{
@@ -287,14 +282,13 @@ video_reset_close(void)
was_reset = 0;
}
static void
video_prepare(void)
{
/* Reset (deallocate) the video font arrays. */
if (fontdatksc5601) {
free(fontdatksc5601);
fontdatksc5601 = NULL;
free(fontdatksc5601);
fontdatksc5601 = NULL;
}
/* Reset the blend. */
@@ -302,7 +296,8 @@ video_prepare(void)
for (int i = 0; i < MONITORS_NUM; i++) {
/* Reset the CGA palette. */
if (monitors[i].mon_cga_palette) *monitors[i].mon_cga_palette = 0;
if (monitors[i].mon_cga_palette)
*monitors[i].mon_cga_palette = 0;
cgapal_rebuild_monitor(i);
/* Do an inform on the default values, so that that there's some sane values initialized
@@ -311,38 +306,34 @@ video_prepare(void)
}
}
void
video_pre_reset(int card)
{
if ((card == VID_NONE) || \
(card == VID_INTERNAL) || machine_has_flags(machine, MACHINE_VIDEO_ONLY))
video_prepare();
if ((card == VID_NONE) || (card == VID_INTERNAL) || machine_has_flags(machine, MACHINE_VIDEO_ONLY))
video_prepare();
}
void
video_reset(int card)
{
/* This is needed to avoid duplicate resets. */
if ((video_get_type() != VIDEO_FLAG_TYPE_NONE) && was_reset)
return;
return;
vid_table_log("VIDEO: reset (gfxcard=%d, internal=%d)\n",
card, machine_has_flags(machine, MACHINE_VIDEO) ? 1 : 0);
card, machine_has_flags(machine, MACHINE_VIDEO) ? 1 : 0);
monitor_index_global = 0;
loadfont("roms/video/mda/mda.rom", 0);
/* Do not initialize internal cards here. */
if (!(card == VID_NONE) && \
!(card == VID_INTERNAL) && !machine_has_flags(machine, MACHINE_VIDEO_ONLY)) {
vid_table_log("VIDEO: initializing '%s'\n", video_cards[card].name);
if (!(card == VID_NONE) && !(card == VID_INTERNAL) && !machine_has_flags(machine, MACHINE_VIDEO_ONLY)) {
vid_table_log("VIDEO: initializing '%s'\n", video_cards[card].name);
video_prepare();
video_prepare();
/* Initialize the video card. */
device_add(video_cards[card].device);
/* Initialize the video card. */
device_add(video_cards[card].device);
}
if (!(card == VID_NONE)
@@ -358,19 +349,18 @@ video_reset(int card)
/* Enable the Voodoo if configured. */
if (voodoo_enabled)
device_add(&voodoo_device);
device_add(&voodoo_device);
was_reset = 1;
}
int
video_card_available(int card)
{
if (video_cards[card].device)
return(device_available(video_cards[card].device));
return (device_available(video_cards[card].device));
return(1);
return (1);
}
int
@@ -382,55 +372,50 @@ video_card_get_flags(int card)
const device_t *
video_card_getdevice(int card)
{
return(video_cards[card].device);
return (video_cards[card].device);
}
int
video_card_has_config(int card)
{
if (video_cards[card].device == NULL) return(0);
if (video_cards[card].device == NULL)
return (0);
return(device_has_config(video_cards[card].device) ? 1 : 0);
return (device_has_config(video_cards[card].device) ? 1 : 0);
}
char *
video_get_internal_name(int card)
{
return device_get_internal_name(video_cards[card].device);
}
int
video_get_video_from_internal_name(char *s)
{
int c = 0;
while (video_cards[c].device != NULL) {
if (!strcmp((char *) video_cards[c].device->internal_name, s))
return(c);
c++;
if (!strcmp((char *) video_cards[c].device->internal_name, s))
return (c);
c++;
}
return(0);
return (0);
}
int
video_is_mda(void)
{
return (video_get_type() == VIDEO_FLAG_TYPE_MDA);
}
int
video_is_cga(void)
{
return (video_get_type() == VIDEO_FLAG_TYPE_CGA);
}
int
video_is_ega_vga(void)
{

File diff suppressed because it is too large Load Diff

View File

@@ -66,30 +66,28 @@
#include <86box/video.h>
#include <86box/vid_svga.h>
typedef struct {
svga_t svga;
svga_t svga;
rom_t bios_rom;
rom_t bios_rom;
int enabled;
int enabled;
uint32_t vram_size;
uint32_t vram_size;
uint8_t banking;
uint8_t reg_2100;
uint8_t reg_210a;
uint8_t banking;
uint8_t reg_2100;
uint8_t reg_210a;
} tivga_t;
static video_timings_t timing_ti_cf62011 = {VIDEO_ISA, 6, 8,16, 6, 8,16};
static video_timings_t timing_ti_cf62011 = { .type = VIDEO_ISA, .write_b = 6, .write_w = 8, .write_l = 16, .read_b = 6, .read_w = 8, .read_l = 16 };
static void
vid_out(uint16_t addr, uint8_t val, void *priv)
{
tivga_t *ti = (tivga_t *)priv;
svga_t *svga = &ti->svga;
uint8_t old;
tivga_t *ti = (tivga_t *) priv;
svga_t *svga = &ti->svga;
uint8_t old;
#if 0
if (((addr & 0xfff0) == 0x03d0 || (addr & 0xfff0) == 0x03b0) &&
@@ -97,60 +95,59 @@ vid_out(uint16_t addr, uint8_t val, void *priv)
#endif
switch (addr) {
case 0x0102:
ti->enabled = (val & 0x01);
return;
case 0x0102:
ti->enabled = (val & 0x01);
return;
case 0x03d4:
svga->crtcreg = val & 0x3f;
return;
case 0x03d4:
svga->crtcreg = val & 0x3f;
return;
case 0x03d5:
if (svga->crtcreg & 0x20)
return;
if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80))
return;
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
old = svga->crtc[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
if (old != val) {
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
}
}
break;
case 0x03d5:
if (svga->crtcreg & 0x20)
return;
if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80))
return;
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
old = svga->crtc[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
if (old != val) {
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
}
}
break;
case 0x2100:
ti->reg_2100 = val;
if ((val & 7) < 4)
svga->read_bank = svga->write_bank = 0;
else
svga->read_bank = svga->write_bank = (ti->banking & 0x7) * 0x10000;
break;
case 0x2100:
ti->reg_2100 = val;
if ((val & 7) < 4)
svga->read_bank = svga->write_bank = 0;
else
svga->read_bank = svga->write_bank = (ti->banking & 0x7) * 0x10000;
break;
case 0x2108:
if ((ti->reg_2100 & 7) >= 4)
svga->read_bank = svga->write_bank = (val & 0x7) * 0x10000;
ti->banking = val;
break;
case 0x2108:
if ((ti->reg_2100 & 7) >= 4)
svga->read_bank = svga->write_bank = (val & 0x7) * 0x10000;
ti->banking = val;
break;
case 0x210a:
ti->reg_210a = val;
break;
case 0x210a:
ti->reg_210a = val;
break;
}
svga_out(addr, val, svga);
}
static uint8_t
vid_in(uint16_t addr, void *priv)
{
tivga_t *ti = (tivga_t *)priv;
svga_t *svga = &ti->svga;
uint8_t ret;
tivga_t *ti = (tivga_t *) priv;
svga_t *svga = &ti->svga;
uint8_t ret;
#if 0
if (((addr & 0xfff0) == 0x03d0 || (addr & 0xfff0) == 0x03b0) &&
@@ -158,120 +155,116 @@ vid_in(uint16_t addr, void *priv)
#endif
switch (addr) {
case 0x0100:
ret = 0xfe;
break;
case 0x0100:
ret = 0xfe;
break;
case 0x0101:
ret = 0xe8;
break;
case 0x0101:
ret = 0xe8;
break;
case 0x0102:
ret = ti->enabled;
break;
case 0x0102:
ret = ti->enabled;
break;
case 0x03d4:
ret = svga->crtcreg;
break;
case 0x03d4:
ret = svga->crtcreg;
break;
case 0x03d5:
if (svga->crtcreg & 0x20)
ret = 0xff;
else
ret = svga->crtc[svga->crtcreg];
break;
case 0x03d5:
if (svga->crtcreg & 0x20)
ret = 0xff;
else
ret = svga->crtc[svga->crtcreg];
break;
case 0x2100:
ret = ti->reg_2100;
break;
case 0x2100:
ret = ti->reg_2100;
break;
case 0x2108:
ret = ti->banking;
break;
case 0x2108:
ret = ti->banking;
break;
case 0x210a:
ret = ti->reg_210a;
break;
case 0x210a:
ret = ti->reg_210a;
break;
default:
ret = svga_in(addr, svga);
break;
default:
ret = svga_in(addr, svga);
break;
}
return(ret);
return (ret);
}
static void
vid_speed_changed(void *priv)
{
tivga_t *ti = (tivga_t *)priv;
tivga_t *ti = (tivga_t *) priv;
svga_recalctimings(&ti->svga);
}
static void
vid_force_redraw(void *priv)
{
tivga_t *ti = (tivga_t *)priv;
tivga_t *ti = (tivga_t *) priv;
ti->svga.fullchange = changeframecount;
}
static void
vid_close(void *priv)
{
tivga_t *ti = (tivga_t *)priv;
tivga_t *ti = (tivga_t *) priv;
svga_close(&ti->svga);
free(ti);
}
static void *
vid_init(const device_t *info)
{
tivga_t *ti;
/* Allocate control block and initialize. */
ti = (tivga_t *)malloc(sizeof(tivga_t));
ti = (tivga_t *) malloc(sizeof(tivga_t));
memset(ti, 0x00, sizeof(tivga_t));
/* Set amount of VRAM in KB. */
if (info->local == 0)
ti->vram_size = device_get_config_int("vram_size");
ti->vram_size = device_get_config_int("vram_size");
else
ti->vram_size = info->local;
ti->vram_size = info->local;
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ti_cf62011);
svga_init(info, &ti->svga, ti,
ti->vram_size<<10,
NULL, vid_in, vid_out, NULL, NULL);
ti->vram_size << 10,
NULL, vid_in, vid_out, NULL, NULL);
io_sethandler(0x0100, 2, vid_in, NULL, NULL, NULL, NULL, NULL, ti);
io_sethandler(0x03c0, 32, vid_in, NULL, NULL, vid_out, NULL, NULL, ti);
io_sethandler(0x2100, 16, vid_in, NULL, NULL, vid_out, NULL, NULL, ti);
ti->svga.bpp = 8;
ti->svga.bpp = 8;
ti->svga.miscout = 1;
return(ti);
return (ti);
}
const device_t ibm_ps1_2121_device = {
.name = "IBM PS/1 Model 2121 SVGA",
.name = "IBM PS/1 Model 2121 SVGA",
.internal_name = "ibm_ps1_2121",
.flags = DEVICE_ISA,
.local = 512,
.init = vid_init,
.close = vid_close,
.reset = NULL,
.flags = DEVICE_ISA,
.local = 512,
.init = vid_init,
.close = vid_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = vid_speed_changed,
.force_redraw = vid_force_redraw,
.config = NULL
.force_redraw = vid_force_redraw,
.config = NULL
};

View File

@@ -28,76 +28,71 @@
#include <86box/video.h>
#include <86box/vid_svga.h>
typedef struct tkd8001_ramdac_t
{
int state;
typedef struct tkd8001_ramdac_t {
int state;
uint8_t ctrl;
} tkd8001_ramdac_t;
void
tkd8001_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga)
{
tkd8001_ramdac_t *ramdac = (tkd8001_ramdac_t *) p;
switch (addr) {
case 0x3C6:
if (ramdac->state == 4) {
ramdac->state = 0;
ramdac->ctrl = val;
switch (val >> 5) {
case 0:
case 1:
case 2:
case 3:
svga->bpp = 8;
break;
case 5:
svga->bpp = 15;
break;
case 6:
svga->bpp = 24;
break;
case 7:
svga->bpp = 16;
break;
}
return;
}
break;
case 0x3C7:
case 0x3C8:
case 0x3C9:
ramdac->state = 0;
break;
case 0x3C6:
if (ramdac->state == 4) {
ramdac->state = 0;
ramdac->ctrl = val;
switch (val >> 5) {
case 0:
case 1:
case 2:
case 3:
svga->bpp = 8;
break;
case 5:
svga->bpp = 15;
break;
case 6:
svga->bpp = 24;
break;
case 7:
svga->bpp = 16;
break;
}
return;
}
break;
case 0x3C7:
case 0x3C8:
case 0x3C9:
ramdac->state = 0;
break;
}
svga_out(addr, val, svga);
}
uint8_t
tkd8001_ramdac_in(uint16_t addr, void *p, svga_t *svga)
{
tkd8001_ramdac_t *ramdac = (tkd8001_ramdac_t *) p;
switch (addr) {
case 0x3C6:
if (ramdac->state == 4)
return ramdac->ctrl;
ramdac->state++;
break;
case 0x3C7:
case 0x3C8:
case 0x3C9:
ramdac->state = 0;
break;
case 0x3C6:
if (ramdac->state == 4)
return ramdac->ctrl;
ramdac->state++;
break;
case 0x3C7:
case 0x3C8:
case 0x3C9:
ramdac->state = 0;
break;
}
return svga_in(addr, svga);
}
static void *
tkd8001_ramdac_init(const device_t *info)
{
@@ -107,26 +102,25 @@ tkd8001_ramdac_init(const device_t *info)
return ramdac;
}
static void
tkd8001_ramdac_close(void *priv)
{
tkd8001_ramdac_t *ramdac = (tkd8001_ramdac_t *) priv;
if (ramdac)
free(ramdac);
free(ramdac);
}
const device_t tkd8001_ramdac_device = {
.name = "Trident TKD8001 RAMDAC",
.name = "Trident TKD8001 RAMDAC",
.internal_name = "tkd8001_ramdac",
.flags = 0,
.local = 0,
.init = tkd8001_ramdac_init,
.close = tkd8001_ramdac_close,
.reset = NULL,
.flags = 0,
.local = 0,
.init = tkd8001_ramdac_init,
.close = tkd8001_ramdac_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.force_redraw = NULL,
.config = NULL
};

View File

@@ -31,420 +31,453 @@
#include <86box/vid_svga.h>
#include <86box/vid_svga_render.h>
#define TVGA8900B_ID 0x03
#define TVGA9000B_ID 0x23
#define TVGA8900CLD_ID 0x33
#define TVGA8900B_ID 0x03
#define TVGA9000B_ID 0x23
#define TVGA8900CLD_ID 0x33
#define ROM_TVGA_8900B "roms/video/tvga/tvga8900b.vbi"
#define ROM_TVGA_8900CLD "roms/video/tvga/trident.bin"
#define ROM_TVGA_9000B "roms/video/tvga/tvga9000b.bin"
#define ROM_TVGA_8900B "roms/video/tvga/tvga8900b.vbi"
#define ROM_TVGA_8900CLD "roms/video/tvga/trident.bin"
#define ROM_TVGA_9000B "roms/video/tvga/tvga9000b.bin"
typedef struct tvga_t
{
mem_mapping_t linear_mapping;
mem_mapping_t accel_mapping;
typedef struct tvga_t {
mem_mapping_t linear_mapping;
mem_mapping_t accel_mapping;
svga_t svga;
svga_t svga;
rom_t bios_rom;
uint8_t card_id;
rom_t bios_rom;
uint8_t card_id;
uint8_t tvga_3d8, tvga_3d9;
int oldmode;
uint8_t oldctrl1;
uint8_t oldctrl2, newctrl2;
uint8_t tvga_3d8, tvga_3d9;
int oldmode;
uint8_t oldctrl1;
uint8_t oldctrl2, newctrl2;
int vram_size;
uint32_t vram_mask;
int vram_size;
uint32_t vram_mask;
} tvga_t;
video_timings_t timing_tvga8900 = {VIDEO_ISA, 3, 3, 6, 8, 8, 12};
video_timings_t timing_tvga9000 = {VIDEO_ISA, 7, 7, 12, 7, 7, 12};
video_timings_t timing_tvga8900 = { .type = VIDEO_ISA, .write_b = 3, .write_w = 3, .write_l = 6, .read_b = 8, .read_w = 8, .read_l = 12 };
video_timings_t timing_tvga9000 = { .type = VIDEO_ISA, .write_b = 7, .write_w = 7, .write_l = 12, .read_b = 7, .read_w = 7, .read_l = 12 };
static uint8_t crtc_mask[0x40] =
{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x7f, 0xff, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xef,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x7f, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x03,
0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
static uint8_t crtc_mask[0x40] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x7f, 0xff, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xef,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x7f, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x03,
0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static void tvga_recalcbanking(tvga_t *tvga);
void tvga_out(uint16_t addr, uint8_t val, void *p)
void
tvga_out(uint16_t addr, uint8_t val, void *p)
{
tvga_t *tvga = (tvga_t *)p;
svga_t *svga = &tvga->svga;
tvga_t *tvga = (tvga_t *) p;
svga_t *svga = &tvga->svga;
uint8_t old;
uint8_t old;
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1)) addr ^= 0x60;
if (((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && !(svga->miscout & 1))
addr ^= 0x60;
switch (addr)
{
case 0x3C5:
switch (svga->seqaddr & 0xf)
{
case 0xB:
tvga->oldmode=1;
break;
case 0xC:
if (svga->seqregs[0xe] & 0x80)
svga->seqregs[0xc] = val;
break;
case 0xd:
if (tvga->oldmode)
tvga->oldctrl2 = val;
else
{
tvga->newctrl2 = val;
svga_recalctimings(svga);
}
break;
case 0xE:
if (tvga->oldmode)
tvga->oldctrl1 = val;
else
{
svga->seqregs[0xe] = val ^ 2;
tvga->tvga_3d8 = svga->seqregs[0xe] & 0xf;
tvga_recalcbanking(tvga);
}
return;
}
break;
case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
if (tvga->card_id != TVGA9000B_ID) {
tkd8001_ramdac_out(addr, val, svga->ramdac, svga);
return;
}
break;
case 0x3CF:
switch (svga->gdcaddr & 15)
{
case 0x6:
old = svga->gdcreg[6];
svga_out(addr, val, svga);
if ((old & 0xc) != 0 && (val & 0xc) == 0)
{
/*override mask - TVGA supports linear 128k at A0000*/
svga->banked_mask = 0x1ffff;
}
return;
case 0xE:
svga->gdcreg[0xe] = val ^ 2;
tvga->tvga_3d9 = svga->gdcreg[0xe] & 0xf;
tvga_recalcbanking(tvga);
break;
case 0xF:
svga->gdcreg[0xf] = val;
tvga_recalcbanking(tvga);
break;
}
break;
case 0x3D4:
svga->crtcreg = val & 0x3f;
return;
case 0x3D5:
if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80))
return;
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
old = svga->crtc[svga->crtcreg];
val &= crtc_mask[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
if (old != val) {
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
{
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
}
}
}
switch (svga->crtcreg) {
case 0x1e:
svga->vram_display_mask = (val & 0x80) ? tvga->vram_mask : 0x3ffff;
break;
}
return;
case 0x3D8:
if (svga->gdcreg[0xf] & 4) {
tvga->tvga_3d8 = val;
tvga_recalcbanking(tvga);
}
return;
case 0x3D9:
if (svga->gdcreg[0xf] & 4) {
tvga->tvga_3d9 = val;
tvga_recalcbanking(tvga);
}
return;
case 0x3DB:
if (tvga->card_id != TVGA9000B_ID) {
/*3db appears to be a 4 bit clock select register on 8900D*/
svga->miscout = (svga->miscout & ~0x0c) | ((val & 3) << 2);
tvga->newctrl2 = (tvga->newctrl2 & ~0x01) | ((val & 4) >> 2);
tvga->oldctrl1 = (tvga->oldctrl1 & ~0x10) | ((val & 8) << 1);
switch (addr) {
case 0x3C5:
switch (svga->seqaddr & 0xf) {
case 0xB:
tvga->oldmode = 1;
break;
case 0xC:
if (svga->seqregs[0xe] & 0x80)
svga->seqregs[0xc] = val;
break;
case 0xd:
if (tvga->oldmode)
tvga->oldctrl2 = val;
else {
tvga->newctrl2 = val;
svga_recalctimings(svga);
}
break;
case 0xE:
if (tvga->oldmode)
tvga->oldctrl1 = val;
else {
svga->seqregs[0xe] = val ^ 2;
tvga->tvga_3d8 = svga->seqregs[0xe] & 0xf;
tvga_recalcbanking(tvga);
}
return;
}
break;
case 0x3C6:
case 0x3C7:
case 0x3C8:
case 0x3C9:
if (tvga->card_id != TVGA9000B_ID) {
tkd8001_ramdac_out(addr, val, svga->ramdac, svga);
return;
}
break;
case 0x3CF:
switch (svga->gdcaddr & 15) {
case 0x6:
old = svga->gdcreg[6];
svga_out(addr, val, svga);
if ((old & 0xc) != 0 && (val & 0xc) == 0) {
/*override mask - TVGA supports linear 128k at A0000*/
svga->banked_mask = 0x1ffff;
}
return;
case 0xE:
svga->gdcreg[0xe] = val ^ 2;
tvga->tvga_3d9 = svga->gdcreg[0xe] & 0xf;
tvga_recalcbanking(tvga);
break;
case 0xF:
svga->gdcreg[0xf] = val;
tvga_recalcbanking(tvga);
break;
}
break;
case 0x3D4:
svga->crtcreg = val & 0x3f;
return;
case 0x3D5:
if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80))
return;
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
old = svga->crtc[svga->crtcreg];
val &= crtc_mask[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
if (old != val) {
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
}
}
break;
}
svga_out(addr, val, svga);
}
switch (svga->crtcreg) {
case 0x1e:
svga->vram_display_mask = (val & 0x80) ? tvga->vram_mask : 0x3ffff;
break;
}
return;
case 0x3D8:
if (svga->gdcreg[0xf] & 4) {
tvga->tvga_3d8 = val;
tvga_recalcbanking(tvga);
}
return;
case 0x3D9:
if (svga->gdcreg[0xf] & 4) {
tvga->tvga_3d9 = val;
tvga_recalcbanking(tvga);
}
return;
case 0x3DB:
if (tvga->card_id != TVGA9000B_ID) {
/*3db appears to be a 4 bit clock select register on 8900D*/
svga->miscout = (svga->miscout & ~0x0c) | ((val & 3) << 2);
tvga->newctrl2 = (tvga->newctrl2 & ~0x01) | ((val & 4) >> 2);
tvga->oldctrl1 = (tvga->oldctrl1 & ~0x10) | ((val & 8) << 1);
svga_recalctimings(svga);
}
break;
}
svga_out(addr, val, svga);
}
uint8_t tvga_in(uint16_t addr, void *p)
uint8_t
tvga_in(uint16_t addr, void *p)
{
tvga_t *tvga = (tvga_t *)p;
svga_t *svga = &tvga->svga;
tvga_t *tvga = (tvga_t *) p;
svga_t *svga = &tvga->svga;
if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1)) addr ^= 0x60;
if (((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && !(svga->miscout & 1))
addr ^= 0x60;
switch (addr)
{
case 0x3C5:
if ((svga->seqaddr & 0xf) == 0xb)
{
tvga->oldmode = 0;
return tvga->card_id; /*Must be at least a TVGA8900*/
}
if ((svga->seqaddr & 0xf) == 0xd)
{
if (tvga->oldmode) return tvga->oldctrl2;
return tvga->newctrl2;
}
if ((svga->seqaddr & 0xf) == 0xe)
{
if (tvga->oldmode)
return tvga->oldctrl1;
}
break;
case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
if (tvga->card_id != TVGA9000B_ID) {
return tkd8001_ramdac_in(addr, svga->ramdac, svga);
}
break;
case 0x3D4:
return svga->crtcreg;
case 0x3D5:
if (svga->crtcreg > 0x18 && svga->crtcreg < 0x1e)
return 0xff;
return svga->crtc[svga->crtcreg];
case 0x3d8:
return tvga->tvga_3d8;
case 0x3d9:
return tvga->tvga_3d9;
}
return svga_in(addr, svga);
switch (addr) {
case 0x3C5:
if ((svga->seqaddr & 0xf) == 0xb) {
tvga->oldmode = 0;
return tvga->card_id; /*Must be at least a TVGA8900*/
}
if ((svga->seqaddr & 0xf) == 0xd) {
if (tvga->oldmode)
return tvga->oldctrl2;
return tvga->newctrl2;
}
if ((svga->seqaddr & 0xf) == 0xe) {
if (tvga->oldmode)
return tvga->oldctrl1;
}
break;
case 0x3C6:
case 0x3C7:
case 0x3C8:
case 0x3C9:
if (tvga->card_id != TVGA9000B_ID) {
return tkd8001_ramdac_in(addr, svga->ramdac, svga);
}
break;
case 0x3D4:
return svga->crtcreg;
case 0x3D5:
if (svga->crtcreg > 0x18 && svga->crtcreg < 0x1e)
return 0xff;
return svga->crtc[svga->crtcreg];
case 0x3d8:
return tvga->tvga_3d8;
case 0x3d9:
return tvga->tvga_3d9;
}
return svga_in(addr, svga);
}
static void tvga_recalcbanking(tvga_t *tvga)
static void
tvga_recalcbanking(tvga_t *tvga)
{
svga_t *svga = &tvga->svga;
svga_t *svga = &tvga->svga;
svga->write_bank = (tvga->tvga_3d8 & 0x1f) * 65536;
svga->write_bank = (tvga->tvga_3d8 & 0x1f) * 65536;
if (svga->gdcreg[0xf] & 1)
svga->read_bank = (tvga->tvga_3d9 & 0x1f) * 65536;
else
svga->read_bank = svga->write_bank;
if (svga->gdcreg[0xf] & 1)
svga->read_bank = (tvga->tvga_3d9 & 0x1f) * 65536;
else
svga->read_bank = svga->write_bank;
}
void tvga_recalctimings(svga_t *svga)
void
tvga_recalctimings(svga_t *svga)
{
tvga_t *tvga = (tvga_t *)svga->p;
int clksel;
int high_res_256 = 0;
tvga_t *tvga = (tvga_t *) svga->p;
int clksel;
int high_res_256 = 0;
if (!svga->rowoffset) svga->rowoffset = 0x100; /*This is the only sensible way I can see this being handled,
given that TVGA8900D has no overflow bits.
Some sort of overflow is required for 320x200x24 and 1024x768x16*/
if (svga->crtc[0x29] & 0x10)
svga->rowoffset += 0x100;
if (!svga->rowoffset)
svga->rowoffset = 0x100; /*This is the only sensible way I can see this being handled,
given that TVGA8900D has no overflow bits.
Some sort of overflow is required for 320x200x24 and 1024x768x16*/
if (svga->crtc[0x29] & 0x10)
svga->rowoffset += 0x100;
if (svga->bpp == 24)
svga->hdisp = (svga->crtc[1] + 1) * 8;
if (svga->bpp == 24)
svga->hdisp = (svga->crtc[1] + 1) * 8;
if ((svga->crtc[0x1e] & 0xA0) == 0xA0) svga->ma_latch |= 0x10000;
if ((svga->crtc[0x27] & 0x01) == 0x01) svga->ma_latch |= 0x20000;
if ((svga->crtc[0x27] & 0x02) == 0x02) svga->ma_latch |= 0x40000;
if ((svga->crtc[0x1e] & 0xA0) == 0xA0)
svga->ma_latch |= 0x10000;
if ((svga->crtc[0x27] & 0x01) == 0x01)
svga->ma_latch |= 0x20000;
if ((svga->crtc[0x27] & 0x02) == 0x02)
svga->ma_latch |= 0x40000;
if (tvga->oldctrl2 & 0x10)
{
svga->rowoffset <<= 1;
svga->ma_latch <<= 1;
}
if (tvga->oldctrl2 & 0x10) {
svga->rowoffset <<= 1;
svga->ma_latch <<= 1;
}
if (svga->gdcreg[0xf] & 0x08)
{
svga->htotal *= 2;
svga->hdisp *= 2;
svga->hdisp_time *= 2;
}
if (svga->gdcreg[0xf] & 0x08) {
svga->htotal *= 2;
svga->hdisp *= 2;
svga->hdisp_time *= 2;
}
svga->interlace = (svga->crtc[0x1e] & 4);
svga->interlace = (svga->crtc[0x1e] & 4);
if (svga->interlace)
svga->rowoffset >>= 1;
if (tvga->card_id == TVGA8900CLD_ID)
clksel = ((svga->miscout >> 2) & 3) | ((tvga->newctrl2 & 0x01) << 2) | ((tvga->oldctrl1 & 0x10) >> 1);
else
clksel = ((svga->miscout >> 2) & 3) | ((tvga->newctrl2 & 0x01) << 2) | ((tvga->newctrl2 & 0x40) >> 3);
switch (clksel) {
case 0x2:
svga->clock = (cpuclock * (double) (1ull << 32)) / 44900000.0;
break;
case 0x3:
svga->clock = (cpuclock * (double) (1ull << 32)) / 36000000.0;
break;
case 0x4:
svga->clock = (cpuclock * (double) (1ull << 32)) / 57272000.0;
break;
case 0x5:
svga->clock = (cpuclock * (double) (1ull << 32)) / 65000000.0;
break;
case 0x6:
svga->clock = (cpuclock * (double) (1ull << 32)) / 50350000.0;
break;
case 0x7:
svga->clock = (cpuclock * (double) (1ull << 32)) / 40000000.0;
break;
case 0x8:
svga->clock = (cpuclock * (double) (1ull << 32)) / 88000000.0;
break;
case 0x9:
svga->clock = (cpuclock * (double) (1ull << 32)) / 98000000.0;
break;
case 0xa:
svga->clock = (cpuclock * (double) (1ull << 32)) / 118800000.0;
break;
case 0xb:
svga->clock = (cpuclock * (double) (1ull << 32)) / 108000000.0;
break;
case 0xc:
svga->clock = (cpuclock * (double) (1ull << 32)) / 72000000.0;
break;
case 0xd:
svga->clock = (cpuclock * (double) (1ull << 32)) / 77000000.0;
break;
case 0xe:
svga->clock = (cpuclock * (double) (1ull << 32)) / 80000000.0;
break;
case 0xf:
svga->clock = (cpuclock * (double) (1ull << 32)) / 75000000.0;
break;
}
if (tvga->card_id != TVGA8900CLD_ID) {
/*TVGA9000 doesn't seem to have support for a 'high res' 256 colour mode
(without the VGA pixel doubling). Instead it implements these modes by
doubling the horizontal pixel count and pixel clock. Hence we use a
basic heuristic to detect this*/
if (svga->interlace)
svga->rowoffset >>= 1;
high_res_256 = (svga->htotal * 8) > (svga->vtotal * 4);
else
high_res_256 = (svga->htotal * 8) > (svga->vtotal * 2);
}
if (tvga->card_id == TVGA8900CLD_ID)
clksel = ((svga->miscout >> 2) & 3) | ((tvga->newctrl2 & 0x01) << 2) | ((tvga->oldctrl1 & 0x10) >> 1);
else
clksel = ((svga->miscout >> 2) & 3) | ((tvga->newctrl2 & 0x01) << 2) | ((tvga->newctrl2 & 0x40) >> 3);
switch (clksel) {
case 0x2: svga->clock = (cpuclock * (double)(1ull << 32)) / 44900000.0; break;
case 0x3: svga->clock = (cpuclock * (double)(1ull << 32)) / 36000000.0; break;
case 0x4: svga->clock = (cpuclock * (double)(1ull << 32)) / 57272000.0; break;
case 0x5: svga->clock = (cpuclock * (double)(1ull << 32)) / 65000000.0; break;
case 0x6: svga->clock = (cpuclock * (double)(1ull << 32)) / 50350000.0; break;
case 0x7: svga->clock = (cpuclock * (double)(1ull << 32)) / 40000000.0; break;
case 0x8: svga->clock = (cpuclock * (double)(1ull << 32)) / 88000000.0; break;
case 0x9: svga->clock = (cpuclock * (double)(1ull << 32)) / 98000000.0; break;
case 0xa: svga->clock = (cpuclock * (double)(1ull << 32)) / 118800000.0; break;
case 0xb: svga->clock = (cpuclock * (double)(1ull << 32)) / 108000000.0; break;
case 0xc: svga->clock = (cpuclock * (double)(1ull << 32)) / 72000000.0; break;
case 0xd: svga->clock = (cpuclock * (double)(1ull << 32)) / 77000000.0; break;
case 0xe: svga->clock = (cpuclock * (double)(1ull << 32)) / 80000000.0; break;
case 0xf: svga->clock = (cpuclock * (double)(1ull << 32)) / 75000000.0; break;
}
if (tvga->card_id != TVGA8900CLD_ID) {
/*TVGA9000 doesn't seem to have support for a 'high res' 256 colour mode
(without the VGA pixel doubling). Instead it implements these modes by
doubling the horizontal pixel count and pixel clock. Hence we use a
basic heuristic to detect this*/
if (svga->interlace)
high_res_256 = (svga->htotal * 8) > (svga->vtotal * 4);
else
high_res_256 = (svga->htotal * 8) > (svga->vtotal * 2);
}
if ((tvga->oldctrl2 & 0x10) || high_res_256)
{
if (high_res_256)
svga->hdisp /= 2;
switch (svga->bpp)
{
case 8:
svga->render = svga_render_8bpp_highres;
break;
case 15:
svga->render = svga_render_15bpp_highres;
svga->hdisp /= 2;
break;
case 16:
svga->render = svga_render_16bpp_highres;
svga->hdisp /= 2;
break;
case 24:
svga->render = svga_render_24bpp_highres;
svga->hdisp /= 3;
break;
}
svga->lowres = 0;
if ((tvga->oldctrl2 & 0x10) || high_res_256) {
if (high_res_256)
svga->hdisp /= 2;
switch (svga->bpp) {
case 8:
svga->render = svga_render_8bpp_highres;
break;
case 15:
svga->render = svga_render_15bpp_highres;
svga->hdisp /= 2;
break;
case 16:
svga->render = svga_render_16bpp_highres;
svga->hdisp /= 2;
break;
case 24:
svga->render = svga_render_24bpp_highres;
svga->hdisp /= 3;
break;
}
svga->lowres = 0;
}
}
static void *tvga_init(const device_t *info)
static void *
tvga_init(const device_t *info)
{
const char *bios_fn;
tvga_t *tvga = malloc(sizeof(tvga_t));
memset(tvga, 0, sizeof(tvga_t));
const char *bios_fn;
tvga_t *tvga = malloc(sizeof(tvga_t));
memset(tvga, 0, sizeof(tvga_t));
if (info->local == TVGA9000B_ID) {
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_tvga9000);
tvga->vram_size = 512 << 10;
} else {
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_tvga8900);
tvga->vram_size = device_get_config_int("memory") << 10;
}
if (info->local == TVGA9000B_ID) {
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_tvga9000);
tvga->vram_size = 512 << 10;
} else {
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_tvga8900);
tvga->vram_size = device_get_config_int("memory") << 10;
}
tvga->vram_mask = tvga->vram_size - 1;
tvga->vram_mask = tvga->vram_size - 1;
tvga->card_id = info->local;
tvga->card_id = info->local;
switch (info->local)
{
case TVGA8900B_ID:
bios_fn = ROM_TVGA_8900B;
break;
case TVGA8900CLD_ID:
bios_fn = ROM_TVGA_8900CLD;
break;
case TVGA9000B_ID:
bios_fn = ROM_TVGA_9000B;
break;
default:
free(tvga);
return NULL;
}
switch (info->local) {
case TVGA8900B_ID:
bios_fn = ROM_TVGA_8900B;
break;
case TVGA8900CLD_ID:
bios_fn = ROM_TVGA_8900CLD;
break;
case TVGA9000B_ID:
bios_fn = ROM_TVGA_9000B;
break;
default:
free(tvga);
return NULL;
}
rom_init(&tvga->bios_rom, (char *) bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
rom_init(&tvga->bios_rom, (char *) bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
svga_init(info, &tvga->svga, tvga, tvga->vram_size,
tvga_recalctimings,
tvga_in, tvga_out,
NULL,
NULL);
svga_init(info, &tvga->svga, tvga, tvga->vram_size,
tvga_recalctimings,
tvga_in, tvga_out,
NULL,
NULL);
if (info->local != TVGA9000B_ID)
tvga->svga.ramdac = device_add(&tkd8001_ramdac_device);
if (info->local != TVGA9000B_ID)
tvga->svga.ramdac = device_add(&tkd8001_ramdac_device);
io_sethandler(0x03c0, 0x0020, tvga_in, NULL, NULL, tvga_out, NULL, NULL, tvga);
io_sethandler(0x03c0, 0x0020, tvga_in, NULL, NULL, tvga_out, NULL, NULL, tvga);
return tvga;
return tvga;
}
static int tvga8900b_available(void)
static int
tvga8900b_available(void)
{
return rom_present(ROM_TVGA_8900B);
return rom_present(ROM_TVGA_8900B);
}
static int tvga8900d_available(void)
static int
tvga8900d_available(void)
{
return rom_present(ROM_TVGA_8900CLD);
return rom_present(ROM_TVGA_8900CLD);
}
static int tvga9000b_available(void)
static int
tvga9000b_available(void)
{
return rom_present(ROM_TVGA_9000B);
return rom_present(ROM_TVGA_9000B);
}
void tvga_close(void *p)
void
tvga_close(void *p)
{
tvga_t *tvga = (tvga_t *)p;
tvga_t *tvga = (tvga_t *) p;
svga_close(&tvga->svga);
svga_close(&tvga->svga);
free(tvga);
free(tvga);
}
void tvga_speed_changed(void *p)
void
tvga_speed_changed(void *p)
{
tvga_t *tvga = (tvga_t *)p;
tvga_t *tvga = (tvga_t *) p;
svga_recalctimings(&tvga->svga);
svga_recalctimings(&tvga->svga);
}
void tvga_force_redraw(void *p)
void
tvga_force_redraw(void *p)
{
tvga_t *tvga = (tvga_t *)p;
tvga_t *tvga = (tvga_t *) p;
tvga->svga.fullchange = changeframecount;
tvga->svga.fullchange = changeframecount;
}
static const device_config_t tvga_config[] = {
// clang-format off
// clang-format off
{
.name = "memory",
.description = "Memory size",

File diff suppressed because it is too large Load Diff

View File

@@ -31,194 +31,195 @@
#include <86box/vid_svga.h>
#include <86box/vid_vga.h>
static video_timings_t timing_ps1_svga_isa = { .type = VIDEO_ISA, .write_b = 6, .write_w = 8, .write_l = 16, .read_b = 6, .read_w = 8, .read_l = 16 };
static video_timings_t timing_ps1_svga_mca = { .type = VIDEO_MCA, .write_b = 6, .write_w = 8, .write_l = 16, .read_b = 6, .read_w = 8, .read_l = 16 };
static video_timings_t timing_ps1_svga_isa = {VIDEO_ISA, 6, 8, 16, 6, 8, 16};
static video_timings_t timing_ps1_svga_mca = {VIDEO_MCA, 6, 8, 16, 6, 8, 16};
void vga_out(uint16_t addr, uint8_t val, void *p)
void
vga_out(uint16_t addr, uint8_t val, void *p)
{
vga_t *vga = (vga_t *)p;
svga_t *svga = &vga->svga;
uint8_t old;
vga_t *vga = (vga_t *) p;
svga_t *svga = &vga->svga;
uint8_t old;
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
switch (addr)
{
case 0x3D4:
svga->crtcreg = val & 0x3f;
switch (addr) {
case 0x3D4:
svga->crtcreg = val & 0x3f;
return;
case 0x3D5:
if (svga->crtcreg & 0x20)
return;
case 0x3D5:
if (svga->crtcreg & 0x20)
return;
if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80))
return;
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
old = svga->crtc[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
if (old != val)
{
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
{
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
}
}
if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80))
return;
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
old = svga->crtc[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
if (old != val) {
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
}
}
break;
}
svga_out(addr, val, svga);
}
break;
}
svga_out(addr, val, svga);
}
uint8_t vga_in(uint16_t addr, void *p)
uint8_t
vga_in(uint16_t addr, void *p)
{
vga_t *vga = (vga_t *)p;
svga_t *svga = &vga->svga;
uint8_t temp;
vga_t *vga = (vga_t *) p;
svga_t *svga = &vga->svga;
uint8_t temp;
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
switch (addr)
{
case 0x3D4:
temp = svga->crtcreg;
break;
case 0x3D5:
if (svga->crtcreg & 0x20)
temp = 0xff;
else
temp = svga->crtc[svga->crtcreg];
break;
default:
temp = svga_in(addr, svga);
break;
}
return temp;
switch (addr) {
case 0x3D4:
temp = svga->crtcreg;
break;
case 0x3D5:
if (svga->crtcreg & 0x20)
temp = 0xff;
else
temp = svga->crtc[svga->crtcreg];
break;
default:
temp = svga_in(addr, svga);
break;
}
return temp;
}
static void *vga_init(const device_t *info)
static void *
vga_init(const device_t *info)
{
vga_t *vga = malloc(sizeof(vga_t));
memset(vga, 0, sizeof(vga_t));
vga_t *vga = malloc(sizeof(vga_t));
memset(vga, 0, sizeof(vga_t));
rom_init(&vga->bios_rom, "roms/video/vga/ibm_vga.bin", 0xc0000, 0x8000, 0x7fff, 0x2000, MEM_MAPPING_EXTERNAL);
rom_init(&vga->bios_rom, "roms/video/vga/ibm_vga.bin", 0xc0000, 0x8000, 0x7fff, 0x2000, MEM_MAPPING_EXTERNAL);
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_vga);
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_vga);
svga_init(info, &vga->svga, vga, 1 << 18, /*256kb*/
NULL,
vga_in, vga_out,
NULL,
NULL);
svga_init(info, &vga->svga, vga, 1 << 18, /*256kb*/
NULL,
vga_in, vga_out,
NULL,
NULL);
io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga);
io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga);
vga->svga.bpp = 8;
vga->svga.miscout = 1;
vga->svga.bpp = 8;
vga->svga.miscout = 1;
return vga;
return vga;
}
/*PS/1 uses a standard VGA controller, but with no option ROM*/
void *ps1vga_init(const device_t *info)
void *
ps1vga_init(const device_t *info)
{
vga_t *vga = malloc(sizeof(vga_t));
memset(vga, 0, sizeof(vga_t));
vga_t *vga = malloc(sizeof(vga_t));
memset(vga, 0, sizeof(vga_t));
if (info->flags & DEVICE_MCA)
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ps1_svga_mca);
else
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ps1_svga_isa);
if (info->flags & DEVICE_MCA)
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ps1_svga_mca);
else
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ps1_svga_isa);
svga_init(info, &vga->svga, vga, 1 << 18, /*256kb*/
NULL,
vga_in, vga_out,
NULL,
NULL);
svga_init(info, &vga->svga, vga, 1 << 18, /*256kb*/
NULL,
vga_in, vga_out,
NULL,
NULL);
io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga);
io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga);
vga->svga.bpp = 8;
vga->svga.miscout = 1;
vga->svga.bpp = 8;
vga->svga.miscout = 1;
return vga;
return vga;
}
static int vga_available(void)
static int
vga_available(void)
{
return rom_present("roms/video/vga/ibm_vga.bin");
return rom_present("roms/video/vga/ibm_vga.bin");
}
void vga_close(void *p)
void
vga_close(void *p)
{
vga_t *vga = (vga_t *)p;
vga_t *vga = (vga_t *) p;
svga_close(&vga->svga);
svga_close(&vga->svga);
free(vga);
free(vga);
}
void vga_speed_changed(void *p)
void
vga_speed_changed(void *p)
{
vga_t *vga = (vga_t *)p;
vga_t *vga = (vga_t *) p;
svga_recalctimings(&vga->svga);
svga_recalctimings(&vga->svga);
}
void vga_force_redraw(void *p)
void
vga_force_redraw(void *p)
{
vga_t *vga = (vga_t *)p;
vga_t *vga = (vga_t *) p;
vga->svga.fullchange = changeframecount;
vga->svga.fullchange = changeframecount;
}
const device_t vga_device = {
.name = "VGA",
.name = "VGA",
.internal_name = "vga",
.flags = DEVICE_ISA,
.local = 0,
.init = vga_init,
.close = vga_close,
.reset = NULL,
.flags = DEVICE_ISA,
.local = 0,
.init = vga_init,
.close = vga_close,
.reset = NULL,
{ .available = vga_available },
.speed_changed = vga_speed_changed,
.force_redraw = vga_force_redraw,
.config = NULL
.force_redraw = vga_force_redraw,
.config = NULL
};
const device_t ps1vga_device = {
.name = "PS/1 VGA",
.name = "PS/1 VGA",
.internal_name = "ps1vga",
.flags = DEVICE_ISA,
.local = 0,
.init = ps1vga_init,
.close = vga_close,
.reset = NULL,
.flags = DEVICE_ISA,
.local = 0,
.init = ps1vga_init,
.close = vga_close,
.reset = NULL,
{ .available = vga_available },
.speed_changed = vga_speed_changed,
.force_redraw = vga_force_redraw,
.config = NULL
.force_redraw = vga_force_redraw,
.config = NULL
};
const device_t ps1vga_mca_device = {
.name = "PS/1 VGA",
.name = "PS/1 VGA",
.internal_name = "ps1vga_mca",
.flags = DEVICE_MCA,
.local = 0,
.init = ps1vga_init,
.close = vga_close,
.reset = NULL,
.flags = DEVICE_MCA,
.local = 0,
.init = ps1vga_init,
.close = vga_close,
.reset = NULL,
{ .available = vga_available },
.speed_changed = vga_speed_changed,
.force_redraw = vga_force_redraw,
.config = NULL
.force_redraw = vga_force_redraw,
.config = NULL
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -39,519 +39,479 @@
#include <86box/vid_voodoo_regs.h>
#include <86box/vid_voodoo_render.h>
enum
{
BLIT_COMMAND_SCREEN_TO_SCREEN = 0,
BLIT_COMMAND_CPU_TO_SCREEN = 1,
BLIT_COMMAND_RECT_FILL = 2,
BLIT_COMMAND_SGRAM_FILL = 3
enum {
BLIT_COMMAND_SCREEN_TO_SCREEN = 0,
BLIT_COMMAND_CPU_TO_SCREEN = 1,
BLIT_COMMAND_RECT_FILL = 2,
BLIT_COMMAND_SGRAM_FILL = 3
};
enum
{
BLIT_SRC_1BPP = (0 << 3),
BLIT_SRC_1BPP_BYTE_PACKED = (1 << 3),
BLIT_SRC_16BPP = (2 << 3),
BLIT_SRC_24BPP = (3 << 3),
BLIT_SRC_24BPP_DITHER_2X2 = (4 << 3),
BLIT_SRC_24BPP_DITHER_4X4 = (5 << 3)
enum {
BLIT_SRC_1BPP = (0 << 3),
BLIT_SRC_1BPP_BYTE_PACKED = (1 << 3),
BLIT_SRC_16BPP = (2 << 3),
BLIT_SRC_24BPP = (3 << 3),
BLIT_SRC_24BPP_DITHER_2X2 = (4 << 3),
BLIT_SRC_24BPP_DITHER_4X4 = (5 << 3)
};
enum
{
BLIT_SRC_RGB_ARGB = (0 << 6),
BLIT_SRC_RGB_ABGR = (1 << 6),
BLIT_SRC_RGB_RGBA = (2 << 6),
BLIT_SRC_RGB_BGRA = (3 << 6)
enum {
BLIT_SRC_RGB_ARGB = (0 << 6),
BLIT_SRC_RGB_ABGR = (1 << 6),
BLIT_SRC_RGB_RGBA = (2 << 6),
BLIT_SRC_RGB_BGRA = (3 << 6)
};
enum
{
BLIT_COMMAND_MASK = 7,
BLIT_SRC_FORMAT = (7 << 3),
BLIT_SRC_RGB_FORMAT = (3 << 6),
BLIT_SRC_CHROMA = (1 << 10),
BLIT_DST_CHROMA = (1 << 12),
BLIT_CLIPPING_ENABLED = (1 << 16)
enum {
BLIT_COMMAND_MASK = 7,
BLIT_SRC_FORMAT = (7 << 3),
BLIT_SRC_RGB_FORMAT = (3 << 6),
BLIT_SRC_CHROMA = (1 << 10),
BLIT_DST_CHROMA = (1 << 12),
BLIT_CLIPPING_ENABLED = (1 << 16)
};
enum
{
BLIT_ROP_DST_PASS = (1 << 0),
BLIT_ROP_SRC_PASS = (1 << 1)
enum {
BLIT_ROP_DST_PASS = (1 << 0),
BLIT_ROP_SRC_PASS = (1 << 1)
};
#ifdef ENABLE_VOODOOBLT_LOG
int voodooblt_do_log = ENABLE_VOODOOBLT_LOG;
static void
voodooblt_log(const char *fmt, ...)
{
va_list ap;
if (voodooblt_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define voodooblt_log(fmt, ...)
# define voodooblt_log(fmt, ...)
#endif
#define MIX(src_dat, dst_dat, rop) \
switch (rop) { \
case 0x0: \
dst_dat = 0; \
break; \
case 0x1: \
dst_dat = ~(src_dat | dst_dat); \
break; \
case 0x2: \
dst_dat = ~src_dat & dst_dat; \
break; \
case 0x3: \
dst_dat = ~src_dat; \
break; \
case 0x4: \
dst_dat = src_dat & ~dst_dat; \
break; \
case 0x5: \
dst_dat = ~dst_dat; \
break; \
case 0x6: \
dst_dat = src_dat ^ dst_dat; \
break; \
case 0x7: \
dst_dat = ~(src_dat & dst_dat); \
break; \
case 0x8: \
dst_dat = src_dat & dst_dat; \
break; \
case 0x9: \
dst_dat = ~(src_dat ^ dst_dat); \
break; \
case 0xa: \
dst_dat = dst_dat; \
break; \
case 0xb: \
dst_dat = ~src_dat | dst_dat; \
break; \
case 0xc: \
dst_dat = src_dat; \
break; \
case 0xd: \
dst_dat = src_dat | ~dst_dat; \
break; \
case 0xe: \
dst_dat = src_dat | dst_dat; \
break; \
case 0xf: \
dst_dat = 0xffff; \
break; \
}
#define MIX(src_dat, dst_dat, rop) \
switch (rop) \
{ \
case 0x0: dst_dat = 0; break; \
case 0x1: dst_dat = ~(src_dat | dst_dat); break; \
case 0x2: dst_dat = ~src_dat & dst_dat; break; \
case 0x3: dst_dat = ~src_dat; break; \
case 0x4: dst_dat = src_dat & ~dst_dat; break; \
case 0x5: dst_dat = ~dst_dat; break; \
case 0x6: dst_dat = src_dat ^ dst_dat; break; \
case 0x7: dst_dat = ~(src_dat & dst_dat); break; \
case 0x8: dst_dat = src_dat & dst_dat; break; \
case 0x9: dst_dat = ~(src_dat ^ dst_dat); break; \
case 0xa: dst_dat = dst_dat; break; \
case 0xb: dst_dat = ~src_dat | dst_dat; break; \
case 0xc: dst_dat = src_dat; break; \
case 0xd: dst_dat = src_dat | ~dst_dat; break; \
case 0xe: dst_dat = src_dat | dst_dat; break; \
case 0xf: dst_dat = 0xffff; break; \
}
void voodoo_v2_blit_start(voodoo_t *voodoo)
void
voodoo_v2_blit_start(voodoo_t *voodoo)
{
uint64_t dat64;
int size_x = ABS(voodoo->bltSizeX), size_y = ABS(voodoo->bltSizeY);
int x_dir = (voodoo->bltSizeX > 0) ? 1 : -1;
int y_dir = (voodoo->bltSizeY > 0) ? 1 : -1;
int dst_x;
int src_y = voodoo->bltSrcY & 0x7ff, dst_y = voodoo->bltDstY & 0x7ff;
int src_stride = (voodoo->bltCommand & BLTCMD_SRC_TILED) ? ((voodoo->bltSrcXYStride & 0x3f) * 32*2) : (voodoo->bltSrcXYStride & 0xff8);
int dst_stride = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstXYStride & 0x3f) * 32*2) : (voodoo->bltDstXYStride & 0xff8);
uint32_t src_base_addr = (voodoo->bltCommand & BLTCMD_SRC_TILED) ? ((voodoo->bltSrcBaseAddr & 0x3ff) << 12) : (voodoo->bltSrcBaseAddr & 0x3ffff8);
uint32_t dst_base_addr = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstBaseAddr & 0x3ff) << 12) : (voodoo->bltDstBaseAddr & 0x3ffff8);
int x, y;
uint64_t dat64;
int size_x = ABS(voodoo->bltSizeX), size_y = ABS(voodoo->bltSizeY);
int x_dir = (voodoo->bltSizeX > 0) ? 1 : -1;
int y_dir = (voodoo->bltSizeY > 0) ? 1 : -1;
int dst_x;
int src_y = voodoo->bltSrcY & 0x7ff, dst_y = voodoo->bltDstY & 0x7ff;
int src_stride = (voodoo->bltCommand & BLTCMD_SRC_TILED) ? ((voodoo->bltSrcXYStride & 0x3f) * 32 * 2) : (voodoo->bltSrcXYStride & 0xff8);
int dst_stride = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstXYStride & 0x3f) * 32 * 2) : (voodoo->bltDstXYStride & 0xff8);
uint32_t src_base_addr = (voodoo->bltCommand & BLTCMD_SRC_TILED) ? ((voodoo->bltSrcBaseAddr & 0x3ff) << 12) : (voodoo->bltSrcBaseAddr & 0x3ffff8);
uint32_t dst_base_addr = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstBaseAddr & 0x3ff) << 12) : (voodoo->bltDstBaseAddr & 0x3ffff8);
int x, y;
/* voodooblt_log("blit_start: command=%08x srcX=%i srcY=%i dstX=%i dstY=%i sizeX=%i sizeY=%i color=%04x,%04x\n",
voodoo->bltCommand, voodoo->bltSrcX, voodoo->bltSrcY, voodoo->bltDstX, voodoo->bltDstY, voodoo->bltSizeX, voodoo->bltSizeY, voodoo->bltColorFg, voodoo->bltColorBg);*/
/* voodooblt_log("blit_start: command=%08x srcX=%i srcY=%i dstX=%i dstY=%i sizeX=%i sizeY=%i color=%04x,%04x\n",
voodoo->bltCommand, voodoo->bltSrcX, voodoo->bltSrcY, voodoo->bltDstX, voodoo->bltDstY, voodoo->bltSizeX, voodoo->bltSizeY, voodoo->bltColorFg, voodoo->bltColorBg);*/
voodoo_wait_for_render_thread_idle(voodoo);
voodoo_wait_for_render_thread_idle(voodoo);
switch (voodoo->bltCommand & BLIT_COMMAND_MASK)
{
case BLIT_COMMAND_SCREEN_TO_SCREEN:
for (y = 0; y <= size_y; y++)
{
uint16_t *src = (uint16_t *)&voodoo->fb_mem[src_base_addr + src_y*src_stride];
uint16_t *dst = (uint16_t *)&voodoo->fb_mem[dst_base_addr + dst_y*dst_stride];
int src_x = voodoo->bltSrcX, dst_x = voodoo->bltDstX;
switch (voodoo->bltCommand & BLIT_COMMAND_MASK) {
case BLIT_COMMAND_SCREEN_TO_SCREEN:
for (y = 0; y <= size_y; y++) {
uint16_t *src = (uint16_t *) &voodoo->fb_mem[src_base_addr + src_y * src_stride];
uint16_t *dst = (uint16_t *) &voodoo->fb_mem[dst_base_addr + dst_y * dst_stride];
int src_x = voodoo->bltSrcX, dst_x = voodoo->bltDstX;
for (x = 0; x <= size_x; x++)
{
uint16_t src_dat = src[src_x];
uint16_t dst_dat = dst[dst_x];
int rop = 0;
for (x = 0; x <= size_x; x++) {
uint16_t src_dat = src[src_x];
uint16_t dst_dat = dst[dst_x];
int rop = 0;
if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED)
{
if (dst_x < voodoo->bltClipLeft || dst_x >= voodoo->bltClipRight ||
dst_y < voodoo->bltClipLowY || dst_y >= voodoo->bltClipHighY)
goto skip_pixel_blit;
}
if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED) {
if (dst_x < voodoo->bltClipLeft || dst_x >= voodoo->bltClipRight || dst_y < voodoo->bltClipLowY || dst_y >= voodoo->bltClipHighY)
goto skip_pixel_blit;
}
if (voodoo->bltCommand & BLIT_SRC_CHROMA)
{
int r = (src_dat >> 11);
int g = (src_dat >> 5) & 0x3f;
int b = src_dat & 0x1f;
if (voodoo->bltCommand & BLIT_SRC_CHROMA) {
int r = (src_dat >> 11);
int g = (src_dat >> 5) & 0x3f;
int b = src_dat & 0x1f;
if (r >= voodoo->bltSrcChromaMinR && r <= voodoo->bltSrcChromaMaxR &&
g >= voodoo->bltSrcChromaMinG && g <= voodoo->bltSrcChromaMaxG &&
b >= voodoo->bltSrcChromaMinB && b <= voodoo->bltSrcChromaMaxB)
rop |= BLIT_ROP_SRC_PASS;
}
if (voodoo->bltCommand & BLIT_DST_CHROMA)
{
int r = (dst_dat >> 11);
int g = (dst_dat >> 5) & 0x3f;
int b = dst_dat & 0x1f;
if (r >= voodoo->bltSrcChromaMinR && r <= voodoo->bltSrcChromaMaxR && g >= voodoo->bltSrcChromaMinG && g <= voodoo->bltSrcChromaMaxG && b >= voodoo->bltSrcChromaMinB && b <= voodoo->bltSrcChromaMaxB)
rop |= BLIT_ROP_SRC_PASS;
}
if (voodoo->bltCommand & BLIT_DST_CHROMA) {
int r = (dst_dat >> 11);
int g = (dst_dat >> 5) & 0x3f;
int b = dst_dat & 0x1f;
if (r >= voodoo->bltDstChromaMinR && r <= voodoo->bltDstChromaMaxR &&
g >= voodoo->bltDstChromaMinG && g <= voodoo->bltDstChromaMaxG &&
b >= voodoo->bltDstChromaMinB && b <= voodoo->bltDstChromaMaxB)
rop |= BLIT_ROP_DST_PASS;
}
if (r >= voodoo->bltDstChromaMinR && r <= voodoo->bltDstChromaMaxR && g >= voodoo->bltDstChromaMinG && g <= voodoo->bltDstChromaMaxG && b >= voodoo->bltDstChromaMinB && b <= voodoo->bltDstChromaMaxB)
rop |= BLIT_ROP_DST_PASS;
}
MIX(src_dat, dst_dat, voodoo->bltRop[rop]);
MIX(src_dat, dst_dat, voodoo->bltRop[rop]);
dst[dst_x] = dst_dat;
dst[dst_x] = dst_dat;
skip_pixel_blit:
src_x += x_dir;
dst_x += x_dir;
}
src_y += y_dir;
dst_y += y_dir;
src_x += x_dir;
dst_x += x_dir;
}
break;
case BLIT_COMMAND_CPU_TO_SCREEN:
voodoo->blt.dst_x = voodoo->bltDstX;
voodoo->blt.dst_y = voodoo->bltDstY;
voodoo->blt.cur_x = 0;
voodoo->blt.size_x = size_x;
voodoo->blt.size_y = size_y;
voodoo->blt.x_dir = x_dir;
voodoo->blt.y_dir = y_dir;
voodoo->blt.dst_stride = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstXYStride & 0x3f) * 32*2) : (voodoo->bltDstXYStride & 0xff8);
break;
src_y += y_dir;
dst_y += y_dir;
}
break;
case BLIT_COMMAND_RECT_FILL:
for (y = 0; y <= size_y; y++)
{
uint16_t *dst;
int dst_x = voodoo->bltDstX;
case BLIT_COMMAND_CPU_TO_SCREEN:
voodoo->blt.dst_x = voodoo->bltDstX;
voodoo->blt.dst_y = voodoo->bltDstY;
voodoo->blt.cur_x = 0;
voodoo->blt.size_x = size_x;
voodoo->blt.size_y = size_y;
voodoo->blt.x_dir = x_dir;
voodoo->blt.y_dir = y_dir;
voodoo->blt.dst_stride = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstXYStride & 0x3f) * 32 * 2) : (voodoo->bltDstXYStride & 0xff8);
break;
if (SLI_ENABLED)
{
if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (voodoo->blt.dst_y & 1)) ||
((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(voodoo->blt.dst_y & 1)))
goto skip_line_fill;
dst = (uint16_t *)&voodoo->fb_mem[dst_base_addr + (dst_y >> 1) * dst_stride];
}
else
dst = (uint16_t *)&voodoo->fb_mem[dst_base_addr + dst_y*dst_stride];
case BLIT_COMMAND_RECT_FILL:
for (y = 0; y <= size_y; y++) {
uint16_t *dst;
int dst_x = voodoo->bltDstX;
for (x = 0; x <= size_x; x++)
{
if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED)
{
if (dst_x < voodoo->bltClipLeft || dst_x >= voodoo->bltClipRight ||
dst_y < voodoo->bltClipLowY || dst_y >= voodoo->bltClipHighY)
goto skip_pixel_fill;
}
if (SLI_ENABLED) {
if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (voodoo->blt.dst_y & 1)) || ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(voodoo->blt.dst_y & 1)))
goto skip_line_fill;
dst = (uint16_t *) &voodoo->fb_mem[dst_base_addr + (dst_y >> 1) * dst_stride];
} else
dst = (uint16_t *) &voodoo->fb_mem[dst_base_addr + dst_y * dst_stride];
dst[dst_x] = voodoo->bltColorFg;
for (x = 0; x <= size_x; x++) {
if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED) {
if (dst_x < voodoo->bltClipLeft || dst_x >= voodoo->bltClipRight || dst_y < voodoo->bltClipLowY || dst_y >= voodoo->bltClipHighY)
goto skip_pixel_fill;
}
dst[dst_x] = voodoo->bltColorFg;
skip_pixel_fill:
dst_x += x_dir;
}
dst_x += x_dir;
}
skip_line_fill:
dst_y += y_dir;
dst_y += y_dir;
}
break;
case BLIT_COMMAND_SGRAM_FILL:
/*32x32 tiles - 2kb*/
dst_y = voodoo->bltDstY & 0x3ff;
size_x = voodoo->bltSizeX & 0x1ff; // 512*8 = 4kb
size_y = voodoo->bltSizeY & 0x3ff;
dat64 = voodoo->bltColorFg | ((uint64_t) voodoo->bltColorFg << 16) | ((uint64_t) voodoo->bltColorFg << 32) | ((uint64_t) voodoo->bltColorFg << 48);
for (y = 0; y <= size_y; y++) {
uint64_t *dst;
/*This may be wrong*/
if (!y) {
dst_x = voodoo->bltDstX & 0x1ff;
size_x = 511 - dst_x;
} else if (y < size_y) {
dst_x = 0;
size_x = 511;
} else {
dst_x = 0;
size_x = voodoo->bltSizeX & 0x1ff;
}
break;
case BLIT_COMMAND_SGRAM_FILL:
/*32x32 tiles - 2kb*/
dst_y = voodoo->bltDstY & 0x3ff;
size_x = voodoo->bltSizeX & 0x1ff; //512*8 = 4kb
size_y = voodoo->bltSizeY & 0x3ff;
dst = (uint64_t *) &voodoo->fb_mem[(dst_y * 512 * 8 + dst_x * 8) & voodoo->fb_mask];
dat64 = voodoo->bltColorFg | ((uint64_t)voodoo->bltColorFg << 16) |
((uint64_t)voodoo->bltColorFg << 32) | ((uint64_t)voodoo->bltColorFg << 48);
for (x = 0; x <= size_x; x++)
dst[x] = dat64;
for (y = 0; y <= size_y; y++)
{
uint64_t *dst;
dst_y++;
}
break;
/*This may be wrong*/
if (!y)
{
dst_x = voodoo->bltDstX & 0x1ff;
size_x = 511 - dst_x;
}
else if (y < size_y)
{
dst_x = 0;
size_x = 511;
}
else
{
dst_x = 0;
size_x = voodoo->bltSizeX & 0x1ff;
}
dst = (uint64_t *)&voodoo->fb_mem[(dst_y*512*8 + dst_x*8) & voodoo->fb_mask];
for (x = 0; x <= size_x; x++)
dst[x] = dat64;
dst_y++;
}
break;
default:
fatal("bad blit command %08x\n", voodoo->bltCommand);
}
default:
fatal("bad blit command %08x\n", voodoo->bltCommand);
}
}
void voodoo_v2_blit_data(voodoo_t *voodoo, uint32_t data)
void
voodoo_v2_blit_data(voodoo_t *voodoo, uint32_t data)
{
int src_bits = 32;
uint32_t base_addr = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstBaseAddr & 0x3ff) << 12) : (voodoo->bltDstBaseAddr & 0x3ffff8);
uint32_t addr;
uint16_t *dst;
int src_bits = 32;
uint32_t base_addr = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstBaseAddr & 0x3ff) << 12) : (voodoo->bltDstBaseAddr & 0x3ffff8);
uint32_t addr;
uint16_t *dst;
if ((voodoo->bltCommand & BLIT_COMMAND_MASK) != BLIT_COMMAND_CPU_TO_SCREEN)
return;
if ((voodoo->bltCommand & BLIT_COMMAND_MASK) != BLIT_COMMAND_CPU_TO_SCREEN)
return;
if (SLI_ENABLED)
{
addr = base_addr + (voodoo->blt.dst_y >> 1) * voodoo->blt.dst_stride;
dst = (uint16_t *)&voodoo->fb_mem[addr];
}
else
{
addr = base_addr + voodoo->blt.dst_y*voodoo->blt.dst_stride;
dst = (uint16_t *)&voodoo->fb_mem[addr];
}
if (SLI_ENABLED) {
addr = base_addr + (voodoo->blt.dst_y >> 1) * voodoo->blt.dst_stride;
dst = (uint16_t *) &voodoo->fb_mem[addr];
} else {
addr = base_addr + voodoo->blt.dst_y * voodoo->blt.dst_stride;
dst = (uint16_t *) &voodoo->fb_mem[addr];
}
if (addr >= voodoo->front_offset && voodoo->row_width)
{
int y = (addr - voodoo->front_offset) / voodoo->row_width;
if (y < voodoo->v_disp)
voodoo->dirty_line[y] = 2;
}
if (addr >= voodoo->front_offset && voodoo->row_width) {
int y = (addr - voodoo->front_offset) / voodoo->row_width;
if (y < voodoo->v_disp)
voodoo->dirty_line[y] = 2;
}
while (src_bits && voodoo->blt.cur_x <= voodoo->blt.size_x)
{
int r = 0, g = 0, b = 0;
uint16_t src_dat = 0, dst_dat;
int x = (voodoo->blt.x_dir > 0) ? (voodoo->blt.dst_x + voodoo->blt.cur_x) : (voodoo->blt.dst_x - voodoo->blt.cur_x);
int rop = 0;
while (src_bits && voodoo->blt.cur_x <= voodoo->blt.size_x) {
int r = 0, g = 0, b = 0;
uint16_t src_dat = 0, dst_dat;
int x = (voodoo->blt.x_dir > 0) ? (voodoo->blt.dst_x + voodoo->blt.cur_x) : (voodoo->blt.dst_x - voodoo->blt.cur_x);
int rop = 0;
switch (voodoo->bltCommand & BLIT_SRC_FORMAT)
{
case BLIT_SRC_1BPP: case BLIT_SRC_1BPP_BYTE_PACKED:
src_dat = (data & 1) ? voodoo->bltColorFg : voodoo->bltColorBg;
data >>= 1;
src_bits--;
switch (voodoo->bltCommand & BLIT_SRC_FORMAT) {
case BLIT_SRC_1BPP:
case BLIT_SRC_1BPP_BYTE_PACKED:
src_dat = (data & 1) ? voodoo->bltColorFg : voodoo->bltColorBg;
data >>= 1;
src_bits--;
break;
case BLIT_SRC_16BPP:
switch (voodoo->bltCommand & BLIT_SRC_RGB_FORMAT) {
case BLIT_SRC_RGB_ARGB:
case BLIT_SRC_RGB_RGBA:
src_dat = data & 0xffff;
break;
case BLIT_SRC_16BPP:
switch (voodoo->bltCommand & BLIT_SRC_RGB_FORMAT)
{
case BLIT_SRC_RGB_ARGB: case BLIT_SRC_RGB_RGBA:
src_dat = data & 0xffff;
break;
case BLIT_SRC_RGB_ABGR: case BLIT_SRC_RGB_BGRA:
src_dat = ((data & 0xf800) >> 11) | (data & 0x07c0) | ((data & 0x0038) << 11);
break;
}
data >>= 16;
src_bits -= 16;
break;
case BLIT_SRC_24BPP: case BLIT_SRC_24BPP_DITHER_2X2: case BLIT_SRC_24BPP_DITHER_4X4:
switch (voodoo->bltCommand & BLIT_SRC_RGB_FORMAT)
{
case BLIT_SRC_RGB_ARGB:
r = (data >> 16) & 0xff;
g = (data >> 8) & 0xff;
b = data & 0xff;
break;
case BLIT_SRC_RGB_ABGR:
r = data & 0xff;
g = (data >> 8) & 0xff;
b = (data >> 16) & 0xff;
break;
case BLIT_SRC_RGB_RGBA:
r = (data >> 24) & 0xff;
g = (data >> 16) & 0xff;
b = (data >> 8) & 0xff;
break;
case BLIT_SRC_RGB_BGRA:
r = (data >> 8) & 0xff;
g = (data >> 16) & 0xff;
b = (data >> 24) & 0xff;
break;
}
switch (voodoo->bltCommand & BLIT_SRC_FORMAT)
{
case BLIT_SRC_24BPP:
src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8);
break;
case BLIT_SRC_24BPP_DITHER_2X2:
r = dither_rb2x2[r][voodoo->blt.dst_y & 1][x & 1];
g = dither_g2x2[g][voodoo->blt.dst_y & 1][x & 1];
b = dither_rb2x2[b][voodoo->blt.dst_y & 1][x & 1];
src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8);
break;
case BLIT_SRC_24BPP_DITHER_4X4:
r = dither_rb[r][voodoo->blt.dst_y & 3][x & 3];
g = dither_g[g][voodoo->blt.dst_y & 3][x & 3];
b = dither_rb[b][voodoo->blt.dst_y & 3][x & 3];
src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8);
break;
}
src_bits = 0;
case BLIT_SRC_RGB_ABGR:
case BLIT_SRC_RGB_BGRA:
src_dat = ((data & 0xf800) >> 11) | (data & 0x07c0) | ((data & 0x0038) << 11);
break;
}
if (SLI_ENABLED)
{
if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (voodoo->blt.dst_y & 1)) ||
((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(voodoo->blt.dst_y & 1)))
goto skip_pixel;
data >>= 16;
src_bits -= 16;
break;
case BLIT_SRC_24BPP:
case BLIT_SRC_24BPP_DITHER_2X2:
case BLIT_SRC_24BPP_DITHER_4X4:
switch (voodoo->bltCommand & BLIT_SRC_RGB_FORMAT) {
case BLIT_SRC_RGB_ARGB:
r = (data >> 16) & 0xff;
g = (data >> 8) & 0xff;
b = data & 0xff;
break;
case BLIT_SRC_RGB_ABGR:
r = data & 0xff;
g = (data >> 8) & 0xff;
b = (data >> 16) & 0xff;
break;
case BLIT_SRC_RGB_RGBA:
r = (data >> 24) & 0xff;
g = (data >> 16) & 0xff;
b = (data >> 8) & 0xff;
break;
case BLIT_SRC_RGB_BGRA:
r = (data >> 8) & 0xff;
g = (data >> 16) & 0xff;
b = (data >> 24) & 0xff;
break;
}
if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED)
{
if (x < voodoo->bltClipLeft || x >= voodoo->bltClipRight ||
voodoo->blt.dst_y < voodoo->bltClipLowY || voodoo->blt.dst_y >= voodoo->bltClipHighY)
goto skip_pixel;
switch (voodoo->bltCommand & BLIT_SRC_FORMAT) {
case BLIT_SRC_24BPP:
src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8);
break;
case BLIT_SRC_24BPP_DITHER_2X2:
r = dither_rb2x2[r][voodoo->blt.dst_y & 1][x & 1];
g = dither_g2x2[g][voodoo->blt.dst_y & 1][x & 1];
b = dither_rb2x2[b][voodoo->blt.dst_y & 1][x & 1];
src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8);
break;
case BLIT_SRC_24BPP_DITHER_4X4:
r = dither_rb[r][voodoo->blt.dst_y & 3][x & 3];
g = dither_g[g][voodoo->blt.dst_y & 3][x & 3];
b = dither_rb[b][voodoo->blt.dst_y & 3][x & 3];
src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8);
break;
}
src_bits = 0;
break;
}
dst_dat = dst[x];
if (SLI_ENABLED) {
if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (voodoo->blt.dst_y & 1)) || ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(voodoo->blt.dst_y & 1)))
goto skip_pixel;
}
if (voodoo->bltCommand & BLIT_SRC_CHROMA)
{
r = (src_dat >> 11);
g = (src_dat >> 5) & 0x3f;
b = src_dat & 0x1f;
if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED) {
if (x < voodoo->bltClipLeft || x >= voodoo->bltClipRight || voodoo->blt.dst_y < voodoo->bltClipLowY || voodoo->blt.dst_y >= voodoo->bltClipHighY)
goto skip_pixel;
}
if (r >= voodoo->bltSrcChromaMinR && r <= voodoo->bltSrcChromaMaxR &&
g >= voodoo->bltSrcChromaMinG && g <= voodoo->bltSrcChromaMaxG &&
b >= voodoo->bltSrcChromaMinB && b <= voodoo->bltSrcChromaMaxB)
rop |= BLIT_ROP_SRC_PASS;
}
if (voodoo->bltCommand & BLIT_DST_CHROMA)
{
r = (dst_dat >> 11);
g = (dst_dat >> 5) & 0x3f;
b = dst_dat & 0x1f;
dst_dat = dst[x];
if (r >= voodoo->bltDstChromaMinR && r <= voodoo->bltDstChromaMaxR &&
g >= voodoo->bltDstChromaMinG && g <= voodoo->bltDstChromaMaxG &&
b >= voodoo->bltDstChromaMinB && b <= voodoo->bltDstChromaMaxB)
rop |= BLIT_ROP_DST_PASS;
}
if (voodoo->bltCommand & BLIT_SRC_CHROMA) {
r = (src_dat >> 11);
g = (src_dat >> 5) & 0x3f;
b = src_dat & 0x1f;
MIX(src_dat, dst_dat, voodoo->bltRop[rop]);
if (r >= voodoo->bltSrcChromaMinR && r <= voodoo->bltSrcChromaMaxR && g >= voodoo->bltSrcChromaMinG && g <= voodoo->bltSrcChromaMaxG && b >= voodoo->bltSrcChromaMinB && b <= voodoo->bltSrcChromaMaxB)
rop |= BLIT_ROP_SRC_PASS;
}
if (voodoo->bltCommand & BLIT_DST_CHROMA) {
r = (dst_dat >> 11);
g = (dst_dat >> 5) & 0x3f;
b = dst_dat & 0x1f;
dst[x] = dst_dat;
if (r >= voodoo->bltDstChromaMinR && r <= voodoo->bltDstChromaMaxR && g >= voodoo->bltDstChromaMinG && g <= voodoo->bltDstChromaMaxG && b >= voodoo->bltDstChromaMinB && b <= voodoo->bltDstChromaMaxB)
rop |= BLIT_ROP_DST_PASS;
}
MIX(src_dat, dst_dat, voodoo->bltRop[rop]);
dst[x] = dst_dat;
skip_pixel:
voodoo->blt.cur_x++;
}
voodoo->blt.cur_x++;
}
if (voodoo->blt.cur_x > voodoo->blt.size_x)
{
voodoo->blt.size_y--;
if (voodoo->blt.size_y >= 0)
{
voodoo->blt.cur_x = 0;
voodoo->blt.dst_y += voodoo->blt.y_dir;
}
if (voodoo->blt.cur_x > voodoo->blt.size_x) {
voodoo->blt.size_y--;
if (voodoo->blt.size_y >= 0) {
voodoo->blt.cur_x = 0;
voodoo->blt.dst_y += voodoo->blt.y_dir;
}
}
}
void voodoo_fastfill(voodoo_t *voodoo, voodoo_params_t *params)
void
voodoo_fastfill(voodoo_t *voodoo, voodoo_params_t *params)
{
int y;
int low_y, high_y;
int y;
int low_y, high_y;
if (params->fbzMode & (1 << 17))
{
int y_origin = (voodoo->type >= VOODOO_BANSHEE) ? (voodoo->y_origin_swap+1) : voodoo->v_disp;
if (params->fbzMode & (1 << 17)) {
int y_origin = (voodoo->type >= VOODOO_BANSHEE) ? (voodoo->y_origin_swap + 1) : voodoo->v_disp;
high_y = y_origin - params->clipLowY;
low_y = y_origin - params->clipHighY;
}
else
{
low_y = params->clipLowY;
high_y = params->clipHighY;
}
high_y = y_origin - params->clipLowY;
low_y = y_origin - params->clipHighY;
} else {
low_y = params->clipLowY;
high_y = params->clipHighY;
}
if (params->fbzMode & FBZ_RGB_WMASK)
{
int r, g, b;
uint16_t col;
if (params->fbzMode & FBZ_RGB_WMASK) {
int r, g, b;
uint16_t col;
r = ((params->color1 >> 16) >> 3) & 0x1f;
g = ((params->color1 >> 8) >> 2) & 0x3f;
b = (params->color1 >> 3) & 0x1f;
col = b | (g << 5) | (r << 11);
r = ((params->color1 >> 16) >> 3) & 0x1f;
g = ((params->color1 >> 8) >> 2) & 0x3f;
b = (params->color1 >> 3) & 0x1f;
col = b | (g << 5) | (r << 11);
if (SLI_ENABLED)
{
for (y = low_y; y < high_y; y += 2)
{
uint16_t *cbuf = (uint16_t *)&voodoo->fb_mem[(params->draw_offset + (y >> 1) * voodoo->row_width) & voodoo->fb_mask];
int x;
if (SLI_ENABLED) {
for (y = low_y; y < high_y; y += 2) {
uint16_t *cbuf = (uint16_t *) &voodoo->fb_mem[(params->draw_offset + (y >> 1) * voodoo->row_width) & voodoo->fb_mask];
int x;
for (x = params->clipLeft; x < params->clipRight; x++)
cbuf[x] = col;
}
}
else
{
for (y = low_y; y < high_y; y++)
{
if (voodoo->col_tiled)
{
uint16_t *cbuf = (uint16_t *)&voodoo->fb_mem[(params->draw_offset + (y >> 5) * voodoo->row_width + (y & 31) * 128) & voodoo->fb_mask];
int x;
for (x = params->clipLeft; x < params->clipRight; x++)
{
int x2 = (x & 63) | ((x >> 6) * 128*32/2);
cbuf[x2] = col;
}
}
else
{
uint16_t *cbuf = (uint16_t *)&voodoo->fb_mem[(params->draw_offset + y * voodoo->row_width) & voodoo->fb_mask];
int x;
for (x = params->clipLeft; x < params->clipRight; x++)
cbuf[x] = col;
}
}
for (x = params->clipLeft; x < params->clipRight; x++)
cbuf[x] = col;
}
} else {
for (y = low_y; y < high_y; y++) {
if (voodoo->col_tiled) {
uint16_t *cbuf = (uint16_t *) &voodoo->fb_mem[(params->draw_offset + (y >> 5) * voodoo->row_width + (y & 31) * 128) & voodoo->fb_mask];
int x;
for (x = params->clipLeft; x < params->clipRight; x++) {
int x2 = (x & 63) | ((x >> 6) * 128 * 32 / 2);
cbuf[x2] = col;
}
} else {
uint16_t *cbuf = (uint16_t *) &voodoo->fb_mem[(params->draw_offset + y * voodoo->row_width) & voodoo->fb_mask];
int x;
for (x = params->clipLeft; x < params->clipRight; x++)
cbuf[x] = col;
}
}
}
if (params->fbzMode & FBZ_DEPTH_WMASK)
{
if (SLI_ENABLED)
{
for (y = low_y; y < high_y; y += 2)
{
uint16_t *abuf = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + (y >> 1) * voodoo->row_width) & voodoo->fb_mask];
int x;
}
if (params->fbzMode & FBZ_DEPTH_WMASK) {
if (SLI_ENABLED) {
for (y = low_y; y < high_y; y += 2) {
uint16_t *abuf = (uint16_t *) &voodoo->fb_mem[(params->aux_offset + (y >> 1) * voodoo->row_width) & voodoo->fb_mask];
int x;
for (x = params->clipLeft; x < params->clipRight; x++)
abuf[x] = params->zaColor & 0xffff;
}
}
else
{
for (y = low_y; y < high_y; y++)
{
if (voodoo->aux_tiled)
{
uint16_t *abuf = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + (y >> 5) * voodoo->aux_row_width + (y & 31) * 128) & voodoo->fb_mask];
int x;
for (x = params->clipLeft; x < params->clipRight; x++)
{
int x2 = (x & 63) | ((x >> 6) * 128*32/2);
abuf[x2] = params->zaColor & 0xffff;
}
}
else
{
uint16_t *abuf = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + y * voodoo->aux_row_width) & voodoo->fb_mask];
int x;
for (x = params->clipLeft; x < params->clipRight; x++)
abuf[x] = params->zaColor & 0xffff;
}
}
for (x = params->clipLeft; x < params->clipRight; x++)
abuf[x] = params->zaColor & 0xffff;
}
} else {
for (y = low_y; y < high_y; y++) {
if (voodoo->aux_tiled) {
uint16_t *abuf = (uint16_t *) &voodoo->fb_mem[(params->aux_offset + (y >> 5) * voodoo->aux_row_width + (y & 31) * 128) & voodoo->fb_mask];
int x;
for (x = params->clipLeft; x < params->clipRight; x++) {
int x2 = (x & 63) | ((x >> 6) * 128 * 32 / 2);
abuf[x2] = params->zaColor & 0xffff;
}
} else {
uint16_t *abuf = (uint16_t *) &voodoo->fb_mem[(params->aux_offset + y * voodoo->aux_row_width) & voodoo->fb_mask];
int x;
for (x = params->clipLeft; x < params->clipRight; x++)
abuf[x] = params->zaColor & 0xffff;
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -38,7 +38,6 @@
#include <86box/vid_voodoo_render.h>
#include <86box/vid_voodoo_fb.h>
#ifdef ENABLE_VOODOO_FB_LOG
int voodoo_fb_do_log = ENABLE_VOODOO_FB_LOG;
@@ -48,447 +47,402 @@ voodoo_fb_log(const char *fmt, ...)
va_list ap;
if (voodoo_fb_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define voodoo_fb_log(fmt, ...)
# define voodoo_fb_log(fmt, ...)
#endif
uint16_t voodoo_fb_readw(uint32_t addr, void *p)
uint16_t
voodoo_fb_readw(uint32_t addr, void *p)
{
voodoo_t *voodoo = (voodoo_t *)p;
int x, y;
uint32_t read_addr;
uint16_t temp;
voodoo_t *voodoo = (voodoo_t *) p;
int x, y;
uint32_t read_addr;
uint16_t temp;
if (voodoo->type >= VOODOO_BANSHEE)
{
x = addr & 0xffe;
y = (addr >> 12) & 0x3ff;
}
if (voodoo->type >= VOODOO_BANSHEE) {
x = addr & 0xffe;
y = (addr >> 12) & 0x3ff;
} else {
x = addr & 0x7fe;
y = (addr >> 11) & 0x3ff;
}
if (SLI_ENABLED) {
voodoo_set_t *set = voodoo->set;
if (y & 1)
voodoo = set->voodoos[1];
else
{
x = addr & 0x7fe;
y = (addr >> 11) & 0x3ff;
}
voodoo = set->voodoos[0];
if (SLI_ENABLED)
{
voodoo_set_t *set = voodoo->set;
y >>= 1;
}
if (y & 1)
voodoo = set->voodoos[1];
else
voodoo = set->voodoos[0];
if (voodoo->col_tiled)
read_addr = voodoo->fb_read_offset + (x & 127) + (x >> 7) * 128 * 32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width;
else
read_addr = voodoo->fb_read_offset + x + (y * voodoo->row_width);
y >>= 1;
}
if (read_addr > voodoo->fb_mask)
return 0xffff;
if (voodoo->col_tiled)
read_addr = voodoo->fb_read_offset + (x & 127) + (x >> 7) * 128*32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width;
else
read_addr = voodoo->fb_read_offset + x + (y * voodoo->row_width);
temp = *(uint16_t *) (&voodoo->fb_mem[read_addr & voodoo->fb_mask]);
if (read_addr > voodoo->fb_mask)
return 0xffff;
temp = *(uint16_t *)(&voodoo->fb_mem[read_addr & voodoo->fb_mask]);
// voodoo_fb_log("voodoo_fb_readw : %08X %08X %i %i %08X %08X %08x:%08x %i\n", addr, temp, x, y, read_addr, *(uint32_t *)(&voodoo->fb_mem[4]), cs, pc, fb_reads++);
return temp;
// voodoo_fb_log("voodoo_fb_readw : %08X %08X %i %i %08X %08X %08x:%08x %i\n", addr, temp, x, y, read_addr, *(uint32_t *)(&voodoo->fb_mem[4]), cs, pc, fb_reads++);
return temp;
}
uint32_t voodoo_fb_readl(uint32_t addr, void *p)
uint32_t
voodoo_fb_readl(uint32_t addr, void *p)
{
voodoo_t *voodoo = (voodoo_t *)p;
int x, y;
uint32_t read_addr;
uint32_t temp;
voodoo_t *voodoo = (voodoo_t *) p;
int x, y;
uint32_t read_addr;
uint32_t temp;
if (voodoo->type >= VOODOO_BANSHEE)
{
x = addr & 0xffe;
y = (addr >> 12) & 0x3ff;
}
if (voodoo->type >= VOODOO_BANSHEE) {
x = addr & 0xffe;
y = (addr >> 12) & 0x3ff;
} else {
x = addr & 0x7fe;
y = (addr >> 11) & 0x3ff;
}
if (SLI_ENABLED) {
voodoo_set_t *set = voodoo->set;
if (y & 1)
voodoo = set->voodoos[1];
else
{
x = addr & 0x7fe;
y = (addr >> 11) & 0x3ff;
}
voodoo = set->voodoos[0];
if (SLI_ENABLED)
{
voodoo_set_t *set = voodoo->set;
y >>= 1;
}
if (y & 1)
voodoo = set->voodoos[1];
else
voodoo = set->voodoos[0];
if (voodoo->col_tiled)
read_addr = voodoo->fb_read_offset + (x & 127) + (x >> 7) * 128 * 32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width;
else
read_addr = voodoo->fb_read_offset + x + (y * voodoo->row_width);
y >>= 1;
}
if (read_addr > voodoo->fb_mask)
return 0xffffffff;
if (voodoo->col_tiled)
read_addr = voodoo->fb_read_offset + (x & 127) + (x >> 7) * 128*32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width;
else
read_addr = voodoo->fb_read_offset + x + (y * voodoo->row_width);
temp = *(uint32_t *) (&voodoo->fb_mem[read_addr & voodoo->fb_mask]);
if (read_addr > voodoo->fb_mask)
return 0xffffffff;
temp = *(uint32_t *)(&voodoo->fb_mem[read_addr & voodoo->fb_mask]);
// voodoo_fb_log("voodoo_fb_readl : %08X %08x %08X x=%i y=%i %08X %08X %08x:%08x %i ro=%08x rw=%i\n", addr, read_addr, temp, x, y, read_addr, *(uint32_t *)(&voodoo->fb_mem[4]), cs, pc, fb_reads++, voodoo->fb_read_offset, voodoo->row_width);
return temp;
// voodoo_fb_log("voodoo_fb_readl : %08X %08x %08X x=%i y=%i %08X %08X %08x:%08x %i ro=%08x rw=%i\n", addr, read_addr, temp, x, y, read_addr, *(uint32_t *)(&voodoo->fb_mem[4]), cs, pc, fb_reads++, voodoo->fb_read_offset, voodoo->row_width);
return temp;
}
static inline uint16_t do_dither(voodoo_params_t *params, rgba8_t col, int x, int y)
static inline uint16_t
do_dither(voodoo_params_t *params, rgba8_t col, int x, int y)
{
int r, g, b;
int r, g, b;
if (dither)
{
if (dither2x2)
{
r = dither_rb2x2[col.r][y & 1][x & 1];
g = dither_g2x2[col.g][y & 1][x & 1];
b = dither_rb2x2[col.b][y & 1][x & 1];
}
else
{
r = dither_rb[col.r][y & 3][x & 3];
g = dither_g[col.g][y & 3][x & 3];
b = dither_rb[col.b][y & 3][x & 3];
}
}
else
{
r = col.r >> 3;
g = col.g >> 2;
b = col.b >> 3;
if (dither) {
if (dither2x2) {
r = dither_rb2x2[col.r][y & 1][x & 1];
g = dither_g2x2[col.g][y & 1][x & 1];
b = dither_rb2x2[col.b][y & 1][x & 1];
} else {
r = dither_rb[col.r][y & 3][x & 3];
g = dither_g[col.g][y & 3][x & 3];
b = dither_rb[col.b][y & 3][x & 3];
}
} else {
r = col.r >> 3;
g = col.g >> 2;
b = col.b >> 3;
}
return b | (g << 5) | (r << 11);
return b | (g << 5) | (r << 11);
}
void voodoo_fb_writew(uint32_t addr, uint16_t val, void *p)
void
voodoo_fb_writew(uint32_t addr, uint16_t val, void *p)
{
voodoo_t *voodoo = (voodoo_t *)p;
voodoo_params_t *params = &voodoo->params;
int x, y;
uint32_t write_addr, write_addr_aux;
rgba8_t colour_data;
uint16_t depth_data;
uint8_t alpha_data;
int write_mask = 0;
voodoo_t *voodoo = (voodoo_t *) p;
voodoo_params_t *params = &voodoo->params;
int x, y;
uint32_t write_addr, write_addr_aux;
rgba8_t colour_data;
uint16_t depth_data;
uint8_t alpha_data;
int write_mask = 0;
colour_data.r = colour_data.g = colour_data.b = colour_data.a = 0;
colour_data.r = colour_data.g = colour_data.b = colour_data.a = 0;
depth_data = voodoo->params.zaColor & 0xffff;
alpha_data = voodoo->params.zaColor >> 24;
depth_data = voodoo->params.zaColor & 0xffff;
alpha_data = voodoo->params.zaColor >> 24;
// while (!RB_EMPTY)
// thread_reset_event(voodoo->not_full_event);
// while (!RB_EMPTY)
// thread_reset_event(voodoo->not_full_event);
// voodoo_fb_log("voodoo_fb_writew : %08X %04X\n", addr, val);
// voodoo_fb_log("voodoo_fb_writew : %08X %04X\n", addr, val);
switch (voodoo->lfbMode & LFB_FORMAT_MASK) {
case LFB_FORMAT_RGB565:
colour_data = rgb565[val];
alpha_data = 0xff;
write_mask = LFB_WRITE_COLOUR;
break;
case LFB_FORMAT_RGB555:
colour_data = argb1555[val];
alpha_data = 0xff;
write_mask = LFB_WRITE_COLOUR;
break;
case LFB_FORMAT_ARGB1555:
colour_data = argb1555[val];
alpha_data = colour_data.a;
write_mask = LFB_WRITE_COLOUR;
break;
case LFB_FORMAT_DEPTH:
depth_data = val;
write_mask = LFB_WRITE_DEPTH;
break;
switch (voodoo->lfbMode & LFB_FORMAT_MASK)
default:
fatal("voodoo_fb_writew : bad LFB format %08X\n", voodoo->lfbMode);
}
if (voodoo->type >= VOODOO_BANSHEE) {
x = addr & 0xffe;
y = (addr >> 12) & 0x3ff;
} else {
x = addr & 0x7fe;
y = (addr >> 11) & 0x3ff;
}
if (SLI_ENABLED) {
if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (y & 1)) || ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(y & 1)))
return;
y >>= 1;
}
if (voodoo->fb_write_offset == voodoo->params.front_offset && y < 2048)
voodoo->dirty_line[y] = 1;
if (voodoo->col_tiled)
write_addr = voodoo->fb_write_offset + (x & 127) + (x >> 7) * 128 * 32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width;
else
write_addr = voodoo->fb_write_offset + x + (y * voodoo->row_width);
if (voodoo->aux_tiled)
write_addr_aux = voodoo->params.aux_offset + (x & 127) + (x >> 7) * 128 * 32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width;
else
write_addr_aux = voodoo->params.aux_offset + x + (y * voodoo->row_width);
// voodoo_fb_log("fb_writew %08x %i %i %i %08x\n", addr, x, y, voodoo->row_width, write_addr);
if (voodoo->lfbMode & 0x100) {
{
case LFB_FORMAT_RGB565:
colour_data = rgb565[val];
alpha_data = 0xff;
write_mask = LFB_WRITE_COLOUR;
break;
case LFB_FORMAT_RGB555:
colour_data = argb1555[val];
alpha_data = 0xff;
write_mask = LFB_WRITE_COLOUR;
break;
case LFB_FORMAT_ARGB1555:
colour_data = argb1555[val];
alpha_data = colour_data.a;
write_mask = LFB_WRITE_COLOUR;
break;
case LFB_FORMAT_DEPTH:
depth_data = val;
write_mask = LFB_WRITE_DEPTH;
break;
rgba8_t write_data = colour_data;
uint16_t new_depth = depth_data;
default:
fatal("voodoo_fb_writew : bad LFB format %08X\n", voodoo->lfbMode);
}
if (params->fbzMode & FBZ_DEPTH_ENABLE) {
uint16_t old_depth = *(uint16_t *) (&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]);
if (voodoo->type >= VOODOO_BANSHEE)
{
x = addr & 0xffe;
y = (addr >> 12) & 0x3ff;
}
else
{
x = addr & 0x7fe;
y = (addr >> 11) & 0x3ff;
}
DEPTH_TEST(new_depth);
}
if (SLI_ENABLED)
{
if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (y & 1)) ||
((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(y & 1)))
return;
y >>= 1;
}
if ((params->fbzMode & FBZ_CHROMAKEY) && write_data.r == params->chromaKey_r && write_data.g == params->chromaKey_g && write_data.b == params->chromaKey_b)
goto skip_pixel;
if (params->fogMode & FOG_ENABLE) {
int32_t z = new_depth << 12;
int64_t w_depth = (int64_t) (int32_t) new_depth;
int32_t ia = alpha_data << 12;
if (voodoo->fb_write_offset == voodoo->params.front_offset && y < 2048)
voodoo->dirty_line[y] = 1;
APPLY_FOG(write_data.r, write_data.g, write_data.b, z, ia, w_depth);
}
if (voodoo->col_tiled)
write_addr = voodoo->fb_write_offset + (x & 127) + (x >> 7) * 128*32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width;
else
write_addr = voodoo->fb_write_offset + x + (y * voodoo->row_width);
if (voodoo->aux_tiled)
write_addr_aux = voodoo->params.aux_offset + (x & 127) + (x >> 7) * 128*32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width;
else
write_addr_aux = voodoo->params.aux_offset + x + (y * voodoo->row_width);
if (params->alphaMode & 1)
ALPHA_TEST(alpha_data);
// voodoo_fb_log("fb_writew %08x %i %i %i %08x\n", addr, x, y, voodoo->row_width, write_addr);
if (params->alphaMode & (1 << 4)) {
uint16_t dat = *(uint16_t *) (&voodoo->fb_mem[write_addr & voodoo->fb_mask]);
int dest_r, dest_g, dest_b, dest_a;
if (voodoo->lfbMode & 0x100)
{
{
rgba8_t write_data = colour_data;
uint16_t new_depth = depth_data;
dest_r = (dat >> 8) & 0xf8;
dest_g = (dat >> 3) & 0xfc;
dest_b = (dat << 3) & 0xf8;
dest_r |= (dest_r >> 5);
dest_g |= (dest_g >> 6);
dest_b |= (dest_b >> 5);
dest_a = 0xff;
if (params->fbzMode & FBZ_DEPTH_ENABLE)
{
uint16_t old_depth = *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]);
ALPHA_BLEND(write_data.r, write_data.g, write_data.b, alpha_data);
}
DEPTH_TEST(new_depth);
}
if ((params->fbzMode & FBZ_CHROMAKEY) &&
write_data.r == params->chromaKey_r &&
write_data.g == params->chromaKey_g &&
write_data.b == params->chromaKey_b)
goto skip_pixel;
if (params->fogMode & FOG_ENABLE)
{
int32_t z = new_depth << 12;
int64_t w_depth = (int64_t)(int32_t)new_depth;
int32_t ia = alpha_data << 12;
APPLY_FOG(write_data.r, write_data.g, write_data.b, z, ia, w_depth);
}
if (params->alphaMode & 1)
ALPHA_TEST(alpha_data);
if (params->alphaMode & (1 << 4))
{
uint16_t dat = *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]);
int dest_r, dest_g, dest_b, dest_a;
dest_r = (dat >> 8) & 0xf8;
dest_g = (dat >> 3) & 0xfc;
dest_b = (dat << 3) & 0xf8;
dest_r |= (dest_r >> 5);
dest_g |= (dest_g >> 6);
dest_b |= (dest_b >> 5);
dest_a = 0xff;
ALPHA_BLEND(write_data.r, write_data.g, write_data.b, alpha_data);
}
if (params->fbzMode & FBZ_RGB_WMASK)
*(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, write_data, x >> 1, y);
if (params->fbzMode & FBZ_DEPTH_WMASK)
*(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = new_depth;
if (params->fbzMode & FBZ_RGB_WMASK)
*(uint16_t *) (&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, write_data, x >> 1, y);
if (params->fbzMode & FBZ_DEPTH_WMASK)
*(uint16_t *) (&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = new_depth;
skip_pixel:
return;
}
}
else
{
if (write_mask & LFB_WRITE_COLOUR)
*(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, colour_data, x >> 1, y);
if (write_mask & LFB_WRITE_DEPTH)
*(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = depth_data;
return;
}
} else {
if (write_mask & LFB_WRITE_COLOUR)
*(uint16_t *) (&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, colour_data, x >> 1, y);
if (write_mask & LFB_WRITE_DEPTH)
*(uint16_t *) (&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = depth_data;
}
}
void voodoo_fb_writel(uint32_t addr, uint32_t val, void *p)
void
voodoo_fb_writel(uint32_t addr, uint32_t val, void *p)
{
voodoo_t *voodoo = (voodoo_t *)p;
voodoo_params_t *params = &voodoo->params;
int x, y;
uint32_t write_addr, write_addr_aux;
rgba8_t colour_data[2];
uint16_t depth_data[2];
uint8_t alpha_data[2];
int write_mask = 0, count = 1;
voodoo_t *voodoo = (voodoo_t *) p;
voodoo_params_t *params = &voodoo->params;
int x, y;
uint32_t write_addr, write_addr_aux;
rgba8_t colour_data[2];
uint16_t depth_data[2];
uint8_t alpha_data[2];
int write_mask = 0, count = 1;
depth_data[0] = depth_data[1] = voodoo->params.zaColor & 0xffff;
alpha_data[0] = alpha_data[1] = voodoo->params.zaColor >> 24;
// while (!RB_EMPTY)
// thread_reset_event(voodoo->not_full_event);
depth_data[0] = depth_data[1] = voodoo->params.zaColor & 0xffff;
alpha_data[0] = alpha_data[1] = voodoo->params.zaColor >> 24;
// while (!RB_EMPTY)
// thread_reset_event(voodoo->not_full_event);
// voodoo_fb_log("voodoo_fb_writel : %08X %08X\n", addr, val);
// voodoo_fb_log("voodoo_fb_writel : %08X %08X\n", addr, val);
switch (voodoo->lfbMode & LFB_FORMAT_MASK)
{
case LFB_FORMAT_RGB565:
colour_data[0] = rgb565[val & 0xffff];
colour_data[1] = rgb565[val >> 16];
write_mask = LFB_WRITE_COLOUR;
count = 2;
break;
case LFB_FORMAT_RGB555:
colour_data[0] = argb1555[val & 0xffff];
colour_data[1] = argb1555[val >> 16];
write_mask = LFB_WRITE_COLOUR;
count = 2;
break;
case LFB_FORMAT_ARGB1555:
colour_data[0] = argb1555[val & 0xffff];
alpha_data[0] = colour_data[0].a;
colour_data[1] = argb1555[val >> 16];
alpha_data[1] = colour_data[1].a;
write_mask = LFB_WRITE_COLOUR;
count = 2;
break;
switch (voodoo->lfbMode & LFB_FORMAT_MASK) {
case LFB_FORMAT_RGB565:
colour_data[0] = rgb565[val & 0xffff];
colour_data[1] = rgb565[val >> 16];
write_mask = LFB_WRITE_COLOUR;
count = 2;
break;
case LFB_FORMAT_RGB555:
colour_data[0] = argb1555[val & 0xffff];
colour_data[1] = argb1555[val >> 16];
write_mask = LFB_WRITE_COLOUR;
count = 2;
break;
case LFB_FORMAT_ARGB1555:
colour_data[0] = argb1555[val & 0xffff];
alpha_data[0] = colour_data[0].a;
colour_data[1] = argb1555[val >> 16];
alpha_data[1] = colour_data[1].a;
write_mask = LFB_WRITE_COLOUR;
count = 2;
break;
case LFB_FORMAT_ARGB8888:
colour_data[0].b = val & 0xff;
colour_data[0].g = (val >> 8) & 0xff;
colour_data[0].r = (val >> 16) & 0xff;
alpha_data[0] = (val >> 24) & 0xff;
write_mask = LFB_WRITE_COLOUR;
addr >>= 1;
break;
case LFB_FORMAT_ARGB8888:
colour_data[0].b = val & 0xff;
colour_data[0].g = (val >> 8) & 0xff;
colour_data[0].r = (val >> 16) & 0xff;
alpha_data[0] = (val >> 24) & 0xff;
write_mask = LFB_WRITE_COLOUR;
addr >>= 1;
break;
case LFB_FORMAT_DEPTH:
depth_data[0] = val;
depth_data[1] = val >> 16;
write_mask = LFB_WRITE_DEPTH;
count = 2;
break;
case LFB_FORMAT_DEPTH:
depth_data[0] = val;
depth_data[1] = val >> 16;
write_mask = LFB_WRITE_DEPTH;
count = 2;
break;
default:
fatal("voodoo_fb_writel : bad LFB format %08X\n", voodoo->lfbMode);
}
default:
fatal("voodoo_fb_writel : bad LFB format %08X\n", voodoo->lfbMode);
}
if (voodoo->type >= VOODOO_BANSHEE)
{
x = addr & 0xffe;
y = (addr >> 12) & 0x3ff;
}
else
{
x = addr & 0x7fe;
y = (addr >> 11) & 0x3ff;
}
if (voodoo->type >= VOODOO_BANSHEE) {
x = addr & 0xffe;
y = (addr >> 12) & 0x3ff;
} else {
x = addr & 0x7fe;
y = (addr >> 11) & 0x3ff;
}
if (SLI_ENABLED)
{
if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (y & 1)) ||
((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(y & 1)))
return;
y >>= 1;
}
if (SLI_ENABLED) {
if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (y & 1)) || ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(y & 1)))
return;
y >>= 1;
}
if (voodoo->fb_write_offset == voodoo->params.front_offset && y < 2048)
voodoo->dirty_line[y] = 1;
if (voodoo->fb_write_offset == voodoo->params.front_offset && y < 2048)
voodoo->dirty_line[y] = 1;
if (voodoo->col_tiled)
write_addr = voodoo->fb_write_offset + (x & 127) + (x >> 7) * 128*32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width;
else
write_addr = voodoo->fb_write_offset + x + (y * voodoo->row_width);
if (voodoo->aux_tiled)
write_addr_aux = voodoo->params.aux_offset + (x & 127) + (x >> 7) * 128*32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width;
else
write_addr_aux = voodoo->params.aux_offset + x + (y * voodoo->row_width);
if (voodoo->col_tiled)
write_addr = voodoo->fb_write_offset + (x & 127) + (x >> 7) * 128 * 32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width;
else
write_addr = voodoo->fb_write_offset + x + (y * voodoo->row_width);
if (voodoo->aux_tiled)
write_addr_aux = voodoo->params.aux_offset + (x & 127) + (x >> 7) * 128 * 32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width;
else
write_addr_aux = voodoo->params.aux_offset + x + (y * voodoo->row_width);
// voodoo_fb_log("fb_writel %08x x=%i y=%i rw=%i %08x wo=%08x\n", addr, x, y, voodoo->row_width, write_addr, voodoo->fb_write_offset);
// voodoo_fb_log("fb_writel %08x x=%i y=%i rw=%i %08x wo=%08x\n", addr, x, y, voodoo->row_width, write_addr, voodoo->fb_write_offset);
if (voodoo->lfbMode & 0x100)
{
int c;
if (voodoo->lfbMode & 0x100) {
int c;
for (c = 0; c < count; c++)
{
rgba8_t write_data = colour_data[c];
uint16_t new_depth = depth_data[c];
for (c = 0; c < count; c++) {
rgba8_t write_data = colour_data[c];
uint16_t new_depth = depth_data[c];
if (params->fbzMode & FBZ_DEPTH_ENABLE)
{
uint16_t old_depth = *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]);
if (params->fbzMode & FBZ_DEPTH_ENABLE) {
uint16_t old_depth = *(uint16_t *) (&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]);
DEPTH_TEST(new_depth);
}
DEPTH_TEST(new_depth);
}
if ((params->fbzMode & FBZ_CHROMAKEY) &&
write_data.r == params->chromaKey_r &&
write_data.g == params->chromaKey_g &&
write_data.b == params->chromaKey_b)
goto skip_pixel;
if ((params->fbzMode & FBZ_CHROMAKEY) && write_data.r == params->chromaKey_r && write_data.g == params->chromaKey_g && write_data.b == params->chromaKey_b)
goto skip_pixel;
if (params->fogMode & FOG_ENABLE)
{
int32_t z = new_depth << 12;
int64_t w_depth = new_depth;
int32_t ia = alpha_data[c] << 12;
if (params->fogMode & FOG_ENABLE) {
int32_t z = new_depth << 12;
int64_t w_depth = new_depth;
int32_t ia = alpha_data[c] << 12;
APPLY_FOG(write_data.r, write_data.g, write_data.b, z, ia, w_depth);
}
APPLY_FOG(write_data.r, write_data.g, write_data.b, z, ia, w_depth);
}
if (params->alphaMode & 1)
ALPHA_TEST(alpha_data[c]);
if (params->alphaMode & 1)
ALPHA_TEST(alpha_data[c]);
if (params->alphaMode & (1 << 4))
{
uint16_t dat = *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]);
int dest_r, dest_g, dest_b, dest_a;
if (params->alphaMode & (1 << 4)) {
uint16_t dat = *(uint16_t *) (&voodoo->fb_mem[write_addr & voodoo->fb_mask]);
int dest_r, dest_g, dest_b, dest_a;
dest_r = (dat >> 8) & 0xf8;
dest_g = (dat >> 3) & 0xfc;
dest_b = (dat << 3) & 0xf8;
dest_r |= (dest_r >> 5);
dest_g |= (dest_g >> 6);
dest_b |= (dest_b >> 5);
dest_a = 0xff;
dest_r = (dat >> 8) & 0xf8;
dest_g = (dat >> 3) & 0xfc;
dest_b = (dat << 3) & 0xf8;
dest_r |= (dest_r >> 5);
dest_g |= (dest_g >> 6);
dest_b |= (dest_b >> 5);
dest_a = 0xff;
ALPHA_BLEND(write_data.r, write_data.g, write_data.b, alpha_data[c]);
}
ALPHA_BLEND(write_data.r, write_data.g, write_data.b, alpha_data[c]);
}
if (params->fbzMode & FBZ_RGB_WMASK)
*(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, write_data, (x >> 1) + c, y);
if (params->fbzMode & FBZ_DEPTH_WMASK)
*(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = new_depth;
if (params->fbzMode & FBZ_RGB_WMASK)
*(uint16_t *) (&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, write_data, (x >> 1) + c, y);
if (params->fbzMode & FBZ_DEPTH_WMASK)
*(uint16_t *) (&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = new_depth;
skip_pixel:
write_addr += 2;
write_addr_aux += 2;
}
write_addr += 2;
write_addr_aux += 2;
}
else
{
int c;
} else {
int c;
for (c = 0; c < count; c++)
{
if (write_mask & LFB_WRITE_COLOUR)
*(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, colour_data[c], (x >> 1) + c, y);
if (write_mask & LFB_WRITE_DEPTH)
*(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = depth_data[c];
for (c = 0; c < count; c++) {
if (write_mask & LFB_WRITE_COLOUR)
*(uint16_t *) (&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, colour_data[c], (x >> 1) + c, y);
if (write_mask & LFB_WRITE_DEPTH)
*(uint16_t *) (&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = depth_data[c];
write_addr += 2;
write_addr_aux += 2;
}
write_addr += 2;
write_addr_aux += 2;
}
}
}

View File

@@ -41,7 +41,6 @@
#include <86box/vid_voodoo_render.h>
#include <86box/vid_voodoo_texture.h>
#ifdef ENABLE_VOODOO_FIFO_LOG
int voodoo_fifo_do_log = ENABLE_VOODOO_FIFO_LOG;
@@ -51,497 +50,461 @@ voodoo_fifo_log(const char *fmt, ...)
va_list ap;
if (voodoo_fifo_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define voodoo_fifo_log(fmt, ...)
# define voodoo_fifo_log(fmt, ...)
#endif
#define WAKE_DELAY (TIMER_USEC * 100)
void voodoo_wake_fifo_thread(voodoo_t *voodoo)
void
voodoo_wake_fifo_thread(voodoo_t *voodoo)
{
if (!timer_is_enabled(&voodoo->wake_timer))
{
/*Don't wake FIFO thread immediately - if we do that it will probably
process one word and go back to sleep, requiring it to be woken on
almost every write. Instead, wait a short while so that the CPU
emulation writes more data so we have more batched-up work.*/
timer_set_delay_u64(&voodoo->wake_timer, WAKE_DELAY);
}
if (!timer_is_enabled(&voodoo->wake_timer)) {
/*Don't wake FIFO thread immediately - if we do that it will probably
process one word and go back to sleep, requiring it to be woken on
almost every write. Instead, wait a short while so that the CPU
emulation writes more data so we have more batched-up work.*/
timer_set_delay_u64(&voodoo->wake_timer, WAKE_DELAY);
}
}
void voodoo_wake_fifo_thread_now(voodoo_t *voodoo)
void
voodoo_wake_fifo_thread_now(voodoo_t *voodoo)
{
thread_set_event(voodoo->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/
thread_set_event(voodoo->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/
}
void voodoo_wake_timer(void *p)
void
voodoo_wake_timer(void *p)
{
voodoo_t *voodoo = (voodoo_t *)p;
voodoo_t *voodoo = (voodoo_t *) p;
thread_set_event(voodoo->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/
thread_set_event(voodoo->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/
}
void voodoo_queue_command(voodoo_t *voodoo, uint32_t addr_type, uint32_t val)
void
voodoo_queue_command(voodoo_t *voodoo, uint32_t addr_type, uint32_t val)
{
fifo_entry_t *fifo = &voodoo->fifo[voodoo->fifo_write_idx & FIFO_MASK];
fifo_entry_t *fifo = &voodoo->fifo[voodoo->fifo_write_idx & FIFO_MASK];
while (FIFO_FULL)
{
thread_reset_event(voodoo->fifo_not_full_event);
if (FIFO_FULL)
{
thread_wait_event(voodoo->fifo_not_full_event, 1); /*Wait for room in ringbuffer*/
if (FIFO_FULL)
voodoo_wake_fifo_thread_now(voodoo);
}
}
fifo->val = val;
fifo->addr_type = addr_type;
voodoo->fifo_write_idx++;
if (FIFO_ENTRIES > 0xe000)
voodoo_wake_fifo_thread(voodoo);
}
void voodoo_flush(voodoo_t *voodoo)
{
voodoo->flush = 1;
while (!FIFO_EMPTY)
{
while (FIFO_FULL) {
thread_reset_event(voodoo->fifo_not_full_event);
if (FIFO_FULL) {
thread_wait_event(voodoo->fifo_not_full_event, 1); /*Wait for room in ringbuffer*/
if (FIFO_FULL)
voodoo_wake_fifo_thread_now(voodoo);
thread_wait_event(voodoo->fifo_not_full_event, 1);
}
voodoo_wait_for_render_thread_idle(voodoo);
voodoo->flush = 0;
}
}
void voodoo_wake_fifo_threads(voodoo_set_t *set, voodoo_t *voodoo)
{
fifo->val = val;
fifo->addr_type = addr_type;
voodoo->fifo_write_idx++;
if (FIFO_ENTRIES > 0xe000)
voodoo_wake_fifo_thread(voodoo);
if (SLI_ENABLED && voodoo->type != VOODOO_2 && set->voodoos[0] == voodoo)
voodoo_wake_fifo_thread(set->voodoos[1]);
}
void voodoo_wait_for_swap_complete(voodoo_t *voodoo)
void
voodoo_flush(voodoo_t *voodoo)
{
while (voodoo->swap_pending)
{
thread_wait_event(voodoo->wake_fifo_thread, -1);
thread_reset_event(voodoo->wake_fifo_thread);
voodoo->flush = 1;
while (!FIFO_EMPTY) {
voodoo_wake_fifo_thread_now(voodoo);
thread_wait_event(voodoo->fifo_not_full_event, 1);
}
voodoo_wait_for_render_thread_idle(voodoo);
voodoo->flush = 0;
}
thread_wait_mutex(voodoo->swap_mutex);
if ((voodoo->swap_pending && voodoo->flush) || FIFO_FULL)
{
/*Main thread is waiting for FIFO to empty, so skip vsync wait and just swap*/
memset(voodoo->dirty_line, 1, sizeof(voodoo->dirty_line));
voodoo->front_offset = voodoo->params.front_offset;
if (voodoo->swap_count > 0)
voodoo->swap_count--;
voodoo->swap_pending = 0;
thread_release_mutex(voodoo->swap_mutex);;
break;
}
else
thread_release_mutex(voodoo->swap_mutex);;
void
voodoo_wake_fifo_threads(voodoo_set_t *set, voodoo_t *voodoo)
{
voodoo_wake_fifo_thread(voodoo);
if (SLI_ENABLED && voodoo->type != VOODOO_2 && set->voodoos[0] == voodoo)
voodoo_wake_fifo_thread(set->voodoos[1]);
}
void
voodoo_wait_for_swap_complete(voodoo_t *voodoo)
{
while (voodoo->swap_pending) {
thread_wait_event(voodoo->wake_fifo_thread, -1);
thread_reset_event(voodoo->wake_fifo_thread);
thread_wait_mutex(voodoo->swap_mutex);
if ((voodoo->swap_pending && voodoo->flush) || FIFO_FULL) {
/*Main thread is waiting for FIFO to empty, so skip vsync wait and just swap*/
memset(voodoo->dirty_line, 1, sizeof(voodoo->dirty_line));
voodoo->front_offset = voodoo->params.front_offset;
if (voodoo->swap_count > 0)
voodoo->swap_count--;
voodoo->swap_pending = 0;
thread_release_mutex(voodoo->swap_mutex);
;
break;
} else
thread_release_mutex(voodoo->swap_mutex);
;
}
}
static uint32_t
cmdfifo_get(voodoo_t *voodoo)
{
uint32_t val;
if (!voodoo->cmdfifo_in_sub) {
while (voodoo->cmdfifo_depth_rd == voodoo->cmdfifo_depth_wr) {
thread_wait_event(voodoo->wake_fifo_thread, -1);
thread_reset_event(voodoo->wake_fifo_thread);
}
}
val = *(uint32_t *) &voodoo->fb_mem[voodoo->cmdfifo_rp & voodoo->fb_mask];
if (!voodoo->cmdfifo_in_sub)
voodoo->cmdfifo_depth_rd++;
voodoo->cmdfifo_rp += 4;
// voodoo_fifo_log(" CMDFIFO get %08x\n", val);
return val;
}
static uint32_t cmdfifo_get(voodoo_t *voodoo)
static inline float
cmdfifo_get_f(voodoo_t *voodoo)
{
uint32_t val;
union {
uint32_t i;
float f;
} tempif;
if (!voodoo->cmdfifo_in_sub) {
while (voodoo->cmdfifo_depth_rd == voodoo->cmdfifo_depth_wr)
{
thread_wait_event(voodoo->wake_fifo_thread, -1);
thread_reset_event(voodoo->wake_fifo_thread);
}
}
val = *(uint32_t *)&voodoo->fb_mem[voodoo->cmdfifo_rp & voodoo->fb_mask];
if (!voodoo->cmdfifo_in_sub)
voodoo->cmdfifo_depth_rd++;
voodoo->cmdfifo_rp += 4;
// voodoo_fifo_log(" CMDFIFO get %08x\n", val);
return val;
tempif.i = cmdfifo_get(voodoo);
return tempif.f;
}
static inline float cmdfifo_get_f(voodoo_t *voodoo)
{
union
{
uint32_t i;
float f;
} tempif;
enum {
CMDFIFO3_PC_MASK_RGB = (1 << 10),
CMDFIFO3_PC_MASK_ALPHA = (1 << 11),
CMDFIFO3_PC_MASK_Z = (1 << 12),
CMDFIFO3_PC_MASK_Wb = (1 << 13),
CMDFIFO3_PC_MASK_W0 = (1 << 14),
CMDFIFO3_PC_MASK_S0_T0 = (1 << 15),
CMDFIFO3_PC_MASK_W1 = (1 << 16),
CMDFIFO3_PC_MASK_S1_T1 = (1 << 17),
tempif.i = cmdfifo_get(voodoo);
return tempif.f;
}
enum
{
CMDFIFO3_PC_MASK_RGB = (1 << 10),
CMDFIFO3_PC_MASK_ALPHA = (1 << 11),
CMDFIFO3_PC_MASK_Z = (1 << 12),
CMDFIFO3_PC_MASK_Wb = (1 << 13),
CMDFIFO3_PC_MASK_W0 = (1 << 14),
CMDFIFO3_PC_MASK_S0_T0 = (1 << 15),
CMDFIFO3_PC_MASK_W1 = (1 << 16),
CMDFIFO3_PC_MASK_S1_T1 = (1 << 17),
CMDFIFO3_PC = (1 << 28)
CMDFIFO3_PC = (1 << 28)
};
void voodoo_fifo_thread(void *param)
void
voodoo_fifo_thread(void *param)
{
voodoo_t *voodoo = (voodoo_t *)param;
voodoo_t *voodoo = (voodoo_t *) param;
while (voodoo->fifo_thread_run)
{
while (voodoo->fifo_thread_run) {
thread_set_event(voodoo->fifo_not_full_event);
thread_wait_event(voodoo->wake_fifo_thread, -1);
thread_reset_event(voodoo->wake_fifo_thread);
voodoo->voodoo_busy = 1;
while (!FIFO_EMPTY) {
uint64_t start_time = plat_timer_read();
uint64_t end_time;
fifo_entry_t *fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK];
switch (fifo->addr_type & FIFO_TYPE) {
case FIFO_WRITEL_REG:
while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_REG) {
voodoo_reg_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo);
fifo->addr_type = FIFO_INVALID;
voodoo->fifo_read_idx++;
if (FIFO_EMPTY)
break;
fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK];
}
break;
case FIFO_WRITEW_FB:
voodoo_wait_for_render_thread_idle(voodoo);
while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEW_FB) {
voodoo_fb_writew(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo);
fifo->addr_type = FIFO_INVALID;
voodoo->fifo_read_idx++;
if (FIFO_EMPTY)
break;
fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK];
}
break;
case FIFO_WRITEL_FB:
voodoo_wait_for_render_thread_idle(voodoo);
while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_FB) {
voodoo_fb_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo);
fifo->addr_type = FIFO_INVALID;
voodoo->fifo_read_idx++;
if (FIFO_EMPTY)
break;
fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK];
}
break;
case FIFO_WRITEL_TEX:
while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_TEX) {
if (!(fifo->addr_type & 0x400000))
voodoo_tex_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo);
fifo->addr_type = FIFO_INVALID;
voodoo->fifo_read_idx++;
if (FIFO_EMPTY)
break;
fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK];
}
break;
case FIFO_WRITEL_2DREG:
while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_2DREG) {
voodoo_2d_reg_writel(voodoo, fifo->addr_type & FIFO_ADDR, fifo->val);
fifo->addr_type = FIFO_INVALID;
voodoo->fifo_read_idx++;
if (FIFO_EMPTY)
break;
fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK];
}
break;
default:
fatal("Unknown fifo entry %08x\n", fifo->addr_type);
}
if (FIFO_ENTRIES > 0xe000)
thread_set_event(voodoo->fifo_not_full_event);
thread_wait_event(voodoo->wake_fifo_thread, -1);
thread_reset_event(voodoo->wake_fifo_thread);
voodoo->voodoo_busy = 1;
while (!FIFO_EMPTY)
{
uint64_t start_time = plat_timer_read();
uint64_t end_time;
fifo_entry_t *fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK];
switch (fifo->addr_type & FIFO_TYPE)
{
case FIFO_WRITEL_REG:
while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_REG)
{
voodoo_reg_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo);
fifo->addr_type = FIFO_INVALID;
voodoo->fifo_read_idx++;
if (FIFO_EMPTY)
break;
fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK];
}
break;
case FIFO_WRITEW_FB:
voodoo_wait_for_render_thread_idle(voodoo);
while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEW_FB)
{
voodoo_fb_writew(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo);
fifo->addr_type = FIFO_INVALID;
voodoo->fifo_read_idx++;
if (FIFO_EMPTY)
break;
fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK];
}
break;
case FIFO_WRITEL_FB:
voodoo_wait_for_render_thread_idle(voodoo);
while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_FB)
{
voodoo_fb_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo);
fifo->addr_type = FIFO_INVALID;
voodoo->fifo_read_idx++;
if (FIFO_EMPTY)
break;
fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK];
}
break;
case FIFO_WRITEL_TEX:
while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_TEX)
{
if (!(fifo->addr_type & 0x400000))
voodoo_tex_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo);
fifo->addr_type = FIFO_INVALID;
voodoo->fifo_read_idx++;
if (FIFO_EMPTY)
break;
fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK];
}
break;
case FIFO_WRITEL_2DREG:
while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_2DREG)
{
voodoo_2d_reg_writel(voodoo, fifo->addr_type & FIFO_ADDR, fifo->val);
fifo->addr_type = FIFO_INVALID;
voodoo->fifo_read_idx++;
if (FIFO_EMPTY)
break;
fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK];
}
break;
default:
fatal("Unknown fifo entry %08x\n", fifo->addr_type);
}
if (FIFO_ENTRIES > 0xe000)
thread_set_event(voodoo->fifo_not_full_event);
end_time = plat_timer_read();
voodoo->time += end_time - start_time;
}
while (voodoo->cmdfifo_enabled && (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr || voodoo->cmdfifo_in_sub))
{
uint64_t start_time = plat_timer_read();
uint64_t end_time;
uint32_t header = cmdfifo_get(voodoo);
uint32_t addr;
uint32_t mask;
int smode;
int num;
int num_verticies;
int v_num;
// voodoo_fifo_log(" CMDFIFO header %08x at %08x\n", header, voodoo->cmdfifo_rp);
switch (header & 7)
{
case 0:
// voodoo_fifo_log("CMDFIFO0\n");
switch ((header >> 3) & 7)
{
case 0: /*NOP*/
break;
case 1: /*JSR*/
// voodoo_fifo_log("JSR %08x\n", (header >> 4) & 0xfffffc);
voodoo->cmdfifo_ret_addr = voodoo->cmdfifo_rp;
voodoo->cmdfifo_rp = (header >> 4) & 0xfffffc;
voodoo->cmdfifo_in_sub = 1;
break;
case 2: /*RET*/
voodoo->cmdfifo_rp = voodoo->cmdfifo_ret_addr;
voodoo->cmdfifo_in_sub = 0;
break;
case 3: /*JMP local frame buffer*/
voodoo->cmdfifo_rp = (header >> 4) & 0xfffffc;
// voodoo_fifo_log("JMP to %08x %04x\n", voodoo->cmdfifo_rp, header);
break;
default:
fatal("Bad CMDFIFO0 %08x\n", header);
}
break;
case 1:
num = header >> 16;
addr = (header & 0x7ff8) >> 1;
// voodoo_fifo_log("CMDFIFO1 addr=%08x\n",addr);
while (num--)
{
uint32_t val = cmdfifo_get(voodoo);
if ((addr & (1 << 13)) && voodoo->type >= VOODOO_BANSHEE)
{
// if (voodoo->type != VOODOO_BANSHEE)
// fatal("CMDFIFO1: Not Banshee\n");
// voodoo_fifo_log("CMDFIFO1: write %08x %08x\n", addr, val);
voodoo_2d_reg_writel(voodoo, addr, val);
}
else
{
if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD ||
(addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD)
voodoo->cmd_written_fifo++;
if (voodoo->type >= VOODOO_BANSHEE && (addr & 0x3ff) == SST_swapbufferCMD)
voodoo->cmd_written_fifo++;
voodoo_reg_writel(addr, val, voodoo);
}
if (header & (1 << 15))
addr += 4;
}
break;
case 2:
if (voodoo->type < VOODOO_BANSHEE)
fatal("CMDFIFO2: Not Banshee\n");
mask = (header >> 3);
addr = 8;
while (mask)
{
if (mask & 1)
{
uint32_t val = cmdfifo_get(voodoo);
voodoo_2d_reg_writel(voodoo, addr, val);
}
addr += 4;
mask >>= 1;
}
break;
case 3:
num = (header >> 29) & 7;
mask = header;//(header >> 10) & 0xff;
smode = (header >> 22) & 0xf;
voodoo_reg_writel(SST_sSetupMode, ((header >> 10) & 0xff) | (smode << 16), voodoo);
num_verticies = (header >> 6) & 0xf;
v_num = 0;
if (((header >> 3) & 7) == 2)
v_num = 1;
// voodoo_fifo_log("CMDFIFO3: num=%i verts=%i mask=%02x\n", num, num_verticies, (header >> 10) & 0xff);
// voodoo_fifo_log("CMDFIFO3 %02x %i\n", (header >> 10), (header >> 3) & 7);
while (num_verticies--)
{
voodoo->verts[3].sVx = cmdfifo_get_f(voodoo);
voodoo->verts[3].sVy = cmdfifo_get_f(voodoo);
if (mask & CMDFIFO3_PC_MASK_RGB)
{
if (header & CMDFIFO3_PC)
{
uint32_t val = cmdfifo_get(voodoo);
voodoo->verts[3].sBlue = (float)(val & 0xff);
voodoo->verts[3].sGreen = (float)((val >> 8) & 0xff);
voodoo->verts[3].sRed = (float)((val >> 16) & 0xff);
voodoo->verts[3].sAlpha = (float)((val >> 24) & 0xff);
}
else
{
voodoo->verts[3].sRed = cmdfifo_get_f(voodoo);
voodoo->verts[3].sGreen = cmdfifo_get_f(voodoo);
voodoo->verts[3].sBlue = cmdfifo_get_f(voodoo);
}
}
if ((mask & CMDFIFO3_PC_MASK_ALPHA) && !(header & CMDFIFO3_PC))
voodoo->verts[3].sAlpha = cmdfifo_get_f(voodoo);
if (mask & CMDFIFO3_PC_MASK_Z)
voodoo->verts[3].sVz = cmdfifo_get_f(voodoo);
if (mask & CMDFIFO3_PC_MASK_Wb)
voodoo->verts[3].sWb = cmdfifo_get_f(voodoo);
if (mask & CMDFIFO3_PC_MASK_W0)
voodoo->verts[3].sW0 = cmdfifo_get_f(voodoo);
if (mask & CMDFIFO3_PC_MASK_S0_T0)
{
voodoo->verts[3].sS0 = cmdfifo_get_f(voodoo);
voodoo->verts[3].sT0 = cmdfifo_get_f(voodoo);
}
if (mask & CMDFIFO3_PC_MASK_W1)
voodoo->verts[3].sW1 = cmdfifo_get_f(voodoo);
if (mask & CMDFIFO3_PC_MASK_S1_T1)
{
voodoo->verts[3].sS1 = cmdfifo_get_f(voodoo);
voodoo->verts[3].sT1 = cmdfifo_get_f(voodoo);
}
if (v_num)
voodoo_reg_writel(SST_sDrawTriCMD, 0, voodoo);
else
voodoo_reg_writel(SST_sBeginTriCMD, 0, voodoo);
v_num++;
if (v_num == 3 && ((header >> 3) & 7) == 0)
v_num = 0;
}
break;
case 4:
num = (header >> 29) & 7;
mask = (header >> 15) & 0x3fff;
addr = (header & 0x7ff8) >> 1;
// voodoo_fifo_log("CMDFIFO4 addr=%08x\n",addr);
while (mask)
{
if (mask & 1)
{
uint32_t val = cmdfifo_get(voodoo);
if ((addr & (1 << 13)) && voodoo->type >= VOODOO_BANSHEE)
{
if (voodoo->type < VOODOO_BANSHEE)
fatal("CMDFIFO1: Not Banshee\n");
// voodoo_fifo_log("CMDFIFO1: write %08x %08x\n", addr, val);
voodoo_2d_reg_writel(voodoo, addr, val);
}
else
{
if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD ||
(addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD)
voodoo->cmd_written_fifo++;
if (voodoo->type >= VOODOO_BANSHEE && (addr & 0x3ff) == SST_swapbufferCMD)
voodoo->cmd_written_fifo++;
voodoo_reg_writel(addr, val, voodoo);
}
}
addr += 4;
mask >>= 1;
}
while (num--)
cmdfifo_get(voodoo);
break;
case 5:
// if (header & 0x3fc00000)
// fatal("CMDFIFO packet 5 has byte disables set %08x\n", header);
num = (header >> 3) & 0x7ffff;
addr = cmdfifo_get(voodoo) & 0xffffff;
if (!num)
num = 1;
// voodoo_fifo_log("CMDFIFO5 addr=%08x num=%i\n", addr, num);
switch (header >> 30)
{
case 0: /*Linear framebuffer (Banshee)*/
case 1: /*Planar YUV*/
if (voodoo->texture_present[0][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT])
{
// voodoo_fifo_log("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT);
flush_texture_cache(voodoo, addr & voodoo->texture_mask, 0);
}
if (voodoo->texture_present[1][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT])
{
// voodoo_fifo_log("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT);
flush_texture_cache(voodoo, addr & voodoo->texture_mask, 1);
}
while (num--)
{
uint32_t val = cmdfifo_get(voodoo);
if (addr <= voodoo->fb_mask)
*(uint32_t *)&voodoo->fb_mem[addr] = val;
addr += 4;
}
break;
case 2: /*Framebuffer*/
while (num--)
{
uint32_t val = cmdfifo_get(voodoo);
voodoo_fb_writel(addr, val, voodoo);
addr += 4;
}
break;
case 3: /*Texture*/
while (num--)
{
uint32_t val = cmdfifo_get(voodoo);
voodoo_tex_writel(addr, val, voodoo);
addr += 4;
}
break;
default:
fatal("CMDFIFO packet 5 bad space %08x %08x\n", header, voodoo->cmdfifo_rp);
}
break;
default:
fatal("Bad CMDFIFO packet %08x %08x\n", header, voodoo->cmdfifo_rp);
}
end_time = plat_timer_read();
voodoo->time += end_time - start_time;
}
voodoo->voodoo_busy = 0;
end_time = plat_timer_read();
voodoo->time += end_time - start_time;
}
while (voodoo->cmdfifo_enabled && (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr || voodoo->cmdfifo_in_sub)) {
uint64_t start_time = plat_timer_read();
uint64_t end_time;
uint32_t header = cmdfifo_get(voodoo);
uint32_t addr;
uint32_t mask;
int smode;
int num;
int num_verticies;
int v_num;
// voodoo_fifo_log(" CMDFIFO header %08x at %08x\n", header, voodoo->cmdfifo_rp);
switch (header & 7) {
case 0:
// voodoo_fifo_log("CMDFIFO0\n");
switch ((header >> 3) & 7) {
case 0: /*NOP*/
break;
case 1: /*JSR*/
// voodoo_fifo_log("JSR %08x\n", (header >> 4) & 0xfffffc);
voodoo->cmdfifo_ret_addr = voodoo->cmdfifo_rp;
voodoo->cmdfifo_rp = (header >> 4) & 0xfffffc;
voodoo->cmdfifo_in_sub = 1;
break;
case 2: /*RET*/
voodoo->cmdfifo_rp = voodoo->cmdfifo_ret_addr;
voodoo->cmdfifo_in_sub = 0;
break;
case 3: /*JMP local frame buffer*/
voodoo->cmdfifo_rp = (header >> 4) & 0xfffffc;
// voodoo_fifo_log("JMP to %08x %04x\n", voodoo->cmdfifo_rp, header);
break;
default:
fatal("Bad CMDFIFO0 %08x\n", header);
}
break;
case 1:
num = header >> 16;
addr = (header & 0x7ff8) >> 1;
// voodoo_fifo_log("CMDFIFO1 addr=%08x\n",addr);
while (num--) {
uint32_t val = cmdfifo_get(voodoo);
if ((addr & (1 << 13)) && voodoo->type >= VOODOO_BANSHEE) {
// if (voodoo->type != VOODOO_BANSHEE)
// fatal("CMDFIFO1: Not Banshee\n");
// voodoo_fifo_log("CMDFIFO1: write %08x %08x\n", addr, val);
voodoo_2d_reg_writel(voodoo, addr, val);
} else {
if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD || (addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD)
voodoo->cmd_written_fifo++;
if (voodoo->type >= VOODOO_BANSHEE && (addr & 0x3ff) == SST_swapbufferCMD)
voodoo->cmd_written_fifo++;
voodoo_reg_writel(addr, val, voodoo);
}
if (header & (1 << 15))
addr += 4;
}
break;
case 2:
if (voodoo->type < VOODOO_BANSHEE)
fatal("CMDFIFO2: Not Banshee\n");
mask = (header >> 3);
addr = 8;
while (mask) {
if (mask & 1) {
uint32_t val = cmdfifo_get(voodoo);
voodoo_2d_reg_writel(voodoo, addr, val);
}
addr += 4;
mask >>= 1;
}
break;
case 3:
num = (header >> 29) & 7;
mask = header; //(header >> 10) & 0xff;
smode = (header >> 22) & 0xf;
voodoo_reg_writel(SST_sSetupMode, ((header >> 10) & 0xff) | (smode << 16), voodoo);
num_verticies = (header >> 6) & 0xf;
v_num = 0;
if (((header >> 3) & 7) == 2)
v_num = 1;
// voodoo_fifo_log("CMDFIFO3: num=%i verts=%i mask=%02x\n", num, num_verticies, (header >> 10) & 0xff);
// voodoo_fifo_log("CMDFIFO3 %02x %i\n", (header >> 10), (header >> 3) & 7);
while (num_verticies--) {
voodoo->verts[3].sVx = cmdfifo_get_f(voodoo);
voodoo->verts[3].sVy = cmdfifo_get_f(voodoo);
if (mask & CMDFIFO3_PC_MASK_RGB) {
if (header & CMDFIFO3_PC) {
uint32_t val = cmdfifo_get(voodoo);
voodoo->verts[3].sBlue = (float) (val & 0xff);
voodoo->verts[3].sGreen = (float) ((val >> 8) & 0xff);
voodoo->verts[3].sRed = (float) ((val >> 16) & 0xff);
voodoo->verts[3].sAlpha = (float) ((val >> 24) & 0xff);
} else {
voodoo->verts[3].sRed = cmdfifo_get_f(voodoo);
voodoo->verts[3].sGreen = cmdfifo_get_f(voodoo);
voodoo->verts[3].sBlue = cmdfifo_get_f(voodoo);
}
}
if ((mask & CMDFIFO3_PC_MASK_ALPHA) && !(header & CMDFIFO3_PC))
voodoo->verts[3].sAlpha = cmdfifo_get_f(voodoo);
if (mask & CMDFIFO3_PC_MASK_Z)
voodoo->verts[3].sVz = cmdfifo_get_f(voodoo);
if (mask & CMDFIFO3_PC_MASK_Wb)
voodoo->verts[3].sWb = cmdfifo_get_f(voodoo);
if (mask & CMDFIFO3_PC_MASK_W0)
voodoo->verts[3].sW0 = cmdfifo_get_f(voodoo);
if (mask & CMDFIFO3_PC_MASK_S0_T0) {
voodoo->verts[3].sS0 = cmdfifo_get_f(voodoo);
voodoo->verts[3].sT0 = cmdfifo_get_f(voodoo);
}
if (mask & CMDFIFO3_PC_MASK_W1)
voodoo->verts[3].sW1 = cmdfifo_get_f(voodoo);
if (mask & CMDFIFO3_PC_MASK_S1_T1) {
voodoo->verts[3].sS1 = cmdfifo_get_f(voodoo);
voodoo->verts[3].sT1 = cmdfifo_get_f(voodoo);
}
if (v_num)
voodoo_reg_writel(SST_sDrawTriCMD, 0, voodoo);
else
voodoo_reg_writel(SST_sBeginTriCMD, 0, voodoo);
v_num++;
if (v_num == 3 && ((header >> 3) & 7) == 0)
v_num = 0;
}
break;
case 4:
num = (header >> 29) & 7;
mask = (header >> 15) & 0x3fff;
addr = (header & 0x7ff8) >> 1;
// voodoo_fifo_log("CMDFIFO4 addr=%08x\n",addr);
while (mask) {
if (mask & 1) {
uint32_t val = cmdfifo_get(voodoo);
if ((addr & (1 << 13)) && voodoo->type >= VOODOO_BANSHEE) {
if (voodoo->type < VOODOO_BANSHEE)
fatal("CMDFIFO1: Not Banshee\n");
// voodoo_fifo_log("CMDFIFO1: write %08x %08x\n", addr, val);
voodoo_2d_reg_writel(voodoo, addr, val);
} else {
if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD || (addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD)
voodoo->cmd_written_fifo++;
if (voodoo->type >= VOODOO_BANSHEE && (addr & 0x3ff) == SST_swapbufferCMD)
voodoo->cmd_written_fifo++;
voodoo_reg_writel(addr, val, voodoo);
}
}
addr += 4;
mask >>= 1;
}
while (num--)
cmdfifo_get(voodoo);
break;
case 5:
// if (header & 0x3fc00000)
// fatal("CMDFIFO packet 5 has byte disables set %08x\n", header);
num = (header >> 3) & 0x7ffff;
addr = cmdfifo_get(voodoo) & 0xffffff;
if (!num)
num = 1;
// voodoo_fifo_log("CMDFIFO5 addr=%08x num=%i\n", addr, num);
switch (header >> 30) {
case 0: /*Linear framebuffer (Banshee)*/
case 1: /*Planar YUV*/
if (voodoo->texture_present[0][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT]) {
// voodoo_fifo_log("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT);
flush_texture_cache(voodoo, addr & voodoo->texture_mask, 0);
}
if (voodoo->texture_present[1][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT]) {
// voodoo_fifo_log("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT);
flush_texture_cache(voodoo, addr & voodoo->texture_mask, 1);
}
while (num--) {
uint32_t val = cmdfifo_get(voodoo);
if (addr <= voodoo->fb_mask)
*(uint32_t *) &voodoo->fb_mem[addr] = val;
addr += 4;
}
break;
case 2: /*Framebuffer*/
while (num--) {
uint32_t val = cmdfifo_get(voodoo);
voodoo_fb_writel(addr, val, voodoo);
addr += 4;
}
break;
case 3: /*Texture*/
while (num--) {
uint32_t val = cmdfifo_get(voodoo);
voodoo_tex_writel(addr, val, voodoo);
addr += 4;
}
break;
default:
fatal("CMDFIFO packet 5 bad space %08x %08x\n", header, voodoo->cmdfifo_rp);
}
break;
default:
fatal("Bad CMDFIFO packet %08x %08x\n", header, voodoo->cmdfifo_rp);
}
end_time = plat_timer_read();
voodoo->time += end_time - start_time;
}
voodoo->voodoo_busy = 0;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -46,216 +46,190 @@ voodoo_setup_log(const char *fmt, ...)
va_list ap;
if (voodoo_setup_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define voodoo_setup_log(fmt, ...)
# define voodoo_setup_log(fmt, ...)
#endif
void voodoo_triangle_setup(voodoo_t *voodoo)
void
voodoo_triangle_setup(voodoo_t *voodoo)
{
float dxAB, dxBC, dyAB, dyBC;
float area;
int va = 0, vb = 1, vc = 2;
vert_t verts[3];
float dxAB, dxBC, dyAB, dyBC;
float area;
int va = 0, vb = 1, vc = 2;
vert_t verts[3];
verts[0] = voodoo->verts[0];
verts[1] = voodoo->verts[1];
verts[2] = voodoo->verts[2];
verts[0] = voodoo->verts[0];
verts[1] = voodoo->verts[1];
verts[2] = voodoo->verts[2];
if (verts[0].sVy < verts[1].sVy)
{
if (verts[1].sVy < verts[2].sVy)
{
/* V1>V0, V2>V1, V2>V1>V0*/
va = 0; /*OK*/
vb = 1;
vc = 2;
}
else
{
/* V1>V0, V1>V2*/
if (verts[0].sVy < verts[2].sVy)
{
/* V1>V0, V1>V2, V2>V0, V1>V2>V0*/
va = 0;
vb = 2;
vc = 1;
}
else
{
/* V1>V0, V1>V2, V0>V2, V1>V0>V2*/
va = 2;
vb = 0;
vc = 1;
}
}
if (verts[0].sVy < verts[1].sVy) {
if (verts[1].sVy < verts[2].sVy) {
/* V1>V0, V2>V1, V2>V1>V0*/
va = 0; /*OK*/
vb = 1;
vc = 2;
} else {
/* V1>V0, V1>V2*/
if (verts[0].sVy < verts[2].sVy) {
/* V1>V0, V1>V2, V2>V0, V1>V2>V0*/
va = 0;
vb = 2;
vc = 1;
} else {
/* V1>V0, V1>V2, V0>V2, V1>V0>V2*/
va = 2;
vb = 0;
vc = 1;
}
}
else
{
if (verts[1].sVy < verts[2].sVy)
{
/* V0>V1, V2>V1*/
if (verts[0].sVy < verts[2].sVy)
{
/* V0>V1, V2>V1, V2>V0, V2>V0>V1*/
va = 1;
vb = 0;
vc = 2;
}
else
{
/* V0>V1, V2>V1, V0>V2, V0>V2>V1*/
va = 1;
vb = 2;
vc = 0;
}
}
else
{
/*V0>V1>V2*/
va = 2;
vb = 1;
vc = 0;
}
} else {
if (verts[1].sVy < verts[2].sVy) {
/* V0>V1, V2>V1*/
if (verts[0].sVy < verts[2].sVy) {
/* V0>V1, V2>V1, V2>V0, V2>V0>V1*/
va = 1;
vb = 0;
vc = 2;
} else {
/* V0>V1, V2>V1, V0>V2, V0>V2>V1*/
va = 1;
vb = 2;
vc = 0;
}
} else {
/*V0>V1>V2*/
va = 2;
vb = 1;
vc = 0;
}
}
dxAB = verts[0].sVx - verts[1].sVx;
dxBC = verts[1].sVx - verts[2].sVx;
dyAB = verts[0].sVy - verts[1].sVy;
dyBC = verts[1].sVy - verts[2].sVy;
dxAB = verts[0].sVx - verts[1].sVx;
dxBC = verts[1].sVx - verts[2].sVx;
dyAB = verts[0].sVy - verts[1].sVy;
dyBC = verts[1].sVy - verts[2].sVy;
area = dxAB * dyBC - dxBC * dyAB;
area = dxAB * dyBC - dxBC * dyAB;
if (area == 0.0)
return;
if (area == 0.0)
return;
if (voodoo->sSetupMode & SETUPMODE_CULLING_ENABLE)
{
int cull_sign = voodoo->sSetupMode & SETUPMODE_CULLING_SIGN;
int sign = (area < 0.0);
if (voodoo->sSetupMode & SETUPMODE_CULLING_ENABLE) {
int cull_sign = voodoo->sSetupMode & SETUPMODE_CULLING_SIGN;
int sign = (area < 0.0);
if ((voodoo->sSetupMode & (SETUPMODE_CULLING_ENABLE | SETUPMODE_DISABLE_PINGPONG))
== SETUPMODE_CULLING_ENABLE && voodoo->cull_pingpong)
cull_sign = !cull_sign;
if ((voodoo->sSetupMode & (SETUPMODE_CULLING_ENABLE | SETUPMODE_DISABLE_PINGPONG))
== SETUPMODE_CULLING_ENABLE
&& voodoo->cull_pingpong)
cull_sign = !cull_sign;
if (cull_sign && sign)
return;
if (!cull_sign && !sign)
return;
}
if (cull_sign && sign)
return;
if (!cull_sign && !sign)
return;
}
dxAB = verts[va].sVx - verts[vb].sVx;
dxBC = verts[vb].sVx - verts[vc].sVx;
dyAB = verts[va].sVy - verts[vb].sVy;
dyBC = verts[vb].sVy - verts[vc].sVy;
dxAB = verts[va].sVx - verts[vb].sVx;
dxBC = verts[vb].sVx - verts[vc].sVx;
dyAB = verts[va].sVy - verts[vb].sVy;
dyBC = verts[vb].sVy - verts[vc].sVy;
area = dxAB * dyBC - dxBC * dyAB;
area = dxAB * dyBC - dxBC * dyAB;
dxAB /= area;
dxBC /= area;
dyAB /= area;
dyBC /= area;
dxAB /= area;
dxBC /= area;
dyAB /= area;
dyBC /= area;
voodoo->params.vertexAx = (int32_t) (int16_t) ((int32_t) (verts[va].sVx * 16.0f) & 0xffff);
voodoo->params.vertexAy = (int32_t) (int16_t) ((int32_t) (verts[va].sVy * 16.0f) & 0xffff);
voodoo->params.vertexBx = (int32_t) (int16_t) ((int32_t) (verts[vb].sVx * 16.0f) & 0xffff);
voodoo->params.vertexBy = (int32_t) (int16_t) ((int32_t) (verts[vb].sVy * 16.0f) & 0xffff);
voodoo->params.vertexCx = (int32_t) (int16_t) ((int32_t) (verts[vc].sVx * 16.0f) & 0xffff);
voodoo->params.vertexCy = (int32_t) (int16_t) ((int32_t) (verts[vc].sVy * 16.0f) & 0xffff);
if (voodoo->params.vertexAy > voodoo->params.vertexBy || voodoo->params.vertexBy > voodoo->params.vertexCy) {
voodoo_setup_log("triangle_setup wrong order %d %d %d\n", voodoo->params.vertexAy, voodoo->params.vertexBy, voodoo->params.vertexCy);
return;
}
if (voodoo->sSetupMode & SETUPMODE_RGB) {
voodoo->params.startR = (int32_t) (verts[va].sRed * 4096.0f);
voodoo->params.dRdX = (int32_t) (((verts[va].sRed - verts[vb].sRed) * dyBC - (verts[vb].sRed - verts[vc].sRed) * dyAB) * 4096.0f);
voodoo->params.dRdY = (int32_t) (((verts[vb].sRed - verts[vc].sRed) * dxAB - (verts[va].sRed - verts[vb].sRed) * dxBC) * 4096.0f);
voodoo->params.startG = (int32_t) (verts[va].sGreen * 4096.0f);
voodoo->params.dGdX = (int32_t) (((verts[va].sGreen - verts[vb].sGreen) * dyBC - (verts[vb].sGreen - verts[vc].sGreen) * dyAB) * 4096.0f);
voodoo->params.dGdY = (int32_t) (((verts[vb].sGreen - verts[vc].sGreen) * dxAB - (verts[va].sGreen - verts[vb].sGreen) * dxBC) * 4096.0f);
voodoo->params.startB = (int32_t) (verts[va].sBlue * 4096.0f);
voodoo->params.dBdX = (int32_t) (((verts[va].sBlue - verts[vb].sBlue) * dyBC - (verts[vb].sBlue - verts[vc].sBlue) * dyAB) * 4096.0f);
voodoo->params.dBdY = (int32_t) (((verts[vb].sBlue - verts[vc].sBlue) * dxAB - (verts[va].sBlue - verts[vb].sBlue) * dxBC) * 4096.0f);
}
if (voodoo->sSetupMode & SETUPMODE_ALPHA) {
voodoo->params.startA = (int32_t) (verts[va].sAlpha * 4096.0f);
voodoo->params.dAdX = (int32_t) (((verts[va].sAlpha - verts[vb].sAlpha) * dyBC - (verts[vb].sAlpha - verts[vc].sAlpha) * dyAB) * 4096.0f);
voodoo->params.dAdY = (int32_t) (((verts[vb].sAlpha - verts[vc].sAlpha) * dxAB - (verts[va].sAlpha - verts[vb].sAlpha) * dxBC) * 4096.0f);
}
if (voodoo->sSetupMode & SETUPMODE_Z) {
voodoo->params.startZ = (int32_t) (verts[va].sVz * 4096.0f);
voodoo->params.dZdX = (int32_t) (((verts[va].sVz - verts[vb].sVz) * dyBC - (verts[vb].sVz - verts[vc].sVz) * dyAB) * 4096.0f);
voodoo->params.dZdY = (int32_t) (((verts[vb].sVz - verts[vc].sVz) * dxAB - (verts[va].sVz - verts[vb].sVz) * dxBC) * 4096.0f);
}
if (voodoo->sSetupMode & SETUPMODE_Wb) {
voodoo->params.startW = (int64_t) (verts[va].sWb * 4294967296.0f);
voodoo->params.dWdX = (int64_t) (((verts[va].sWb - verts[vb].sWb) * dyBC - (verts[vb].sWb - verts[vc].sWb) * dyAB) * 4294967296.0f);
voodoo->params.dWdY = (int64_t) (((verts[vb].sWb - verts[vc].sWb) * dxAB - (verts[va].sWb - verts[vb].sWb) * dxBC) * 4294967296.0f);
voodoo->params.tmu[0].startW = voodoo->params.tmu[1].startW = voodoo->params.startW;
voodoo->params.tmu[0].dWdX = voodoo->params.tmu[1].dWdX = voodoo->params.dWdX;
voodoo->params.tmu[0].dWdY = voodoo->params.tmu[1].dWdY = voodoo->params.dWdY;
}
if (voodoo->sSetupMode & SETUPMODE_W0) {
voodoo->params.tmu[0].startW = (int64_t) (verts[va].sW0 * 4294967296.0f);
voodoo->params.tmu[0].dWdX = (int64_t) (((verts[va].sW0 - verts[vb].sW0) * dyBC - (verts[vb].sW0 - verts[vc].sW0) * dyAB) * 4294967296.0f);
voodoo->params.tmu[0].dWdY = (int64_t) (((verts[vb].sW0 - verts[vc].sW0) * dxAB - (verts[va].sW0 - verts[vb].sW0) * dxBC) * 4294967296.0f);
voodoo->params.tmu[1].startW = voodoo->params.tmu[0].startW;
voodoo->params.tmu[1].dWdX = voodoo->params.tmu[0].dWdX;
voodoo->params.tmu[1].dWdY = voodoo->params.tmu[0].dWdY;
}
if (voodoo->sSetupMode & SETUPMODE_S0_T0) {
voodoo->params.tmu[0].startS = (int64_t) (verts[va].sS0 * 4294967296.0f);
voodoo->params.tmu[0].dSdX = (int64_t) (((verts[va].sS0 - verts[vb].sS0) * dyBC - (verts[vb].sS0 - verts[vc].sS0) * dyAB) * 4294967296.0f);
voodoo->params.tmu[0].dSdY = (int64_t) (((verts[vb].sS0 - verts[vc].sS0) * dxAB - (verts[va].sS0 - verts[vb].sS0) * dxBC) * 4294967296.0f);
voodoo->params.tmu[0].startT = (int64_t) (verts[va].sT0 * 4294967296.0f);
voodoo->params.tmu[0].dTdX = (int64_t) (((verts[va].sT0 - verts[vb].sT0) * dyBC - (verts[vb].sT0 - verts[vc].sT0) * dyAB) * 4294967296.0f);
voodoo->params.tmu[0].dTdY = (int64_t) (((verts[vb].sT0 - verts[vc].sT0) * dxAB - (verts[va].sT0 - verts[vb].sT0) * dxBC) * 4294967296.0f);
voodoo->params.tmu[1].startS = voodoo->params.tmu[0].startS;
voodoo->params.tmu[1].dSdX = voodoo->params.tmu[0].dSdX;
voodoo->params.tmu[1].dSdY = voodoo->params.tmu[0].dSdY;
voodoo->params.tmu[1].startT = voodoo->params.tmu[0].startT;
voodoo->params.tmu[1].dTdX = voodoo->params.tmu[0].dTdX;
voodoo->params.tmu[1].dTdY = voodoo->params.tmu[0].dTdY;
}
if (voodoo->sSetupMode & SETUPMODE_W1) {
voodoo->params.tmu[1].startW = (int64_t) (verts[va].sW1 * 4294967296.0f);
voodoo->params.tmu[1].dWdX = (int64_t) (((verts[va].sW1 - verts[vb].sW1) * dyBC - (verts[vb].sW1 - verts[vc].sW1) * dyAB) * 4294967296.0f);
voodoo->params.tmu[1].dWdY = (int64_t) (((verts[vb].sW1 - verts[vc].sW1) * dxAB - (verts[va].sW1 - verts[vb].sW1) * dxBC) * 4294967296.0f);
}
if (voodoo->sSetupMode & SETUPMODE_S1_T1) {
voodoo->params.tmu[1].startS = (int64_t) (verts[va].sS1 * 4294967296.0f);
voodoo->params.tmu[1].dSdX = (int64_t) (((verts[va].sS1 - verts[vb].sS1) * dyBC - (verts[vb].sS1 - verts[vc].sS1) * dyAB) * 4294967296.0f);
voodoo->params.tmu[1].dSdY = (int64_t) (((verts[vb].sS1 - verts[vc].sS1) * dxAB - (verts[va].sS1 - verts[vb].sS1) * dxBC) * 4294967296.0f);
voodoo->params.tmu[1].startT = (int64_t) (verts[va].sT1 * 4294967296.0f);
voodoo->params.tmu[1].dTdX = (int64_t) (((verts[va].sT1 - verts[vb].sT1) * dyBC - (verts[vb].sT1 - verts[vc].sT1) * dyAB) * 4294967296.0f);
voodoo->params.tmu[1].dTdY = (int64_t) (((verts[vb].sT1 - verts[vc].sT1) * dxAB - (verts[va].sT1 - verts[vb].sT1) * dxBC) * 4294967296.0f);
}
voodoo->params.vertexAx = (int32_t)(int16_t)((int32_t)(verts[va].sVx * 16.0f) & 0xffff);
voodoo->params.vertexAy = (int32_t)(int16_t)((int32_t)(verts[va].sVy * 16.0f) & 0xffff);
voodoo->params.vertexBx = (int32_t)(int16_t)((int32_t)(verts[vb].sVx * 16.0f) & 0xffff);
voodoo->params.vertexBy = (int32_t)(int16_t)((int32_t)(verts[vb].sVy * 16.0f) & 0xffff);
voodoo->params.vertexCx = (int32_t)(int16_t)((int32_t)(verts[vc].sVx * 16.0f) & 0xffff);
voodoo->params.vertexCy = (int32_t)(int16_t)((int32_t)(verts[vc].sVy * 16.0f) & 0xffff);
voodoo->params.sign = (area < 0.0);
if (voodoo->params.vertexAy > voodoo->params.vertexBy || voodoo->params.vertexBy > voodoo->params.vertexCy) {
voodoo_setup_log("triangle_setup wrong order %d %d %d\n", voodoo->params.vertexAy, voodoo->params.vertexBy, voodoo->params.vertexCy);
return;
}
if (voodoo->ncc_dirty[0])
voodoo_update_ncc(voodoo, 0);
if (voodoo->ncc_dirty[1])
voodoo_update_ncc(voodoo, 1);
voodoo->ncc_dirty[0] = voodoo->ncc_dirty[1] = 0;
if (voodoo->sSetupMode & SETUPMODE_RGB)
{
voodoo->params.startR = (int32_t)(verts[va].sRed * 4096.0f);
voodoo->params.dRdX = (int32_t)(((verts[va].sRed - verts[vb].sRed) * dyBC - (verts[vb].sRed - verts[vc].sRed) * dyAB) * 4096.0f);
voodoo->params.dRdY = (int32_t)(((verts[vb].sRed - verts[vc].sRed) * dxAB - (verts[va].sRed - verts[vb].sRed) * dxBC) * 4096.0f);
voodoo->params.startG = (int32_t)(verts[va].sGreen * 4096.0f);
voodoo->params.dGdX = (int32_t)(((verts[va].sGreen - verts[vb].sGreen) * dyBC - (verts[vb].sGreen - verts[vc].sGreen) * dyAB) * 4096.0f);
voodoo->params.dGdY = (int32_t)(((verts[vb].sGreen - verts[vc].sGreen) * dxAB - (verts[va].sGreen - verts[vb].sGreen) * dxBC) * 4096.0f);
voodoo->params.startB = (int32_t)(verts[va].sBlue * 4096.0f);
voodoo->params.dBdX = (int32_t)(((verts[va].sBlue - verts[vb].sBlue) * dyBC - (verts[vb].sBlue - verts[vc].sBlue) * dyAB) * 4096.0f);
voodoo->params.dBdY = (int32_t)(((verts[vb].sBlue - verts[vc].sBlue) * dxAB - (verts[va].sBlue - verts[vb].sBlue) * dxBC) * 4096.0f);
}
if (voodoo->sSetupMode & SETUPMODE_ALPHA)
{
voodoo->params.startA = (int32_t)(verts[va].sAlpha * 4096.0f);
voodoo->params.dAdX = (int32_t)(((verts[va].sAlpha - verts[vb].sAlpha) * dyBC - (verts[vb].sAlpha - verts[vc].sAlpha) * dyAB) * 4096.0f);
voodoo->params.dAdY = (int32_t)(((verts[vb].sAlpha - verts[vc].sAlpha) * dxAB - (verts[va].sAlpha - verts[vb].sAlpha) * dxBC) * 4096.0f);
}
if (voodoo->sSetupMode & SETUPMODE_Z)
{
voodoo->params.startZ = (int32_t)(verts[va].sVz * 4096.0f);
voodoo->params.dZdX = (int32_t)(((verts[va].sVz - verts[vb].sVz) * dyBC - (verts[vb].sVz - verts[vc].sVz) * dyAB) * 4096.0f);
voodoo->params.dZdY = (int32_t)(((verts[vb].sVz - verts[vc].sVz) * dxAB - (verts[va].sVz - verts[vb].sVz) * dxBC) * 4096.0f);
}
if (voodoo->sSetupMode & SETUPMODE_Wb)
{
voodoo->params.startW = (int64_t)(verts[va].sWb * 4294967296.0f);
voodoo->params.dWdX = (int64_t)(((verts[va].sWb - verts[vb].sWb) * dyBC - (verts[vb].sWb - verts[vc].sWb) * dyAB) * 4294967296.0f);
voodoo->params.dWdY = (int64_t)(((verts[vb].sWb - verts[vc].sWb) * dxAB - (verts[va].sWb - verts[vb].sWb) * dxBC) * 4294967296.0f);
voodoo->params.tmu[0].startW = voodoo->params.tmu[1].startW = voodoo->params.startW;
voodoo->params.tmu[0].dWdX = voodoo->params.tmu[1].dWdX = voodoo->params.dWdX;
voodoo->params.tmu[0].dWdY = voodoo->params.tmu[1].dWdY = voodoo->params.dWdY;
}
if (voodoo->sSetupMode & SETUPMODE_W0)
{
voodoo->params.tmu[0].startW = (int64_t)(verts[va].sW0 * 4294967296.0f);
voodoo->params.tmu[0].dWdX = (int64_t)(((verts[va].sW0 - verts[vb].sW0) * dyBC - (verts[vb].sW0 - verts[vc].sW0) * dyAB) * 4294967296.0f);
voodoo->params.tmu[0].dWdY = (int64_t)(((verts[vb].sW0 - verts[vc].sW0) * dxAB - (verts[va].sW0 - verts[vb].sW0) * dxBC) * 4294967296.0f);
voodoo->params.tmu[1].startW = voodoo->params.tmu[0].startW;
voodoo->params.tmu[1].dWdX = voodoo->params.tmu[0].dWdX;
voodoo->params.tmu[1].dWdY = voodoo->params.tmu[0].dWdY;
}
if (voodoo->sSetupMode & SETUPMODE_S0_T0)
{
voodoo->params.tmu[0].startS = (int64_t)(verts[va].sS0 * 4294967296.0f);
voodoo->params.tmu[0].dSdX = (int64_t)(((verts[va].sS0 - verts[vb].sS0) * dyBC - (verts[vb].sS0 - verts[vc].sS0) * dyAB) * 4294967296.0f);
voodoo->params.tmu[0].dSdY = (int64_t)(((verts[vb].sS0 - verts[vc].sS0) * dxAB - (verts[va].sS0 - verts[vb].sS0) * dxBC) * 4294967296.0f);
voodoo->params.tmu[0].startT = (int64_t)(verts[va].sT0 * 4294967296.0f);
voodoo->params.tmu[0].dTdX = (int64_t)(((verts[va].sT0 - verts[vb].sT0) * dyBC - (verts[vb].sT0 - verts[vc].sT0) * dyAB) * 4294967296.0f);
voodoo->params.tmu[0].dTdY = (int64_t)(((verts[vb].sT0 - verts[vc].sT0) * dxAB - (verts[va].sT0 - verts[vb].sT0) * dxBC) * 4294967296.0f);
voodoo->params.tmu[1].startS = voodoo->params.tmu[0].startS;
voodoo->params.tmu[1].dSdX = voodoo->params.tmu[0].dSdX;
voodoo->params.tmu[1].dSdY = voodoo->params.tmu[0].dSdY;
voodoo->params.tmu[1].startT = voodoo->params.tmu[0].startT;
voodoo->params.tmu[1].dTdX = voodoo->params.tmu[0].dTdX;
voodoo->params.tmu[1].dTdY = voodoo->params.tmu[0].dTdY;
}
if (voodoo->sSetupMode & SETUPMODE_W1)
{
voodoo->params.tmu[1].startW = (int64_t)(verts[va].sW1 * 4294967296.0f);
voodoo->params.tmu[1].dWdX = (int64_t)(((verts[va].sW1 - verts[vb].sW1) * dyBC - (verts[vb].sW1 - verts[vc].sW1) * dyAB) * 4294967296.0f);
voodoo->params.tmu[1].dWdY = (int64_t)(((verts[vb].sW1 - verts[vc].sW1) * dxAB - (verts[va].sW1 - verts[vb].sW1) * dxBC) * 4294967296.0f);
}
if (voodoo->sSetupMode & SETUPMODE_S1_T1)
{
voodoo->params.tmu[1].startS = (int64_t)(verts[va].sS1 * 4294967296.0f);
voodoo->params.tmu[1].dSdX = (int64_t)(((verts[va].sS1 - verts[vb].sS1) * dyBC - (verts[vb].sS1 - verts[vc].sS1) * dyAB) * 4294967296.0f);
voodoo->params.tmu[1].dSdY = (int64_t)(((verts[vb].sS1 - verts[vc].sS1) * dxAB - (verts[va].sS1 - verts[vb].sS1) * dxBC) * 4294967296.0f);
voodoo->params.tmu[1].startT = (int64_t)(verts[va].sT1 * 4294967296.0f);
voodoo->params.tmu[1].dTdX = (int64_t)(((verts[va].sT1 - verts[vb].sT1) * dyBC - (verts[vb].sT1 - verts[vc].sT1) * dyAB) * 4294967296.0f);
voodoo->params.tmu[1].dTdY = (int64_t)(((verts[vb].sT1 - verts[vc].sT1) * dxAB - (verts[va].sT1 - verts[vb].sT1) * dxBC) * 4294967296.0f);
}
voodoo->params.sign = (area < 0.0);
if (voodoo->ncc_dirty[0])
voodoo_update_ncc(voodoo, 0);
if (voodoo->ncc_dirty[1])
voodoo_update_ncc(voodoo, 1);
voodoo->ncc_dirty[0] = voodoo->ncc_dirty[1] = 0;
voodoo_queue_triangle(voodoo, &voodoo->params);
voodoo_queue_triangle(voodoo, &voodoo->params);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff