BitBlt works, but improperly
This commit is contained in:
@@ -78,7 +78,7 @@ typedef struct chips_69000_bitblt_t
|
||||
|
||||
/* BR0A - Source Expansion Foreground Color Register. */
|
||||
uint32_t source_key_fg;
|
||||
};
|
||||
} chips_69000_bitblt_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef struct chips_69000_t {
|
||||
@@ -122,6 +122,13 @@ typedef struct chips_69000_t {
|
||||
|
||||
uint32_t actual_source_height;
|
||||
uint32_t actual_destination_height;
|
||||
|
||||
uint32_t actual_destination_width;
|
||||
|
||||
uint32_t count_x, count_y;
|
||||
uint32_t x, y;
|
||||
int x_dir, y_dir;
|
||||
|
||||
uint8_t bytes_per_pixel;
|
||||
} bitblt_running;
|
||||
|
||||
@@ -144,6 +151,13 @@ typedef struct chips_69000_t {
|
||||
|
||||
static video_timings_t timing_sis = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 4, .read_b = 20, .read_w = 20, .read_l = 35 };
|
||||
|
||||
uint8_t chips_69000_readb_linear(uint32_t addr, void *p);
|
||||
uint16_t chips_69000_readw_linear(uint32_t addr, void *p);
|
||||
uint32_t chips_69000_readl_linear(uint32_t addr, void *p);
|
||||
void chips_69000_writeb_linear(uint32_t addr, uint8_t val, void *p);
|
||||
void chips_69000_writew_linear(uint32_t addr, uint16_t val, void *p);
|
||||
void chips_69000_writel_linear(uint32_t addr, uint32_t val, void *p);
|
||||
|
||||
/* Multimedia handling. */
|
||||
uint8_t
|
||||
chips_69000_read_multimedia(chips_69000_t* chips)
|
||||
@@ -209,6 +223,7 @@ chips_69000_interrupt(chips_69000_t* chips)
|
||||
void
|
||||
chips_69000_bitblt_interrupt(chips_69000_t* chips)
|
||||
{
|
||||
chips->engine_active = 0;
|
||||
chips->mem_regs[1] |= 1 << 31;
|
||||
|
||||
chips_69000_interrupt(chips);
|
||||
@@ -382,6 +397,10 @@ chips_69000_do_rop_24bpp(uint32_t *dst, uint32_t src, uint8_t rop)
|
||||
void
|
||||
chips_69000_do_rop_8bpp_patterned(uint8_t *dst, uint8_t src, uint8_t nonpattern_src, uint8_t rop)
|
||||
{
|
||||
if ((rop & 0xF) == ((rop >> 4) & 0xF)) {
|
||||
return chips_69000_do_rop_8bpp(dst, nonpattern_src, rop);
|
||||
}
|
||||
|
||||
switch (rop) {
|
||||
case 0x00:
|
||||
*dst = 0;
|
||||
@@ -439,6 +458,10 @@ chips_69000_do_rop_8bpp_patterned(uint8_t *dst, uint8_t src, uint8_t nonpattern_
|
||||
void
|
||||
chips_69000_do_rop_16bpp_patterned(uint16_t *dst, uint16_t src, uint8_t nonpattern_src, uint8_t rop)
|
||||
{
|
||||
if ((rop & 0xF) == ((rop >> 4) & 0xF)) {
|
||||
return chips_69000_do_rop_16bpp(dst, nonpattern_src, rop);
|
||||
}
|
||||
|
||||
switch (rop) {
|
||||
case 0x00:
|
||||
*dst = 0;
|
||||
@@ -497,6 +520,11 @@ void
|
||||
chips_69000_do_rop_24bpp_patterned(uint32_t *dst, uint32_t src, uint8_t nonpattern_src, uint8_t rop)
|
||||
{
|
||||
uint32_t orig_dst = *dst & 0xFF000000;
|
||||
|
||||
if ((rop & 0xF) == ((rop >> 4) & 0xF)) {
|
||||
return chips_69000_do_rop_24bpp(dst, nonpattern_src, rop);
|
||||
}
|
||||
|
||||
switch (rop) {
|
||||
case 0x00:
|
||||
*dst = 0;
|
||||
@@ -655,6 +683,99 @@ chips_69000_recalc_banking(chips_69000_t *chips)
|
||||
}*/
|
||||
}
|
||||
|
||||
void
|
||||
chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel)
|
||||
{
|
||||
uint32_t pattern_fg = chips->bitblt_running.bitblt.pattern_source_key_fg;
|
||||
uint32_t pattern_bg = chips->bitblt_running.bitblt.pattern_source_key_bg;
|
||||
uint8_t pattern_data = 0;
|
||||
uint8_t pattern_data_8bpp[8][8];
|
||||
uint16_t pattern_data_16bpp[8][8];
|
||||
uint32_t pattern_pixel = 0;
|
||||
uint32_t dest_pixel = 0;
|
||||
uint32_t dest_addr = chips->bitblt_running.bitblt.destination_addr + (chips->bitblt_running.y * chips->bitblt.destination_span) + (chips->bitblt_running.x * chips->bitblt_running.bytes_per_pixel);
|
||||
uint8_t vert_pat_alignment = (chips->bitblt_running.bitblt.bitblt_control >> 20) & 7;
|
||||
|
||||
switch (chips->bitblt_running.bytes_per_pixel) {
|
||||
case 1: /* 8 bits-per-pixel. */
|
||||
{
|
||||
dest_pixel = chips_69000_readb_linear(dest_addr, chips);
|
||||
break;
|
||||
}
|
||||
case 2: /* 16 bits-per-pixel. */
|
||||
{
|
||||
dest_pixel = chips_69000_readb_linear(dest_addr, chips);
|
||||
dest_pixel |= chips_69000_readb_linear(dest_addr + 1, chips) << 8;
|
||||
break;
|
||||
}
|
||||
case 3: /* 24 bits-per-pixel. */
|
||||
{
|
||||
dest_pixel = chips_69000_readb_linear(dest_addr, chips);
|
||||
dest_pixel |= chips_69000_readb_linear(dest_addr + 1, chips) << 8;
|
||||
dest_pixel |= chips_69000_readb_linear(dest_addr + 2, chips) << 16;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Find out from where it actually pulls the exact pattern x and y values. */
|
||||
if (chips->bitblt_running.bitblt.bitblt_control & (1 << 18)) {
|
||||
uint8_t is_true = 0;
|
||||
if (chips->bitblt_running.bitblt.bitblt_control & (1 << 19))
|
||||
pattern_data = 0;
|
||||
else
|
||||
pattern_data = chips_69000_readb_linear(chips->bitblt_running.bitblt.pat_addr + (vert_pat_alignment + chips->bitblt_running.count_y), chips);
|
||||
|
||||
is_true = !!(pattern_data & (1 << (((chips->bitblt_running.bitblt.destination_addr & 7) + chips->bitblt_running.count_x) & 7)));
|
||||
|
||||
if (!is_true && (chips->bitblt_running.bitblt.bitblt_control & (1 << 17))) {
|
||||
return;
|
||||
}
|
||||
|
||||
pattern_pixel = is_true ? pattern_fg : pattern_bg;
|
||||
|
||||
pattern_pixel &= (1 << (8 * (chips->bitblt_running.bytes_per_pixel))) - 1;
|
||||
}
|
||||
|
||||
switch (chips->bitblt_running.bytes_per_pixel) {
|
||||
case 1: /* 8 bits-per-pixel. */
|
||||
{
|
||||
chips_69000_do_rop_8bpp_patterned((uint8_t*)&dest_pixel, pattern_pixel, pixel, chips->bitblt_running.bitblt.bitblt_control & 0xFF);
|
||||
break;
|
||||
}
|
||||
case 2: /* 16 bits-per-pixel. */
|
||||
{
|
||||
chips_69000_do_rop_16bpp_patterned((uint16_t*)&dest_pixel, pattern_pixel, pixel, chips->bitblt_running.bitblt.bitblt_control & 0xFF);
|
||||
break;
|
||||
}
|
||||
case 3: /* 24 bits-per-pixel. */
|
||||
{
|
||||
chips_69000_do_rop_24bpp_patterned((uint32_t*)&dest_pixel, pattern_pixel, pixel, chips->bitblt_running.bitblt.bitblt_control & 0xFF);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (chips->bitblt_running.bytes_per_pixel) {
|
||||
case 1: /* 8 bits-per-pixel. */
|
||||
{
|
||||
chips_69000_writeb_linear(dest_addr, dest_pixel & 0xFF, chips);
|
||||
break;
|
||||
}
|
||||
case 2: /* 16 bits-per-pixel. */
|
||||
{
|
||||
chips_69000_writeb_linear(dest_addr, dest_pixel & 0xFF, chips);
|
||||
chips_69000_writeb_linear(dest_addr + 1, (dest_pixel >> 8) & 0xFF, chips);
|
||||
break;
|
||||
}
|
||||
case 3: /* 24 bits-per-pixel. */
|
||||
{
|
||||
chips_69000_writeb_linear(dest_addr, dest_pixel & 0xFF, chips);
|
||||
chips_69000_writeb_linear(dest_addr + 1, (dest_pixel >> 8) & 0xFF, chips);
|
||||
chips_69000_writeb_linear(dest_addr + 2, (dest_pixel >> 16) & 0xFF, chips);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
chips_69000_setup_bitblt(chips_69000_t* chips)
|
||||
{
|
||||
@@ -662,14 +783,90 @@ chips_69000_setup_bitblt(chips_69000_t* chips)
|
||||
chips->bitblt_running.bitblt = chips->bitblt;
|
||||
chips->bitblt_running.actual_source_height = chips->bitblt.destination_height;
|
||||
chips->bitblt_running.actual_destination_height = chips->bitblt.destination_height;
|
||||
chips->bitblt_running.count_x = chips->bitblt_running.count_y = 0;
|
||||
|
||||
if (!chips->bitblt_running.actual_destination_height) {
|
||||
chips->bitblt_running.actual_destination_height = 1;
|
||||
if (chips->bitblt.bitblt_control & (1 << 23)) {
|
||||
chips->bitblt_running.bytes_per_pixel = 1 + ((chips->bitblt.bitblt_control >> 24) & 3);
|
||||
} else {
|
||||
chips->bitblt_running.bytes_per_pixel = 1 + ((chips->ext_regs[0x20] >> 4) & 3);
|
||||
}
|
||||
|
||||
|
||||
/*Stubbed!*/
|
||||
chips->engine_active = 0;
|
||||
chips->bitblt_running.actual_destination_width = chips->bitblt_running.bitblt.destination_width / chips->bitblt_running.bytes_per_pixel;
|
||||
|
||||
switch ((chips->bitblt.bitblt_control >> 8) & 3) {
|
||||
case 0:
|
||||
chips->bitblt_running.x = 0;
|
||||
chips->bitblt_running.y = 0;
|
||||
chips->bitblt_running.x_dir = 1;
|
||||
chips->bitblt_running.y_dir = 1;
|
||||
break;
|
||||
case 1:
|
||||
chips->bitblt_running.x = chips->bitblt_running.actual_destination_width - 1;
|
||||
chips->bitblt_running.y = 0;
|
||||
chips->bitblt_running.x_dir = -1;
|
||||
chips->bitblt_running.y_dir = 1;
|
||||
break;
|
||||
case 2:
|
||||
chips->bitblt_running.x = 0;
|
||||
chips->bitblt_running.y = chips->bitblt_running.bitblt.destination_height - 1;
|
||||
chips->bitblt_running.x_dir = 1;
|
||||
chips->bitblt_running.y_dir = -1;
|
||||
break;
|
||||
case 3:
|
||||
chips->bitblt_running.x = chips->bitblt_running.actual_destination_width - 1;
|
||||
chips->bitblt_running.y = chips->bitblt_running.bitblt.destination_height - 1;
|
||||
chips->bitblt_running.x_dir = -1;
|
||||
chips->bitblt_running.y_dir = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (chips->bitblt_running.bitblt.bitblt_control & (1 << 10)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Drawing is pointless if monochrome pattern is enabled, monochrome write-masking is enabled and solid pattern is enabled. */
|
||||
if ((chips->bitblt_running.bitblt.bitblt_control & (1 << 17))
|
||||
&& (chips->bitblt_running.bitblt.bitblt_control & (1 << 18))
|
||||
&& (chips->bitblt_running.bitblt.bitblt_control & (1 << 19))) {
|
||||
chips_69000_bitblt_interrupt(chips);
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
do {
|
||||
uint32_t pixel = 0;
|
||||
uint32_t source_addr = chips->bitblt_running.bitblt.source_addr + (chips->bitblt_running.y * chips->bitblt.source_span) + (chips->bitblt_running.x * chips->bitblt_running.bytes_per_pixel);
|
||||
|
||||
switch (chips->bitblt_running.bytes_per_pixel) {
|
||||
case 1: /* 8 bits-per-pixel. */
|
||||
{
|
||||
pixel = chips_69000_readb_linear(source_addr, chips);
|
||||
break;
|
||||
}
|
||||
case 2: /* 16 bits-per-pixel. */
|
||||
{
|
||||
pixel = chips_69000_readb_linear(source_addr, chips);
|
||||
pixel |= chips_69000_readb_linear(source_addr + 1, chips) << 8;
|
||||
break;
|
||||
}
|
||||
case 3: /* 24 bits-per-pixel. */
|
||||
{
|
||||
pixel = chips_69000_readb_linear(source_addr, chips);
|
||||
pixel |= chips_69000_readb_linear(source_addr + 1, chips) << 8;
|
||||
pixel |= chips_69000_readb_linear(source_addr + 2, chips) << 16;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
chips_69000_process_pixel(chips, pixel);
|
||||
|
||||
chips->bitblt_running.x += chips->bitblt_running.x_dir;
|
||||
} while ((chips->bitblt_running.count_x++) < chips->bitblt_running.actual_destination_width);
|
||||
|
||||
chips->bitblt_running.y += chips->bitblt_running.y_dir;
|
||||
chips->bitblt_running.count_x = 0;
|
||||
} while ((chips->bitblt_running.count_y++) < chips->bitblt_running.actual_destination_height);
|
||||
|
||||
chips_69000_bitblt_interrupt(chips);
|
||||
}
|
||||
|
||||
@@ -708,7 +905,7 @@ chips_69000_read_ext_reg(chips_69000_t* chips)
|
||||
break;
|
||||
case 0x20:
|
||||
val &= ~1;
|
||||
val |= !!(chips->bitblt.bitblt_control & (1 << 31));
|
||||
val |= !!chips->engine_active;
|
||||
/* TODO: Handle BitBLT reset, if required. */
|
||||
break;
|
||||
case 0x63:
|
||||
@@ -729,18 +926,18 @@ chips_69000_read_ext_reg(chips_69000_t* chips)
|
||||
val = 0x0;
|
||||
break;
|
||||
}
|
||||
if (chips->ext_index != 0x4E && chips->ext_index != 0x4F
|
||||
&& (chips->ext_index < 0xE0 || chips->ext_index > 0xEB))
|
||||
pclog("C&T: Read ext reg 0x%02X, ret = 0x%02X\n", index, val);
|
||||
// if (chips->ext_index != 0x4E && chips->ext_index != 0x4F
|
||||
// && (chips->ext_index < 0xE0 || chips->ext_index > 0xEB))
|
||||
// pclog("C&T: Read ext reg 0x%02X, ret = 0x%02X\n", index, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
void
|
||||
chips_69000_write_ext_reg(chips_69000_t* chips, uint8_t val)
|
||||
{
|
||||
if (chips->ext_index != 0x4E && chips->ext_index != 0x4F
|
||||
&& (chips->ext_index < 0xE0 || chips->ext_index > 0xEB))
|
||||
pclog("C&T: Write ext reg 0x%02X, ret = 0x%02X\n", chips->ext_index, val);
|
||||
// if (chips->ext_index != 0x4E && chips->ext_index != 0x4F
|
||||
// && (chips->ext_index < 0xE0 || chips->ext_index > 0xEB))
|
||||
// pclog("C&T: Write ext reg 0x%02X, ret = 0x%02X\n", chips->ext_index, val);
|
||||
switch (chips->ext_index) {
|
||||
case 0xA:
|
||||
chips->ext_regs[chips->ext_index] = val & 0x37;
|
||||
@@ -1119,10 +1316,13 @@ chips_69000_pci_write(int func, int addr, uint8_t val, void *p)
|
||||
uint8_t
|
||||
chips_69000_readb_mmio(uint32_t addr, chips_69000_t* chips)
|
||||
{
|
||||
pclog("C&T Read 0x%X\n", addr);
|
||||
//pclog("C&T Read 0x%X\n", addr);
|
||||
addr &= 0xFFF;
|
||||
switch (addr & 0xFFF) {
|
||||
case 0x00 ... 0x28:
|
||||
if (addr == 0x10) {
|
||||
return (chips->bitblt_regs_b[addr & 0xFF] & 0x7F) | (chips->engine_active ? 0x80 : 0x00);
|
||||
}
|
||||
return chips->bitblt_regs_b[addr & 0xFF];
|
||||
case 0x600 ... 0x60F:
|
||||
return chips->mem_regs_b[addr & 0xF];
|
||||
@@ -1205,12 +1405,12 @@ chips_69000_readl_mmio(uint32_t addr, chips_69000_t* chips)
|
||||
void
|
||||
chips_69000_writeb_mmio(uint32_t addr, uint8_t val, chips_69000_t* chips)
|
||||
{
|
||||
pclog("C&T Write 0x%X, val = 0x%02X\n", addr, val);
|
||||
//pclog("C&T Write 0x%X, val = 0x%02X\n", addr, val);
|
||||
addr &= 0xFFF;
|
||||
switch (addr & 0xFFF) {
|
||||
case 0x00 ... 0x28:
|
||||
chips->bitblt_regs_b[addr & 0xFF] = val;
|
||||
if ((addr & 0xFFF) == 0x023) {
|
||||
if ((addr & 0xFFF) == 0x023 && chips->bitblt_regs[0x8] != 0) {
|
||||
uint8_t cntr = 0;
|
||||
pclog("BitBLT/Draw operation %hd\n", (uint8_t)cntr++);
|
||||
chips_69000_setup_bitblt(chips);
|
||||
|
Reference in New Issue
Block a user