Refactor Hires GRaphics to C

This commit is contained in:
Aaron Culliney 2014-05-18 14:49:05 -07:00
parent 57a01d28a8
commit fd12c8cf53
2 changed files with 235 additions and 297 deletions

View File

@ -21,33 +21,6 @@
#include "cpu.h"
#include "misc.h"
/* -------------------------------------------------------------------------
* Plot a dynamically interpolated swath of pixels.
* For 640x400 this is 2 rows of 18 pixels.
* ebx: from table
* eax: to graphics memory
* ecx: scratch
* ------------------------------------------------------------------------- */
#define PlotPixelsExtra\
subl $2, %eax;\
pushl %edx;\
xorl %edx, %edx;\
PlotPixelsExtraRow;\
addl $SCANWIDTH-18, %eax;\
subl $9, %ebx;\
PlotPixelsExtraRow;\
popl %edx;
#define PlotPixelsExtraRow\
movb $9, %dl;\
1: movb (%ebx), %cl;\
movb %cl, %ch;\
movw %cx, (%eax);\
incl %ebx;\
addl $2, %eax;\
decb %dl;\
jnz 1b;
/* -------------------------------------------------------------------------
* Plots a normalized byte of dhires color directly into graphics memory.
* eax: graphics memory index
@ -68,169 +41,6 @@
subl $4, %eax;\
PlotDHiresByte
/* -------------------------------------------------------------------------
* Calculate the graphics memory offset based on EffectiveAddr.
* BASE 0x2000, 0x4000
* PTR register to store the offset
* ------------------------------------------------------------------------- */
#define CalcHiresGM(BASE,PTR,GM)\
movl EffectiveAddr_E, %ecx; /* ecx = mem addrs */ \
subw BASE, EffectiveAddr; /* - graphics base */ \
movl SN(video__screen_addresses) \
(,EffectiveAddr_E,4), PTR; /* PTR = GM offset */ \
movl %ecx, EffectiveAddr_E; /* + graphics base */ \
addl SN(GM), PTR; /* PTR += GM base */
/* -------------------------------------------------------------------------
* PlotByte - macro to plot a hires byte into graphics memory.
* BASE = 0x2000,0x4000.
* TABLE = expanded_col_hires_even, expanded_col_hires_odd.
* OPP_TABLE = opposite table
* INTERP_COLOR = video__even_colors, video__odd_colors
* ALT_INTERP_COLOR = opposite colors
* ------------------------------------------------------------------------- */
#define PlotByte(BASE,X,TABLE,OPP_TABLE,INTERP_COLOR,ALT_INTERP_COLOR,GM)\
pushl %eax; /* save regs */ \
pushl %ebx; \
pushl %ecx; \
\
xorb %ah, %ah; /* clear noise */ \
PB_dynamic##X:\
leal SN(video__hires_##TABLE)(,%eax,8), %ebx;\
leal SN(temp), %eax; /* eax = temp */\
addl $2, %eax;\
\
/* plot exactly 7 pixels */ \
movl (%ebx), %ecx; /* long -> GM */ \
movl %ecx, (%eax); \
addl $4, %ebx; /* inc pointers */ \
addl $4, %eax; \
movw (%ebx), %cx; /* word -> GM */ \
movw %cx, (%eax); \
addl $2, %ebx; /* inc pointers */ \
addl $2, %eax; \
movb (%ebx), %cl; /* byte -> GM */ \
movb %cl, (%eax); \
\
subl $8, %eax;\
CalcHiresGM(BASE,%ebx,GM); /* ebx = GM */\
/* copy adjacent color bytes into temp array */\
subl $3, %ebx;\
movw (%ebx), %cx;\
movw %cx, (%eax); /* GM -> temp */\
addl $9, %eax;\
addl $18, %ebx;\
movw (%ebx), %cx;\
movw %cx, (%eax); /* GM -> temp */\
decl %eax; \
\
/* ------------------------------------------------------------------------- */ \
/* calculate dynamic colors in temp array */ \
movw (%eax), %cx; \
testb $0xFF, %ch; /* check right color */ \
jz PB_next0##X; /* right black, do other end */ \
movw SN(apple_ii_64k)(,EffectiveAddr_E,1), %cx;\
andb $1, %ch; \
jz PB_black0##X; /* right black */ \
andb $0x40, %cl; \
jz PB_black0##X; /* inside black, right colored */ \
movw $0x3737, (%eax); /* edge is white (#55) */ \
jmp PB_next0##X; \
PB_black0##X: \
movzwl SN(apple_ii_64k)(,EffectiveAddr_E,1), %ecx;\
movzbl %ch, %ecx; \
leal SN(video__hires_##OPP_TABLE) \
(,%ecx,8), %ebx; \
incl %eax; \
movb (%ebx), %cl; \
movb %cl, (%eax); \
decl %eax; \
PB_next0##X: \
decw EffectiveAddr; /* previous byte */ \
subl $7, %eax; /* left edge of byte */ \
movb (%eax), %cl; \
testb $0xFF, %cl; /* check left color */ \
jz PB_next1##X; /* left black, done */ \
movw SN(apple_ii_64k)(,EffectiveAddr_E,1), %cx;\
andb $0x40, %cl; \
jz PB_black1##X; /* left black */ \
andb $0x1, %ch; \
jz PB_black1##X; /* left colored, inside black */ \
movw $0x3737, (%eax); /* edge is white (#55) */ \
jmp PB_next1##X; \
PB_black1##X: \
movzbl SN(apple_ii_64k)(,EffectiveAddr_E,1), %ecx;\
leal SN(video__hires_##OPP_TABLE) \
(,%ecx,8), %ebx; \
addl $6, %ebx; \
movb (%ebx), %cl; \
movb %cl, (%eax); \
PB_next1##X: \
incw EffectiveAddr; \
/* do extra calculation for interpolated colors */ \
cmpb $2, SN(video__strictcolors); \
jne PB_plot_dynamic##X; \
\
decw EffectiveAddr; \
CalculateInterpColor(X,2,ALT_INTERP_COLOR); \
PB_next2##X: \
incw EffectiveAddr; \
incl %eax; \
CalculateInterpColor(X,3,INTERP_COLOR); \
PB_next3##X: \
addl $6, %eax; \
CalculateInterpColor(X,4,INTERP_COLOR); \
PB_next4##X: \
incw EffectiveAddr; \
incl %eax; \
CalculateInterpColor(X,5,ALT_INTERP_COLOR); \
PB_next5##X: \
decw EffectiveAddr; \
/* ------------------------------------------------------------------------- */ \
\
PB_plot_dynamic##X:\
leal SN(temp), %ebx; /* ebx = temp */\
incl %ebx;\
CalcHiresGM(BASE,%eax,GM); /* eax = GM */\
PlotPixelsExtra /* temp -> GM: 1 + 7 + 1 */\
PB_exit##X:\
popl %ecx; /* restore regs */ \
popl %ebx; \
popl %eax;
/* -------------------------------------------------------------------------
* Calculates the color at the edge of interpolated bytes.
* Done 4 times in little endian order (...7 0...7 0...)
* ------------------------------------------------------------------------- */
#define CalculateInterpColor(X,Y,INTERP_COLOR) \
testb $0xFF, (%eax); \
jnz PB_next##Y##X; /* not black, next */ \
movw (%eax), %cx; /* off+1 in %ch */ \
testb $0xFF, %ch; \
jz PB_next##Y##X; /* off+1 is black, next */ \
movb -1(%eax), %cl; /* off-1 in %cl */ \
testb $0xFF, %cl; \
jz PB_next##Y##X; /* off-1 is black, next */ \
cmpb $55, %cl; /* off-1 is white? */ \
je PB_white0##X##Y; \
movb %cl, (%eax); /* store non-white */ \
jmp PB_next##Y##X; /* next */ \
PB_white0##X##Y: \
cmpb $55, %ch; /* off+1 is white? */ \
je PB_white##X##Y; \
movb %ch, (%eax); /* store non-white */ \
jmp PB_next##Y##X; /* next */ \
PB_white##X##Y: /* both sides are white */ \
movzbl SN(apple_ii_64k)(,EffectiveAddr_E,1), %ecx;\
shrb $7, %cl; \
movb SN(INTERP_COLOR)(,%ecx,1), %bl; \
movb %bl, (%eax);
/* -------------------------------------------------------------------------
* compeletely update all the hires/dhires page rows.
* X=0,1
@ -444,113 +254,6 @@ E(video_redraw)
ret
/******************************************/
#define DRAW_GRAPHICS(PARITY, PAGE, TEXT_SW) \
testl TEXT_SW, SN(softswitches); \
jnz ram_nop /* text */; \
testl $SS_HIRES, SN(softswitches); \
jz ram_nop /* lores */; \
testl $SS_80COL, SN(softswitches); \
jz 1f; \
testl $SS_DHIRES, SN(softswitches); \
jnz iie_plot_dhires##PAGE /* plot dhires */; \
1: testl $SS_HGRWRT, SN(softswitches); \
jnz ram_nop /* in auxram */; \
call plot_##PARITY##_byte##PAGE /* plot hires */; \
ret;
#if 1
/* video__write_2e_even0 - handle hires page //e specific */
E(video__write_2e_even0)
addl SN(base_hgrwrt), EffectiveAddr_E
movb %al, (EffectiveAddr_E)
subl SN(base_hgrwrt), EffectiveAddr_E
iie_soft_write_even0:
DRAW_GRAPHICS(even, 0, $SS_TEXT)
/* video__write_2e_even0_mixed - handle mixed hires page //e specific */
E(video__write_2e_even0_mixed)
addl SN(base_hgrwrt), EffectiveAddr_E
movb %al, (EffectiveAddr_E)
subl SN(base_hgrwrt), EffectiveAddr_E
iie_soft_write_even0_mixed:
DRAW_GRAPHICS(even, 0, $(SS_TEXT|SS_MIXED))
/* video__write_2e_odd0 - handle hires page //e specific */
E(video__write_2e_odd0)
addl SN(base_hgrwrt), EffectiveAddr_E
movb %al, (EffectiveAddr_E)
subl SN(base_hgrwrt), EffectiveAddr_E
iie_soft_write_odd0:
DRAW_GRAPHICS(odd, 0, $SS_TEXT)
/* video__write_2e_odd0_mixed - handle mixed hires page //e specific */
E(video__write_2e_odd0_mixed)
addl SN(base_hgrwrt), EffectiveAddr_E
movb %al, (EffectiveAddr_E)
subl SN(base_hgrwrt), EffectiveAddr_E
iie_soft_write_odd0_mixed:
DRAW_GRAPHICS(odd, 0, $(SS_TEXT|SS_MIXED))
/* video__write_2e_even1 - write hires page1 //e specific */
E(video__write_2e_even1)
addl SN(base_ramwrt), EffectiveAddr_E
movb %al, (EffectiveAddr_E)
subl SN(base_ramwrt), EffectiveAddr_E
iie_soft_write_even1:
DRAW_GRAPHICS(even, 1, $SS_TEXT)
/* video__write_2e_even1_mixed - write hires page1 //e specific */
E(video__write_2e_even1_mixed)
addl SN(base_ramwrt), EffectiveAddr_E
movb %al, (EffectiveAddr_E)
subl SN(base_ramwrt), EffectiveAddr_E
iie_soft_write_even1_mixed:
DRAW_GRAPHICS(even, 1, $(SS_TEXT|SS_MIXED))
/* video__write_2e_odd1 - write hires page1 //e specific */
E(video__write_2e_odd1)
addl SN(base_ramwrt), EffectiveAddr_E
movb %al, (EffectiveAddr_E)
subl SN(base_ramwrt), EffectiveAddr_E
iie_soft_write_odd1:
DRAW_GRAPHICS(odd, 1, $SS_TEXT)
/* video__write_2e_odd1_mixed - write hires page1 //e specific */
E(video__write_2e_odd1_mixed)
addl SN(base_ramwrt), EffectiveAddr_E
movb %al, (EffectiveAddr_E)
subl SN(base_ramwrt), EffectiveAddr_E
iie_soft_write_odd1_mixed:
DRAW_GRAPHICS(odd, 1, $(SS_TEXT|SS_MIXED))
/* plot even column hires byte on page 0 */
.align 4
plot_even_byte0:
PlotByte($0x2000,0,even,odd,video__even_colors,video__odd_colors,video__fb1)
ret
/* plot odd column hires byte on page 0 */
.align 4
plot_odd_byte0:
PlotByte($0x2000,1,odd,even,video__odd_colors,video__even_colors,video__fb1)
ret
/* plot even column hires byte on page 1 */
.align 4
plot_even_byte1:
PlotByte($0x4000,2,even,odd,video__even_colors,video__odd_colors,video__fb2)
ret
/* plot odd column hires byte on page 1 */
.align 4
plot_odd_byte1:
PlotByte($0x4000,3,odd,even,video__odd_colors,video__even_colors,video__fb2)
ret
#endif
E(iie_plot_dhires0)
PlotDHires($0x2000,0,video__fb1)
@ -559,3 +262,4 @@ E(iie_plot_dhires0)
E(iie_plot_dhires1)
PlotDHires($0x4000,1,video__fb2)
ret

View File

@ -16,6 +16,8 @@
#include "common.h"
#define DYNAMIC_SZ 11 // 7 pixels (as bytes) + 2pre + 2post
#define TEXT_ROWS 24
#define BEGIN_MIX 20
#define TEXT_COLS 40
@ -684,3 +686,235 @@ GLUE_C_WRITE(video__write_2e_text1_mixed)
c_iie_soft_write_text1_mixed(ea, b);
}
// ----------------------------------------------------------------------------
// Hires (and Double-Hires) GRaphics
// CalculateInterpColor
static inline void _calculate_interp_color(uint8_t *color_buf, const unsigned int idx, const uint8_t *interp_base, const uint16_t ea) {
if (color_buf[idx] != 0x0) {
return;
}
uint8_t pixR = color_buf[idx+1];
if (pixR == 0x0) {
return;
}
uint8_t pixL = color_buf[idx-1];
if (pixL == 0x0) {
return;
}
// Calculates the color at the edge of interpolated bytes: called 4 times in little endian order (...7 0...7 0...)
if (pixL == COLOR_LIGHT_WHITE) {
if (pixR == COLOR_LIGHT_WHITE) {
pixL = apple_ii_64k[0][ea];
color_buf[idx] = interp_base[pixL>>7];
} else {
color_buf[idx] = pixR;
}
} else {
color_buf[idx] = pixL;
}
}
// PlotPixelsExtra
static inline void _plot_pixels(uint8_t *dst, const uint8_t *src) {
uint8_t pix;
for (unsigned int i=2; i; i--) {
for (unsigned int j=DYNAMIC_SZ-1; j; j--) {
uint16_t pix = *src;
pix = ((pix<<8) | pix);
*((uint16_t *)dst) = pix;
++src;
dst+=2;
}
dst += (SCANWIDTH-18);
src -= DYNAMIC_SZ-2;
}
}
// PlotByte
static inline void _plot_hires(uint16_t ea, uint8_t b, bool is_even, uint8_t *fb_ptr) {
uint8_t *hires_altbase = NULL;
uint8_t *interp_base = NULL;
uint8_t color_buf[DYNAMIC_SZ];
uint8_t *hires_ptr = NULL;
if (is_even) {
hires_ptr = (uint8_t *)&video__hires_even[b<<3];
hires_altbase = (uint8_t *)&video__hires_odd[0];
interp_base = (uint8_t *)&video__even_colors[0];
} else {
hires_ptr = (uint8_t *)&video__hires_odd[b<<3];
hires_altbase = (uint8_t *)&video__hires_even[0];
interp_base = (uint8_t *)&video__odd_colors[0];
}
*((uint32_t *)&color_buf[2]) = *((uint32_t *)(hires_ptr+0));
*((uint16_t *)&color_buf[6]) = *((uint16_t *)(hires_ptr+4));
*((uint8_t *)&color_buf[8]) = *((uint8_t *)(hires_ptr+6));
hires_ptr = NULL;
// copy adjacent pixel bytes
*((uint16_t *)&color_buf[0]) = *((uint16_t *)(fb_ptr-3));
*((uint16_t *)&color_buf[DYNAMIC_SZ-2]) = *((uint16_t *)(fb_ptr+15));
// %eax = +8
if (color_mode != COLOR_NONE) {
// if right-side color is not black, re-calculate edge values
if (color_buf[DYNAMIC_SZ-2] & 0xff) {
uint16_t pix16 = *((uint16_t *)&apple_ii_64k[0][ea]);
if ((pix16 & 0x100) && (pix16 & 0x40)) {
*((uint16_t *)&color_buf[DYNAMIC_SZ-3]) = (uint16_t)0x3737;// COLOR_LIGHT_WHITE
} else {
// PB_black0:
pix16 >>= 8;
color_buf[DYNAMIC_SZ-2] = hires_altbase[pix16<<3];
}
}
// if left-side color is not black, re-calculate edge values
if (color_buf[1] & 0xff) {
uint16_t pix16 = *((uint16_t *)&apple_ii_64k[0][ea-1]);
if ((pix16 & 0x100) && (pix16 & 0x40)) {
*((uint16_t *)&color_buf[1]) = (uint16_t)0x3737;// COLOR_LIGHT_WHITE
} else {
// PB_black1:
pix16 &= 0xFF;
color_buf[1] = hires_altbase[(pix16<<3)+6];
}
}
if (color_mode == COLOR_INTERP) {
// calculate interpolated/bleed colors
_calculate_interp_color(color_buf, 1, interp_base, ea-1);
_calculate_interp_color(color_buf, 2, interp_base, ea);
_calculate_interp_color(color_buf, 8, interp_base, ea);
_calculate_interp_color(color_buf, 9, interp_base, ea+1);
}
}
_plot_pixels(fb_ptr-4, color_buf);
}
// DRAW_GRAPHICS
static inline void _draw_hires_graphics(uint16_t ea, uint8_t b, bool is_even, uint8_t page, unsigned int ss_textflags) {
if (softswitches & ss_textflags) {
return;
}
if (!(softswitches & SS_HIRES)) {
return;
}
if ((softswitches & SS_80COL) && (softswitches & SS_DHIRES)) {
if (page) {
extern void iie_plot_dhires1();
iie_plot_dhires1();
} else {
extern void iie_plot_dhires0();
iie_plot_dhires0();
}
return;
}
if (softswitches & SS_HGRWRT) {
return;
}
uint16_t off = ea - 0x2000;
uint8_t *fb_base = NULL;
if (page) {
off -= 0x2000;
fb_base = video__fb2;
} else {
fb_base = video__fb1;
}
_plot_hires(ea, b, is_even, fb_base+video__screen_addresses[off]);
}
GLUE_C_WRITE(iie_soft_write_even0) // refactor : remove
{
_draw_hires_graphics(ea, b, /*even*/true, 0, SS_TEXT);
}
GLUE_C_WRITE(video__write_2e_even0)
{
base_hgrwrt[ea] = b;
_draw_hires_graphics(ea, b, /*even*/true, 0, SS_TEXT);
}
GLUE_C_WRITE(iie_soft_write_even0_mixed) // refactor : remove
{
_draw_hires_graphics(ea, b, /*even*/true, 0, (SS_TEXT|SS_MIXED));
}
GLUE_C_WRITE(video__write_2e_even0_mixed)
{
base_hgrwrt[ea] = b;
_draw_hires_graphics(ea, b, /*even*/true, 0, (SS_TEXT|SS_MIXED));
}
GLUE_C_WRITE(iie_soft_write_odd0) // refactor : remove
{
_draw_hires_graphics(ea, b, /*even*/false, 0, SS_TEXT);
}
GLUE_C_WRITE(video__write_2e_odd0)
{
base_hgrwrt[ea] = b;
_draw_hires_graphics(ea, b, /*even*/false, 0, SS_TEXT);
}
GLUE_C_WRITE(iie_soft_write_odd0_mixed) // refactor : remove
{
_draw_hires_graphics(ea, b, /*even*/false, 0, (SS_TEXT|SS_MIXED));
}
GLUE_C_WRITE(video__write_2e_odd0_mixed)
{
base_hgrwrt[ea] = b;
_draw_hires_graphics(ea, b, /*even*/false, 0, (SS_TEXT|SS_MIXED));
}
GLUE_C_WRITE(iie_soft_write_even1) // refactor : remove
{
_draw_hires_graphics(ea, b, /*even*/true, 1, SS_TEXT);
}
GLUE_C_WRITE(video__write_2e_even1)
{
base_ramwrt[ea] = b;
_draw_hires_graphics(ea, b, /*even*/true, 1, SS_TEXT);
}
GLUE_C_WRITE(iie_soft_write_even1_mixed) // refactor : remove
{
_draw_hires_graphics(ea, b, /*even*/true, 1, (SS_TEXT|SS_MIXED));
}
GLUE_C_WRITE(video__write_2e_even1_mixed)
{
base_ramwrt[ea] = b;
_draw_hires_graphics(ea, b, /*even*/true, 1, (SS_TEXT|SS_MIXED));
}
GLUE_C_WRITE(iie_soft_write_odd1) // refactor : remove
{
_draw_hires_graphics(ea, b, /*even*/false, 1, SS_TEXT);
}
GLUE_C_WRITE(video__write_2e_odd1)
{
base_ramwrt[ea] = b;
_draw_hires_graphics(ea, b, /*even*/false, 1, SS_TEXT);
}
GLUE_C_WRITE(iie_soft_write_odd1_mixed) // refactor : remove
{
_draw_hires_graphics(ea, b, /*even*/false, 1, (SS_TEXT|SS_MIXED));
}
GLUE_C_WRITE(video__write_2e_odd1_mixed)
{
base_ramwrt[ea] = b;
_draw_hires_graphics(ea, b, /*even*/false, 1, (SS_TEXT|SS_MIXED));
}