Refactor all drawing to run on video thread in one scanner pass

- Moves extra work off CPU/audio thread
    - Prepares the way to possibly remove the vestigal intermediate indexed framebuffer and do direct RGBA_8888 writes
      to XImage or OpenGL texture
    - Prepares the ground for possible better emulation of video scanner hardware

Conflicts:
	src/display.c
	src/video/glvideo.c
	src/video/video.h
This commit is contained in:
Aaron Culliney 2016-01-20 21:56:25 -08:00
parent bd9b38cd65
commit 829291feba
12 changed files with 319 additions and 380 deletions

View File

@ -31,8 +31,6 @@ void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetColor(JNIEnv *env, jc
color_mode = color;
video_reset();
video_setpage(!!(softswitches & SS_SCREEN));
video_redraw();
#endif
}

View File

@ -216,8 +216,6 @@
#warning HACK TODO FIXME need to refactor video resetting procedure
video_reset();
video_setpage(!!(softswitches & SS_SCREEN));
video_redraw();
}
- (IBAction)soundCardChoiceChanged:(id)sender

View File

@ -21,14 +21,19 @@
#define DYNAMIC_SZ 11 // 7 pixels (as bytes) + 2pre + 2post
typedef enum drawpage_mode_t {
DRAWPAGE_TEXT = 1,
DRAWPAGE_HIRES,
} drawpage_mode_t;
// framebuffers
static uint8_t vga_mem_page_0[SCANWIDTH*SCANHEIGHT] = { 0 };
static uint8_t vga_mem_page_1[SCANWIDTH*SCANHEIGHT] = { 0 };
static uint8_t *video__fb = NULL;
A2Color_s colormap[256] = { { 0 } };
video_animation_s *video_animations = NULL;
video_backend_s *video_backend = NULL;
static pthread_t render_thread_id = 0;
static pthread_mutex_t video_scan_mutex = PTHREAD_MUTEX_INITIALIZER;
static uint8_t video__wider_font[0x8000] = { 0 };
static uint8_t video__font[0x4000] = { 0 };
@ -38,13 +43,10 @@ static uint8_t video__int_font[3][0x4000] = { { 0 } }; // interface font
unsigned int video__screen_addresses[8192] = { INT_MIN };
uint8_t video__columns[8192] = { 0 };
uint8_t *video__fb1 = NULL;
uint8_t *video__fb2 = NULL;
uint8_t video__hires_even[0x800] = { 0 };
uint8_t video__hires_odd[0x800] = { 0 };
int video__current_page = 0; // current visual page
volatile unsigned long _vid_dirty = 0;
// Video constants -- sourced from AppleWin
static const bool bVideoScannerNTSC = true;
@ -475,6 +477,7 @@ static void _initialize_color() {
void video_reset(void) {
_initialize_hires_values();
_initialize_tables_video();
video_setDirty(A2_DIRTY_FLAG);
}
void video_loadfont(int first, int quantity, const uint8_t *data, int mode) {
@ -578,7 +581,7 @@ static inline void _plot_char80(uint8_t **d, uint8_t **s, const unsigned int fb_
*d += fb_width-6, *s += 2;
}
static inline void _plot_lores(uint8_t **d, const uint32_t val) {
static inline void _plot_lores40(uint8_t **d, const uint32_t val) {
*((uint32_t *)(*d)) = val;
*d += 4;
*((uint32_t *)(*d)) = val;
@ -596,7 +599,7 @@ static inline void _plot_lores(uint8_t **d, const uint32_t val) {
*((uint16_t *)(*d)) = (uint16_t)(val & 0xffff);
}
static inline void _plot_dlores(uint8_t **d, const uint32_t val) {
static inline void _plot_lores80(uint8_t **d, const uint32_t val) {
*((uint32_t *)(*d)) = val;
*d += 4;
*((uint16_t *)(*d)) = (uint16_t)val;
@ -610,8 +613,7 @@ static inline void _plot_dlores(uint8_t **d, const uint32_t val) {
*((uint8_t *)(*d)) = (uint8_t)val;
}
static inline void _plot_character(const unsigned int font_off, uint8_t *fb_ptr) {
video_setDirty();
static inline void __plot_character40(const unsigned int font_off, uint8_t *fb_ptr) {
uint8_t *font_ptr = video__wider_font+font_off;
_plot_char40(/*dst*/&fb_ptr, /*src*/&font_ptr);
_plot_char40(/*dst*/&fb_ptr, /*src*/&font_ptr);
@ -623,16 +625,14 @@ static inline void _plot_character(const unsigned int font_off, uint8_t *fb_ptr)
_plot_char40(/*dst*/&fb_ptr, /*src*/&font_ptr);
}
static void _plot_character0(uint16_t ea, uint8_t b) {
_plot_character(b<<7/* *128 */, video__fb1+video__screen_addresses[ea-0x0400]);
static void _plot_character40(uint16_t off, int page, int bank) {
uint16_t base = page ? 0x0800 : 0x0400;
uint16_t ea = base+off;
uint8_t b = apple_ii_64k[bank][ea];
__plot_character40(b<<7/* *128 */, video__fb+video__screen_addresses[off]);
}
static void _plot_character1(uint16_t ea, uint8_t b) {
_plot_character(b<<7/* *128 */, video__fb2+video__screen_addresses[ea-0x0800]);
}
static inline void _plot_80character(const unsigned int font_off, uint8_t *fb_ptr) {
video_setDirty();
static inline void __plot_character80(const unsigned int font_off, uint8_t *fb_ptr) {
uint8_t *font_ptr = video__font+font_off;
_plot_char80(/*dst*/&fb_ptr, /*src*/&font_ptr, SCANWIDTH);
_plot_char80(/*dst*/&fb_ptr, /*src*/&font_ptr, SCANWIDTH);
@ -644,186 +644,168 @@ static inline void _plot_80character(const unsigned int font_off, uint8_t *fb_pt
_plot_char80(/*dst*/&fb_ptr, /*src*/&font_ptr, SCANWIDTH);
}
// FIXME TODO NOTE : dup'ing work here?
static void _plot_80character0(uint16_t ea, uint8_t b) {
b = apple_ii_64k[1][ea];
_plot_80character(b<<6/* *64 */, video__fb1+video__screen_addresses[ea-0x0400]);
b = apple_ii_64k[0][ea];
_plot_80character(b<<6/* *64 */, video__fb1+video__screen_addresses[ea-0x0400]+7);
static void _plot_character80(uint16_t off, int page, int bank) {
uint16_t base = page ? 0x0800 : 0x0400;
uint16_t ea = base+off;
{
uint8_t b = apple_ii_64k[1][ea];
__plot_character80(b<<6/* *64 */, video__fb+video__screen_addresses[off]);
}
{
uint8_t b = apple_ii_64k[0][ea];
__plot_character80(b<<6/* *64 */, video__fb+video__screen_addresses[off]+7);
}
}
static void _plot_80character1(uint16_t ea, uint8_t b) {
b = apple_ii_64k[1][ea];
_plot_80character(b<<6/* *64 */, video__fb2+video__screen_addresses[ea-0x0800]);
b = apple_ii_64k[0][ea];
_plot_80character(b<<6/* *64 */, video__fb2+video__screen_addresses[ea-0x0800]+7);
}
static inline void _plot_block(const uint8_t val, uint8_t *fb_ptr) {
video_setDirty();
static inline void __plot_block40(const uint8_t val, uint8_t *fb_ptr) {
uint8_t color = (val & 0x0F) << 4;
uint32_t val32 = (color << 24) | (color << 16) | (color << 8) | color;
_plot_lores(/*dst*/&fb_ptr, val32);
_plot_lores40(/*dst*/&fb_ptr, val32);
fb_ptr += SCANSTEP;
_plot_lores(/*dst*/&fb_ptr, val32);
_plot_lores40(/*dst*/&fb_ptr, val32);
fb_ptr += SCANSTEP;
_plot_lores(/*dst*/&fb_ptr, val32);
_plot_lores40(/*dst*/&fb_ptr, val32);
fb_ptr += SCANSTEP;
_plot_lores(/*dst*/&fb_ptr, val32);
_plot_lores40(/*dst*/&fb_ptr, val32);
fb_ptr += SCANSTEP;
color = val & 0xF0;
val32 = (color << 24) | (color << 16) | (color << 8) | color;
_plot_lores(/*dst*/&fb_ptr, val32);
_plot_lores40(/*dst*/&fb_ptr, val32);
fb_ptr += SCANSTEP;
_plot_lores(/*dst*/&fb_ptr, val32);
_plot_lores40(/*dst*/&fb_ptr, val32);
fb_ptr += SCANSTEP;
_plot_lores(/*dst*/&fb_ptr, val32);
_plot_lores40(/*dst*/&fb_ptr, val32);
fb_ptr += SCANSTEP;
_plot_lores(/*dst*/&fb_ptr, val32);
_plot_lores40(/*dst*/&fb_ptr, val32);
}
/* plot lores block first page */
static inline void _plot_block0(uint16_t ea, uint8_t b)
{
_plot_block(b, video__fb1+video__screen_addresses[ea-0x0400]);
static void _plot_block40(uint16_t off, int page, int bank) {
uint16_t base = page ? 0x0800 : 0x0400;
uint16_t ea = base+off;
uint8_t b = apple_ii_64k[bank][ea];
__plot_block40(b, video__fb+video__screen_addresses[off]);
}
static inline void _plot_block1(uint16_t ea, uint8_t b)
{
_plot_block(b, video__fb2+video__screen_addresses[ea-0x0800]);
}
static inline void _plot_dblock(const uint8_t val, uint8_t *fb_ptr) {
static inline void __plot_block80(const uint8_t val, uint8_t *fb_ptr) {
uint8_t color = (val & 0x0F) << 4;
uint32_t val32 = (color << 24) | (color << 16) | (color << 8) | color;
_plot_dlores(/*dst*/&fb_ptr, val32);
_plot_lores80(/*dst*/&fb_ptr, val32);
fb_ptr += SCANDSTEP;
_plot_dlores(/*dst*/&fb_ptr, val32);
_plot_lores80(/*dst*/&fb_ptr, val32);
fb_ptr += SCANDSTEP;
_plot_dlores(/*dst*/&fb_ptr, val32);
_plot_lores80(/*dst*/&fb_ptr, val32);
fb_ptr += SCANDSTEP;
_plot_dlores(/*dst*/&fb_ptr, val32);
_plot_lores80(/*dst*/&fb_ptr, val32);
fb_ptr += SCANDSTEP;
color = val & 0xF0;
val32 = (color << 24) | (color << 16) | (color << 8) | color;
_plot_dlores(/*dst*/&fb_ptr, val32);
_plot_lores80(/*dst*/&fb_ptr, val32);
fb_ptr += SCANDSTEP;
_plot_dlores(/*dst*/&fb_ptr, val32);
_plot_lores80(/*dst*/&fb_ptr, val32);
fb_ptr += SCANDSTEP;
_plot_dlores(/*dst*/&fb_ptr, val32);
_plot_lores80(/*dst*/&fb_ptr, val32);
fb_ptr += SCANDSTEP;
_plot_dlores(/*dst*/&fb_ptr, val32);
_plot_lores80(/*dst*/&fb_ptr, val32);
}
/* plot double-lores block first page */
static inline void _plot_dblock0(uint16_t ea, uint8_t b, bool odd) {
uint8_t *fb = video__fb1+video__screen_addresses[ea-0x0400] + (odd ? 7 : 0);
_plot_dblock(b, fb);
static inline uint8_t __shift_block80(uint8_t b) {
// plot even half-block from auxmem, rotate nybbles to match color (according to UTAIIe: 8-29)
uint8_t b0 = (b & 0x0F);
uint8_t b1 = (b & 0xF0) >> 4;
uint8_t rot0 = ((b0 & 0x8) >> 3);
uint8_t rot1 = ((b1 & 0x8) >> 3);
b0 = (((b0<<5) | (rot0<<4)) >> 4);
b1 = ((b1<<5) | (rot1<<4));
b = b0 | b1;
return b;
}
static inline void _plot_dblock1(uint16_t ea, uint8_t b, bool odd) {
uint8_t *fb = video__fb2+video__screen_addresses[ea-0x0800] + (odd ? 7 : 0);
_plot_dblock(b, fb);
static void _plot_block80(uint16_t off, int page, int bank) {
uint16_t base = page ? 0x0800 : 0x0400;
uint16_t ea = base+off;
#warning FIXME TODO INVESTIGATE : ... does RAMRD/80STORE/PAGE2 affect load order here?
// plot even half-block from auxmem, rotate nybbles to match color (according to UTAIIe)
{
uint8_t b = apple_ii_64k[1][ea];
b = __shift_block80(b);
uint8_t *fb = video__fb+video__screen_addresses[off];
__plot_block80(b, fb);
}
// plot odd half-block from main mem
{
uint8_t b = apple_ii_64k[0][ea];
uint8_t *fb = video__fb+video__screen_addresses[off] + 7;
__plot_block80(b, fb);
}
}
static inline void _draw_text(uint16_t ea, uint8_t b, int page, uint32_t sw, uint32_t flags) {
if (softswitches & flags) {
if (softswitches & SS_80COL) {
void (*plot80Fn)(uint16_t, uint8_t) = !page ? _plot_80character0 : _plot_80character1;
plot80Fn(ea,b);
} else if (softswitches & sw) {
/* ??? */
} else {
void (*plotCharFn)(uint16_t, uint8_t) = !page ? _plot_character0 : _plot_character1;
plotCharFn(ea, b);
}
static void (*_textpage_plotter(uint32_t currswitches, uint32_t txtflags))(uint16_t, int, int) {
void (*plotFn)(uint16_t, int, int) = NULL;
if (currswitches & txtflags) {
plotFn = (currswitches & SS_80COL) ? _plot_character80 : _plot_character40;
} else {
if (softswitches & (SS_HIRES|sw)) {
/* ??? */
} else {
if (!(softswitches & SS_80COL)) {
void (*plotBlockFn)(uint16_t, uint8_t) = !page ? _plot_block0 : _plot_block1;
if (!(softswitches & SS_DHIRES)) {
// LORES40 ...
plotBlockFn(ea, b);
} else {
// TODO : abnormal LORES output. See UTAIIe : 8-28
plotBlockFn(ea, b);
}
assert(!(currswitches & SS_HIRES) && "must be lores graphics or programmer error");
if (!(currswitches & SS_80COL)) {
plotFn = _plot_block40;
if (!(currswitches & SS_DHIRES)) {
// LORES40 ...
} else {
if (softswitches & SS_DHIRES) {
// LORES80 ...
void (*plotBlockFn)(uint16_t, uint8_t, bool) = !page ? _plot_dblock0 : _plot_dblock1;
// plot even half-block from auxmem, rotate nybbles to match color (according to UTAIIe)
b = apple_ii_64k[1][ea];
uint8_t b0 = (b & 0x0F);
uint8_t b1 = (b & 0xF0) >> 4;
uint8_t rot0 = ((b0 & 0x8) >> 3);
uint8_t rot1 = ((b1 & 0x8) >> 3);
b0 = (((b0<<5) | (rot0<<4)) >> 4);
b1 = ((b1<<5) | (rot1<<4));
b = b0 | b1;
plotBlockFn(ea, b, false);
// plot odd half-block from main mem
b = apple_ii_64k[0][ea];
plotBlockFn(ea, b, true);
video_setDirty();
} else {
/* ??? */
void (*plotBlockFn)(uint16_t, uint8_t) = !page ? _plot_block0 : _plot_block1;
plotBlockFn(ea, b);
}
// TODO : abnormal LORES output. See UTAIIe : 8-28
}
} else {
if (currswitches & SS_DHIRES) {
// LORES80 ...
plotFn = _plot_block80;
} else {
/* ??? */
RELEASE_LOG("!!!!!!!!!!!! what mode is this? !!!!!!!!!!!!");
plotFn = _plot_block40;
#warning FIXME TODO ... verify this lores40/lores80 mode ...
}
}
}
return plotFn;
}
GLUE_C_WRITE(video__write_2e_text0)
{
base_textwrt[ea] = b;
if (!(softswitches & SS_PAGE2)) {
_draw_text(ea, b, 0, SS_TEXTWRT, SS_TEXT);
}
video_setDirty(A2_DIRTY_FLAG);
}
GLUE_C_WRITE(video__write_2e_text0_mixed)
{
base_textwrt[ea] = b;
if (!(softswitches & SS_PAGE2)) {
_draw_text(ea, b, 0, SS_TEXTWRT, (SS_TEXT|SS_MIXED));
}
video_setDirty(A2_DIRTY_FLAG);
}
GLUE_C_WRITE(video__write_2e_text1)
{
base_ramwrt[ea] = b;
if (softswitches & SS_PAGE2) {
_draw_text(ea, b, 1, SS_RAMWRT, SS_TEXT);
}
video_setDirty(A2_DIRTY_FLAG);
}
GLUE_C_WRITE(video__write_2e_text1_mixed)
{
base_ramwrt[ea] = b;
if (softswitches & SS_PAGE2) {
_draw_text(ea, b, 1, SS_RAMWRT, (SS_TEXT|SS_MIXED));
}
video_setDirty(A2_DIRTY_FLAG);
}
// ----------------------------------------------------------------------------
// Classic interface and printing HUD messages
void interface_plotChar(uint8_t *fboff, int fb_pix_width, interface_colorscheme_t cs, uint8_t c) {
video_setDirty();
uint8_t *src = video__int_font[cs] + c * (FONT_GLYPH_X*FONT_GLYPH_Y);
_plot_char80(&fboff, &src, fb_pix_width);
_plot_char80(&fboff, &src, fb_pix_width);
@ -836,10 +818,9 @@ void interface_plotChar(uint8_t *fboff, int fb_pix_width, interface_colorscheme_
}
// ----------------------------------------------------------------------------
// Double-Hires GRaphics
// Double-HIRES (HIRES80) graphics
// PlotDHiresByte
static inline void _plot_dhires_pixels(uint8_t idx, uint8_t *fb_ptr) {
static inline void __plot_hires80_pixels(uint8_t idx, uint8_t *fb_ptr) {
uint8_t b1 = video__dhires1[idx];
uint8_t b2 = video__dhires2[idx];
uint32_t b = (b2<<24) | (b1<<8);
@ -847,13 +828,11 @@ static inline void _plot_dhires_pixels(uint8_t idx, uint8_t *fb_ptr) {
*((uint32_t *)(fb_ptr+SCANWIDTH)) = b;
}
// PlotDHires
static inline void _plot_dhires(uint16_t base, uint16_t ea, uint8_t *fb_base) {
video_setDirty();
static inline void __plot_hires80(uint16_t base, uint16_t ea) {
ea &= ~0x1;
uint16_t memoff = ea - base;
uint8_t *fb_ptr = fb_base+video__screen_addresses[memoff];
uint8_t *fb_ptr = video__fb+video__screen_addresses[memoff];
uint8_t col = video__columns[memoff];
uint8_t b0 = 0x0;
@ -867,7 +846,7 @@ static inline void _plot_dhires(uint16_t base, uint16_t ea, uint8_t *fb_base) {
b0 &= ~0x80;
b0 = (b1<<4)|(b0>>3);
_plot_dhires_pixels(b0, fb_ptr-4);
__plot_hires80_pixels(b0, fb_ptr-4);
}
b1 = apple_ii_64k[1][ea+2];
@ -891,45 +870,42 @@ static inline void _plot_dhires(uint16_t base, uint16_t ea, uint8_t *fb_base) {
// 00000001 11111122 22222333 3333xxxx
_plot_dhires_pixels(b, fb_ptr);
__plot_hires80_pixels(b, fb_ptr);
b >>= 4;
fb_ptr += 4;
_plot_dhires_pixels(b, fb_ptr);
__plot_hires80_pixels(b, fb_ptr);
b >>= 4;
fb_ptr += 4;
_plot_dhires_pixels(b, fb_ptr);
__plot_hires80_pixels(b, fb_ptr);
b >>= 4;
fb_ptr += 4;
_plot_dhires_pixels(b, fb_ptr);
__plot_hires80_pixels(b, fb_ptr);
b >>= 4;
fb_ptr += 4;
_plot_dhires_pixels(b, fb_ptr);
__plot_hires80_pixels(b, fb_ptr);
b >>= 4;
fb_ptr += 4;
_plot_dhires_pixels(b, fb_ptr);
__plot_hires80_pixels(b, fb_ptr);
b >>= 4;
fb_ptr += 4;
_plot_dhires_pixels(b, fb_ptr);
__plot_hires80_pixels(b, fb_ptr);
}
static inline void iie_plot_dhires0(uint16_t ea) {
_plot_dhires(0x2000, ea, video__fb1);
}
static inline void iie_plot_dhires1(uint16_t ea) {
_plot_dhires(0x4000, ea, video__fb2);
static void _plot_hires80(uint16_t off, int page, int bank, bool is_even) {
uint16_t base = page ? 0x4000 : 0x2000;
uint16_t ea = base+off;
__plot_hires80(base, ea);
}
// ----------------------------------------------------------------------------
// 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;
@ -956,7 +932,6 @@ static inline void _calculate_interp_color(uint8_t *color_buf, const unsigned in
}
}
// PlotPixelsExtra
static inline void _plot_hires_pixels(uint8_t *dst, const uint8_t *src) {
for (unsigned int i=2; i; i--) {
for (unsigned int j=DYNAMIC_SZ-1; j; j--) {
@ -972,12 +947,16 @@ static inline void _plot_hires_pixels(uint8_t *dst, const uint8_t *src) {
}
}
// PlotByte
static inline void _plot_hires(uint16_t ea, uint8_t b, bool is_even, uint8_t *fb_ptr) {
static void _plot_hires40(uint16_t off, int page, int bank, bool is_even) {
uint16_t base = page ? 0x4000 : 0x2000;
uint16_t ea = base+off;
uint8_t b = apple_ii_64k[bank][ea];
uint8_t *fb_ptr = video__fb+video__screen_addresses[off];
uint8_t _buf[DYNAMIC_SZ] = { 0 };
uint8_t *color_buf = (uint8_t *)_buf; // <--- work around for -Wstrict-aliasing
uint8_t *apple2_vmem = (uint8_t *)apple_ii_64k[0];
uint8_t *apple2_vmem = (uint8_t *)apple_ii_64k[bank];
uint8_t *hires_ptr = NULL;
if (is_even) {
@ -1051,100 +1030,56 @@ static inline void _plot_hires(uint16_t ea, uint8_t b, bool is_even, uint8_t *fb
_plot_hires_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) {
iie_plot_dhires1(ea);
} else {
iie_plot_dhires0(ea);
}
return;
}
if (softswitches & SS_HGRWRT) {
return;
}
video_setDirty();
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]);
static void (*_hirespage_plotter(uint32_t currswitches))(uint16_t, int, int, bool) {
return ((currswitches & SS_80COL) && (currswitches & SS_DHIRES)) ? _plot_hires80 : _plot_hires40;
}
GLUE_C_WRITE(video__write_2e_even0)
{
base_hgrwrt[ea] = b;
if (!(softswitches & SS_PAGE2)) {
_draw_hires_graphics(ea, b, /*even*/true, 0, SS_TEXT);
}
video_setDirty(A2_DIRTY_FLAG);
}
GLUE_C_WRITE(video__write_2e_even0_mixed)
{
base_hgrwrt[ea] = b;
if (!(softswitches & SS_PAGE2)) {
_draw_hires_graphics(ea, b, /*even*/true, 0, (SS_TEXT|SS_MIXED));
}
video_setDirty(A2_DIRTY_FLAG);
}
GLUE_C_WRITE(video__write_2e_odd0)
{
base_hgrwrt[ea] = b;
if (!(softswitches & SS_PAGE2)) {
_draw_hires_graphics(ea, b, /*even*/false, 0, SS_TEXT);
}
video_setDirty(A2_DIRTY_FLAG);
}
GLUE_C_WRITE(video__write_2e_odd0_mixed)
{
base_hgrwrt[ea] = b;
if (!(softswitches & SS_PAGE2)) {
_draw_hires_graphics(ea, b, /*even*/false, 0, (SS_TEXT|SS_MIXED));
}
video_setDirty(A2_DIRTY_FLAG);
}
GLUE_C_WRITE(video__write_2e_even1)
{
base_ramwrt[ea] = b;
if (softswitches & SS_PAGE2) {
_draw_hires_graphics(ea, b, /*even*/true, 1, SS_TEXT);
}
video_setDirty(A2_DIRTY_FLAG);
}
GLUE_C_WRITE(video__write_2e_even1_mixed)
{
base_ramwrt[ea] = b;
if (softswitches & SS_PAGE2) {
_draw_hires_graphics(ea, b, /*even*/true, 1, (SS_TEXT|SS_MIXED));
}
video_setDirty(A2_DIRTY_FLAG);
}
GLUE_C_WRITE(video__write_2e_odd1)
{
base_ramwrt[ea] = b;
if (softswitches & SS_PAGE2) {
_draw_hires_graphics(ea, b, /*even*/false, 1, SS_TEXT);
}
video_setDirty(A2_DIRTY_FLAG);
}
GLUE_C_WRITE(video__write_2e_odd1_mixed)
{
base_ramwrt[ea] = b;
if (softswitches & SS_PAGE2) {
_draw_hires_graphics(ea, b, /*even*/false, 1, (SS_TEXT|SS_MIXED));
}
video_setDirty(A2_DIRTY_FLAG);
}
// ----------------------------------------------------------------------------
@ -1154,17 +1089,15 @@ void video_init(void) {
LOG("(re)setting render_thread_id : %ld -> %ld", render_thread_id, pthread_self());
render_thread_id = pthread_self();
video__fb1 = vga_mem_page_0;
video__fb2 = vga_mem_page_1;
// reset Apple2 softframebuffers
memset(video__fb1,0,SCANWIDTH*SCANHEIGHT);
memset(video__fb2,0,SCANWIDTH*SCANHEIGHT);
assert(!video__fb);
video__fb = MALLOC(SCANWIDTH*SCANHEIGHT*sizeof(uint8_t));
video_clear();
video_backend->init((void*)0);
}
void _video_setRenderThread(pthread_t id) {
LOG("setting render_thread_id : %ld -> %ld", render_thread_id, id);
render_thread_id = id;
}
@ -1178,6 +1111,7 @@ void video_shutdown(bool emulatorShuttingDown) {
video_backend->shutdown(emulatorShuttingDown);
render_thread_id = 0;
FREE(video__fb);
}
void video_reshape(int w, int h, bool landscape) {
@ -1193,19 +1127,9 @@ void video_main_loop(void) {
video_backend->main_loop();
}
void video_setpage(int p) {
video_setDirty();
video__current_page = p;
}
const uint8_t * const video_current_framebuffer(void) {
return !video__current_page ? video__fb1 : video__fb2;
}
void video_clear(void) {
uint8_t *current_fb = (uint8_t *)video_current_framebuffer();
memset(current_fb, 0x0, sizeof(uint8_t)*SCANWIDTH*SCANHEIGHT);
video_setDirty();
memset(video__fb, 0x0, sizeof(uint8_t)*SCANWIDTH*SCANHEIGHT);
video_setDirty(A2_DIRTY_FLAG);
}
bool video_saveState(StateHelper_s *helper) {
@ -1214,12 +1138,10 @@ bool video_saveState(StateHelper_s *helper) {
do {
uint8_t state = 0x0;
state = (uint8_t)video__current_page;
if (!helper->save(fd, &state, 1)) {
break;
}
LOG("SAVE video__current_page = %02x", state);
LOG("SAVE (no-op) video__current_page = %02x", state);
saved = true;
} while (0);
@ -1237,70 +1159,132 @@ bool video_loadState(StateHelper_s *helper) {
if (!helper->load(fd, &state, 1)) {
break;
}
video__current_page = state;
LOG("LOAD video__current_page = %02x", video__current_page);
LOG("LOAD (no-op) video__current_page = %02x", state);
loaded = true;
} while (0);
video_redraw();
return loaded;
}
void video_redraw(void) {
// ----------------------------------------------------------------------------
// temporarily reset softswitches
uint32_t softswitches_save = softswitches;
softswitches &= ~(SS_TEXTWRT|SS_HGRWRT|SS_RAMWRT);
static inline drawpage_mode_t _currentMainMode(uint32_t currswitches) {
if (currswitches & SS_TEXT) {
return DRAWPAGE_TEXT;
} else {
if (currswitches & SS_HIRES) {
return DRAWPAGE_HIRES;
} else {
return DRAWPAGE_TEXT; // (LORES)
}
}
}
for (unsigned int y = 0; y < TEXT_ROWS; y++) {
for (unsigned int x = 0; x < TEXT_COLS; x++) {
uint16_t ea = video__line_offset[y] + x + 0x400;
uint8_t b = apple_ii_64k[0][ea];
static inline drawpage_mode_t _currentMixedMode(uint32_t currswitches) {
if (currswitches & (SS_TEXT|SS_MIXED)) {
return DRAWPAGE_TEXT;
} else {
if (currswitches & SS_HIRES) {
return DRAWPAGE_HIRES;
} else {
return DRAWPAGE_TEXT; // (LORES)
}
}
}
// text/lores pages
if (y < 20) {
_draw_text(ea, b, 0, SS_TEXTWRT, SS_TEXT);
ea += 0x400;
b = apple_ii_64k[0][ea];
_draw_text(ea, b, 1, SS_RAMWRT, SS_TEXT);
} else {
_draw_text(ea, b, 0, SS_TEXTWRT, (SS_TEXT|SS_MIXED));
ea += 0x400;
b = apple_ii_64k[0][ea];
_draw_text(ea, b, 1, SS_RAMWRT, (SS_TEXT|SS_MIXED));
static inline void _currentPageAndBank(uint32_t currswitches, drawpage_mode_t mode, OUTPARM int *page, OUTPARM int *bank) {
// UTAIIe : 5-25
if (currswitches & SS_80STORE) {
*page = 0;
//*bank = !!(currswitches & SS_PAGE2);
*bank = 0;
if (mode != DRAWPAGE_TEXT) {
assert(currswitches & SS_HIRES);
}
return;
}
*page = !!(currswitches & SS_PAGE2);
//*bank = !!(currswitches & SS_RAMRD);
*bank = 0;
}
uint8_t *video_currentFramebuffer(void) {
return video__fb;
}
uint8_t *video_scan(void) {
#warning FIXME TODO ... this needs to scan memory in the same way as the actually //e video scanner
pthread_mutex_lock(&video_scan_mutex);
int page = 0;
int bank = 0;
const uint32_t mainswitches = softswitches;
// render main portion of screen ...
drawpage_mode_t mainDrawPageMode = _currentMainMode(mainswitches);
_currentPageAndBank(mainswitches, mainDrawPageMode, &page, &bank);
if (mainDrawPageMode == DRAWPAGE_TEXT) {
void (*textMainPlotFn)(uint16_t, int, int) = _textpage_plotter(mainswitches, SS_TEXT);
for (unsigned int y=0; y < TEXT_ROWS-4; y++) {
for (unsigned int x=0; x < TEXT_COLS; x++) {
uint16_t off = video__line_offset[y] + x;
textMainPlotFn(off, page, bank);
}
// hires/dhires pages
for (unsigned int i = 0; i < 8; i++) {
uint16_t ea0 = 0x2000 + video__line_offset[y] + (0x400*i) + x;
uint16_t ea1 = ea0+0x2000;
uint8_t b0 = apple_ii_64k[0][ea0];
uint8_t b1 = apple_ii_64k[0][ea1];
if (y < 20) {
if (x & 1) {
_draw_hires_graphics(ea0, b0, /*even*/false, 0, SS_TEXT);
_draw_hires_graphics(ea1, b1, /*even*/false, 1, SS_TEXT);
} else {
_draw_hires_graphics(ea0, b0, /*even*/true, 0, SS_TEXT);
_draw_hires_graphics(ea1, b1, /*even*/true, 1, SS_TEXT);
}
} else {
if (x & 1) {
_draw_hires_graphics(ea0, b0, /*even*/false, 0, (SS_TEXT|SS_MIXED));
_draw_hires_graphics(ea1, b1, /*even*/false, 1, (SS_TEXT|SS_MIXED));
} else {
_draw_hires_graphics(ea0, b0, /*even*/true, 0, (SS_TEXT|SS_MIXED));
_draw_hires_graphics(ea1, b1, /*even*/true, 1, (SS_TEXT|SS_MIXED));
}
}
} else {
assert(!(mainswitches & SS_TEXT) && "TEXT should not be set");
assert((mainswitches & SS_HIRES) && "HIRES should be set");
void (*hiresMainPlotFn)(uint16_t, int, int, bool) = _hirespage_plotter(mainswitches);
for (unsigned int y=0; y < TEXT_ROWS-4; y++) {
for (unsigned int x=0; x < TEXT_COLS; x++) {
for (unsigned int i = 0; i < 8; i++) {
uint16_t off = video__line_offset[y] + (0x400*i) + x;
hiresMainPlotFn(off, page, bank, /*even*/!(x & 1));
}
}
}
}
softswitches = softswitches_save;
video_setDirty();
// resample current switches ... and render mixed portion of screen
const uint32_t mixedswitches = softswitches;
drawpage_mode_t mixedDrawPageMode = _currentMixedMode(mixedswitches);
_currentPageAndBank(mixedswitches, mixedDrawPageMode, &page, &bank);
if (mixedDrawPageMode == DRAWPAGE_TEXT) {
void (*textMixedPlotFn)(uint16_t, int, int) = _textpage_plotter(mixedswitches, (SS_TEXT|SS_MIXED));
for (unsigned int y=TEXT_ROWS-4; y < TEXT_ROWS; y++) {
for (unsigned int x=0; x < TEXT_COLS; x++) {
uint16_t off = video__line_offset[y] + x;
textMixedPlotFn(off, page, bank);
}
}
} else {
//assert(!(mixedswitches & SS_TEXT) && "TEXT should not be set"); // TEXT may have been reset from last sample?
assert(!(mixedswitches & SS_MIXED) && "MIXED should not be set");
assert((mixedswitches & SS_HIRES) && "HIRES should be set");
void (*hiresMixedPlotFn)(uint16_t, int, int, bool) = _hirespage_plotter(mixedswitches);
for (unsigned int y=TEXT_ROWS-4; y < TEXT_ROWS; y++) {
for (unsigned int x=0; x < TEXT_COLS; x++) {
for (unsigned int i = 0; i < 8; i++) {
uint16_t off = video__line_offset[y] + (0x400*i) + x;
hiresMixedPlotFn(off, page, bank, /*even*/!(x & 1));
}
}
}
}
video_setDirty(FB_DIRTY_FLAG);
pthread_mutex_unlock(&video_scan_mutex);
return video__fb;
}
void video_flashText(void) {
@ -1328,10 +1312,22 @@ void video_flashText(void) {
colormap[ COLOR_FLASHING_WHITE].blue = 0;
}
video_setDirty();
video_setDirty(FB_DIRTY_FLAG);
}
}
bool video_isDirty(int flags) {
return (_vid_dirty & flags);
}
unsigned long video_setDirty(flags) {
return __sync_fetch_and_or(&_vid_dirty, flags);
}
unsigned long video_clearDirty(flags) {
return __sync_fetch_and_and(&_vid_dirty, ~flags);
}
// ----------------------------------------------------------------------------
// VBL/timing routines

View File

@ -104,11 +104,15 @@ void video_reset(void);
void video_loadfont(int first, int qty, const uint8_t *data, int mode);
/*
* Redraw the display. This is called after exiting an interface display,
* when changes have been made to the Apple's emulated framebuffer that
* bypass the driver's hooks, or when the video mode has changed.
* Flushes currently set Apple //e video memory into staging framebuffer and returns pointer.
* This should only really be called from render thread or testsuite.
*/
void video_redraw(void);
uint8_t *video_scan(void);
/*
* Get a reference to current staging framebuffer
*/
uint8_t *video_currentFramebuffer(void);
/*
* Toggles FLASHing text between NORMAL and INVERSE character sets.
@ -120,41 +124,23 @@ void video_flashText(void);
*/
void video_clear(void);
/*
* Change the displayed video page to PAGE
* 0 - Page 1: $400-$7ff/$2000-$3fff
* 1 - Page 2: $800-$bff/$4000-$5fff
*/
void video_setpage(int page);
#define A2_DIRTY_FLAG 0x1 // Apple //e video is dirty
#define FB_DIRTY_FLAG 0x2 // Internal framebuffer is dirty
/*
* Get a reference to current internal framebuffer
* True if dirty bit(s) are set for flag(s)
*/
const uint8_t * const video_current_framebuffer();
// do not access directly, but through inline accessor methods
extern volatile unsigned long _backend_vid_dirty;
bool video_isDirty(int flags);
/*
* True if anything changed in framebuffer and not yet drawn
* Atomically set dirty bit(s), return previous bit(s) value
*/
static inline bool video_isDirty(void) {
return _backend_vid_dirty;
}
unsigned long video_setDirty(int flags);
/*
* Atomically set dirty bit, return previous value
* Atomically clear dirty bit(s), return previous bit(s) value
*/
static inline unsigned long video_setDirty(void) {
return __sync_fetch_and_or(&_backend_vid_dirty, 1UL);
}
/*
* Atomically clear dirty bit, return previous value
*/
static inline unsigned long video_clearDirty(void) {
return __sync_fetch_and_and(&_backend_vid_dirty, 0UL);
}
unsigned long video_clearDirty(int flags);
extern bool video_saveState(StateHelper_s *helper);
extern bool video_loadState(StateHelper_s *helper);
@ -275,17 +261,6 @@ uint8_t floating_bus_hibit(const bool hibit);
generic graphics globals
---------------------------------- */
/*
* Pointers to framebuffer (can be VGA memory or host buffer)
*/
extern uint8_t *video__fb1;
extern uint8_t *video__fb2;
/*
* Current visual page
*/
extern READONLY int video__current_page;
/*
* font glyph data
*/

View File

@ -165,7 +165,8 @@ static int altdrive = 0;
void video_plotchar(const int col, const int row, const interface_colorscheme_t cs, const uint8_t c) {
unsigned int off = row * SCANWIDTH * FONT_HEIGHT_PIXELS + col * FONT80_WIDTH_PIXELS + _INTERPOLATED_PIXEL_ADJUSTMENT_PRE;
interface_plotChar(video__fb1+off, SCANWIDTH, cs, c);
interface_plotChar(video_currentFramebuffer()+off, SCANWIDTH, cs, c);
video_setDirty(FB_DIRTY_FLAG);
}
void copy_and_pad_string(char *dest, const char* src, const char c, const int len, const char cap) {
@ -198,7 +199,8 @@ static void pad_string(char *s, const char c, const int len) {
}
void c_interface_print( int x, int y, const interface_colorscheme_t cs, const char *s ) {
_interface_plotLine(video__fb1, SCANWIDTH, _INTERPOLATED_PIXEL_ADJUSTMENT_PRE, x, y, cs, s);
_interface_plotLine(video_currentFramebuffer(), SCANWIDTH, _INTERPOLATED_PIXEL_ADJUSTMENT_PRE, x, y, cs, s);
video_setDirty(FB_DIRTY_FLAG);
}
/* -------------------------------------------------------------------------
@ -219,7 +221,8 @@ void c_interface_translate_screen( char screen[24][INTERFACE_SCREEN_X+1] ) {
}
void c_interface_print_submenu_centered( char *submenu, const int message_cols, const int message_rows ) {
_interface_plotMessageCentered(video__fb1, INTERFACE_SCREEN_X, TEXT_ROWS, RED_ON_BLACK, submenu, message_cols, message_rows);
_interface_plotMessageCentered(video_currentFramebuffer(), INTERFACE_SCREEN_X, TEXT_ROWS, RED_ON_BLACK, submenu, message_cols, message_rows);
video_setDirty(FB_DIRTY_FLAG);
}
/* ------------------------------------------------------------------------- */
@ -303,8 +306,7 @@ void c_interface_exit(int ch)
}
else
{
video_setpage(!!(softswitches & SS_SCREEN));
video_redraw();
video_setDirty(A2_DIRTY_FLAG);
}
}
@ -374,8 +376,6 @@ void c_interface_select_diskette( int drive )
screen[ 1 ][ DRIVE_X ] = (drive == 0) ? 'A' : 'B';
video_setpage( 0 );
c_interface_translate_screen( screen );
do {
@ -757,7 +757,6 @@ void c_interface_parameters()
/* reset the x position, so we don't lose our cursor if path changes */
cur_x = 0;
video_setpage( 0 );
screen[ 2 ][ 33 ] = MOUSETEXT_OPENAPPLE;
screen[ 2 ][ 46 ] = MOUSETEXT_CLOSEDAPPLE;
@ -1416,8 +1415,6 @@ void c_interface_credits()
" ",
" " };
video_setpage( 0 );
c_interface_translate_screen( screen );
c_interface_translate_screen_x_y( credits[0], SCROLL_WIDTH, SCROLL_LENGTH);
c_interface_print_screen( screen );
@ -1506,8 +1503,6 @@ void c_interface_keyboard_layout()
"| (Press any key to exit) |",
"||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||" };
video_setpage( 0 );
screen[ 6 ][ 68 ] = MOUSETEXT_UP;
screen[ 7 ][ 67 ] = MOUSETEXT_LEFT;
screen[ 7 ][ 69 ] = MOUSETEXT_RIGHT;

View File

@ -978,7 +978,6 @@ void show_opcode_breakpts() {
------------------------------------------------------------------------- */
void show_lc_info() {
int i = num_buffer_lines;
#warning FIXME TODO ... investigate/refactor all uses of !! here and elsewhere
sprintf(second_buf[i++], "lc bank = %d", 1 + !!(softswitches & SS_BANK2));
(softswitches & SS_LCWRT) ? sprintf(second_buf[i++], "write LC") : sprintf(second_buf[i++], "LC write protected");
(softswitches & SS_LCRAM) ? sprintf(second_buf[i++], "read LC") : sprintf(second_buf[i++], "read ROM");
@ -1075,7 +1074,6 @@ void show_disk_info() {
void clear_debugger_screen() {
#ifdef INTERFACE_CLASSIC
int i;
video_setpage( 0 );
for (i = 0; i < 24; i++)
{
c_interface_print(0, i, 2, screen[ i ] );
@ -1090,10 +1088,7 @@ void fb_sha1() {
uint8_t md[SHA_DIGEST_LENGTH];
char buf[(SHA_DIGEST_LENGTH*2)+1];
video_setpage(!!(softswitches & SS_SCREEN));
video_redraw();
const uint8_t * const fb = video_current_framebuffer();
const uint8_t * const fb = video_scan();
SHA1(fb, SCANWIDTH*SCANHEIGHT, md);
int i=0;
@ -1440,7 +1435,6 @@ void c_interface_debugging() {
lex_initted = 1;
}
video_setpage( 0 );
c_interface_translate_screen( screen );
for (i = 0; i < 24; i++)
{

View File

@ -49,7 +49,7 @@ void sha1_to_str(const uint8_t * const md, char *buf);
static inline int ASSERT_SHA(const char *SHA_STR) {
uint8_t md[SHA_DIGEST_LENGTH];
const uint8_t * const fb = video_current_framebuffer();
const uint8_t * const fb = video_scan();
SHA1(fb, SCANWIDTH*SCANHEIGHT, md);
sha1_to_str(md, mdstr);
ASSERT(strcmp(mdstr, SHA_STR) == 0);

View File

@ -163,9 +163,7 @@ void reinitialize(void) {
softswitches = SS_TEXT | SS_IOUDIS | SS_C3ROM | SS_LCWRT | SS_LCSEC;
video_setpage( 0 );
video_redraw();
video_setDirty(A2_DIRTY_FLAG);
cpu65_init();
@ -438,7 +436,7 @@ static void *cpu_thread(void *dummyptr) {
#ifdef AUDIO_ENABLED
!speaker_isActive() &&
#endif
!video_isDirty() && (!disk6.motor_off && (disk_motor_time.tv_sec || disk_motor_time.tv_nsec > DISK_MOTOR_QUIET_NSECS)) )
!video_isDirty(A2_DIRTY_FLAG) && (!disk6.motor_off && (disk_motor_time.tv_sec || disk_motor_time.tv_nsec > DISK_MOTOR_QUIET_NSECS)) )
{
TIMING_LOG("auto switching to full speed");
_timing_initialize(CPU_SCALE_FASTEST);
@ -509,7 +507,7 @@ static void *cpu_thread(void *dummyptr) {
#ifdef AUDIO_ENABLED
speaker_isActive() ||
#endif
video_isDirty() || (disk6.motor_off && (disk_motor_time.tv_sec || disk_motor_time.tv_nsec > DISK_MOTOR_QUIET_NSECS))) )
video_isDirty(A2_DIRTY_FLAG) || (disk6.motor_off && (disk_motor_time.tv_sec || disk_motor_time.tv_nsec > DISK_MOTOR_QUIET_NSECS))) )
{
double speed = alt_speed_enabled ? cpu_altscale_factor : cpu_scale_factor;
if (speed < CPU_SCALE_FASTEST) {

View File

@ -13,8 +13,6 @@
#include <regex.h>
volatile unsigned long _backend_vid_dirty = 0;
static int viewportX = 0;
static int viewportY = 0;
static int viewportWidth = SCANWIDTH*1.5;
@ -276,7 +274,7 @@ static void glvideo_shutdown(void) {
static void glvideo_render(void) {
SCOPE_TRACE_VIDEO("glvideo render");
const uint8_t * const fb = video_current_framebuffer();
uint8_t *fb = video_currentFramebuffer();
if (UNLIKELY(!fb)) {
return;
}
@ -309,8 +307,17 @@ static void glvideo_render(void) {
glUniformMatrix4fv(uniformMVPIdx, 1, GL_FALSE, mvpIdentity);
#endif
unsigned long wasDirty = video_clearDirty();
if (!cpu_isPaused()) {
// check if a2 video memory is dirty
unsigned long wasDirty = video_clearDirty(A2_DIRTY_FLAG);
wasDirty = 1;
#warning HACK FIXME TODO ... always setting A2 video memory dirty bit for now ...
if (wasDirty) {
fb = video_scan();
}
}
unsigned long wasDirty = video_clearDirty(FB_DIRTY_FLAG);
char *pixels = (char *)crtModel->texPixels;
if (wasDirty) {
SCOPE_TRACE_VIDEO("pixel convert");

View File

@ -41,7 +41,7 @@ typedef struct A2Color_s {
/*
* Reference to the internal 8bit-indexed color format
*/
extern A2Color_s colormap[256];
extern A2Color_s colormap[];
#endif /* !A2_VIDEO_H */

View File

@ -62,8 +62,6 @@ static video_backend_s xvideo_backend = { 0 };
static bool request_set_mode = false;
static int request_mode = 0;
volatile unsigned long _backend_vid_dirty = 0;
typedef struct {
unsigned long flags;
unsigned long functions;
@ -338,7 +336,7 @@ static int keysym_to_scancode(void) {
static void post_image() {
// copy Apple //e video memory into XImage uint32_t buffer
uint8_t *fb = !video__current_page ? video__fb1 : video__fb2;
uint8_t *fb = video_scan();
uint8_t index;
unsigned int count = SCANWIDTH * SCANHEIGHT;

View File

@ -135,8 +135,7 @@ GLUE_C_READ(iie_page2_off)
}
}
video_setpage(0);
video_redraw();
video_setDirty(A2_DIRTY_FLAG);
return floating_bus();
}
@ -160,8 +159,7 @@ GLUE_C_READ(iie_page2_on)
}
} else {
softswitches |= SS_SCREEN;
video_setpage(1);
video_redraw();
video_setDirty(A2_DIRTY_FLAG);
}
return floating_bus();
@ -176,7 +174,6 @@ GLUE_C_READ(read_switch_graphics)
{
if (softswitches & SS_TEXT) {
softswitches &= ~SS_TEXT;
video_redraw();
}
return floating_bus();
}
@ -185,7 +182,6 @@ GLUE_C_READ(read_switch_text)
{
if (!(softswitches & SS_TEXT)) {
softswitches |= SS_TEXT;
video_redraw();
}
return floating_bus();
}
@ -199,7 +195,6 @@ GLUE_C_READ(read_switch_no_mixed)
{
if (softswitches & SS_MIXED) {
softswitches &= ~SS_MIXED;
video_redraw();
}
return floating_bus();
}
@ -208,7 +203,6 @@ GLUE_C_READ(read_switch_mixed)
{
if (!(softswitches & SS_MIXED)) {
softswitches |= SS_MIXED;
video_redraw();
}
return floating_bus();
}
@ -246,7 +240,6 @@ GLUE_C_READ(iie_hires_off)
softswitches |= SS_HGRWRT;
}
video_redraw();
return floating_bus();
}
@ -270,7 +263,6 @@ GLUE_C_READ(iie_hires_on)
}
}
video_redraw();
return floating_bus();
}
@ -544,7 +536,7 @@ GLUE_C_READ(iie_80store_off)
if (softswitches & SS_PAGE2) {
softswitches |= SS_SCREEN;
video_setpage(1);
video_setDirty(A2_DIRTY_FLAG);
}
return floating_bus();
@ -579,7 +571,8 @@ GLUE_C_READ(iie_80store_on)
}
softswitches &= ~SS_SCREEN;
video_setpage(0);
video_setDirty(A2_DIRTY_FLAG);
return floating_bus();
}
@ -741,10 +734,6 @@ GLUE_C_READ(iie_80col_off)
softswitches &= ~SS_80COL;
if (softswitches & (SS_TEXT|SS_MIXED|SS_DHIRES)) {
video_redraw();
}
return floating_bus();
}
@ -756,10 +745,6 @@ GLUE_C_READ(iie_80col_on)
softswitches |= SS_80COL;
if (softswitches & (SS_TEXT|SS_MIXED|SS_DHIRES)) {
video_redraw();
}
return floating_bus();
}
@ -773,7 +758,6 @@ GLUE_C_READ(iie_altchar_off)
if (softswitches & SS_ALTCHAR) {
softswitches &= ~SS_ALTCHAR;
video_loadfont(0x40,0x40,ucase_glyphs,3);
video_redraw();
}
return floating_bus();
}
@ -784,7 +768,6 @@ GLUE_C_READ(iie_altchar_on)
softswitches |= SS_ALTCHAR;
video_loadfont(0x40,0x20,mousetext_glyphs,1);
video_loadfont(0x60,0x20,lcase_glyphs,2);
video_redraw();
}
return floating_bus();
}
@ -816,7 +799,6 @@ GLUE_C_READ(iie_dhires_on)
{
if (!(softswitches & SS_DHIRES)) {
softswitches |= SS_DHIRES;
video_redraw();
}
return floating_bus();
}
@ -825,7 +807,6 @@ GLUE_C_READ(iie_dhires_off)
{
if (softswitches & SS_DHIRES) {
softswitches &= ~SS_DHIRES;
video_redraw();
}
return floating_bus();
}
@ -945,7 +926,6 @@ static void _initialize_font(void) {
video_loadfont(0x80,0x40,ucase_glyphs,0);
video_loadfont(0xC0,0x20,ucase_glyphs,0);
video_loadfont(0xE0,0x20,lcase_glyphs,0);
video_redraw();
}
static void _initialize_apple_ii_memory(void) {