read colors from generated palette; checkpoint DHGR work

This commit is contained in:
Brad Grantham 2021-01-02 09:45:49 -08:00
parent b908e772ef
commit 2e095b24f6
3 changed files with 123 additions and 92 deletions

View File

@ -1236,6 +1236,8 @@ struct MAINboard : board_base
SoftSwitch PAGE2 {"PAGE2", 0xC054, 0xC055, 0xC01C, true, switches, false, true};
SoftSwitch HIRES {"HIRES", 0xC056, 0xC057, 0xC01D, true, switches, false, true};
std::array<bool,4> AN = {false, false, false, false};
vector<backed_region*> regions;
std::array<backed_region*,256> read_regions_by_page;
std::array<backed_region*,256> write_regions_by_page;
@ -1322,11 +1324,25 @@ struct MAINboard : board_base
backed_region text_page2 = {"text_page2", 0x0800, 0x0400, RAM, &regions, read_from_main_ram, write_to_main_ram};
backed_region text_page2x = {"text_page2x", 0x0800, 0x0400, RAM, &regions, read_from_aux_ram, write_to_aux_ram};
enabled_func read_from_aux_hires1 = [&]{return HIRES && RAMRD && ((!STORE80) || (STORE80 && PAGE2));};
enabled_func write_to_aux_hires1 = [&]{return HIRES && RAMWRT && ((!STORE80) || (STORE80 && PAGE2));};
// Understanding the IIe by Sather:
// if 80Store is set and hires is cleared, then page2 switches text between main and aux
// if 80Store is set and hires is set, then page2 switches text AND hires between main and aux
// if 80Store is cleared, then RAMRD and RAMWRT switch text AND hires AND 200-BFFF between main and aux
// enabled_func read_from_aux_hires1 = [&]{return HIRES && RAMRD && ((!STORE80) || (STORE80 && PAGE2));};
// enabled_func write_to_aux_hires1 = [&]{return HIRES && RAMWRT && ((!STORE80) || (STORE80 && PAGE2));};
enabled_func read_from_aux_hires1 = [&]{return (STORE80 && HIRES && PAGE2) || (!STORE80 && RAMRD);};
enabled_func write_to_aux_hires1 = [&]{return (STORE80 && HIRES && PAGE2) || (!STORE80 && RAMWRT);};
enabled_func read_from_main_hires1 = [&]{return !read_from_aux_hires1();};
enabled_func write_to_main_hires1 = [&]{return !write_to_aux_hires1();};
//STA $C057 ;TURN ON HIRES
//STA $C05E ;TURN ON DHR ?
//STA $C00D ;TURN ON 80 COLUMNS
//STA $C001 ;TURN ON 80STORE
//STA $C055 ;TURN ON PAGE2
//LDA #$0E ;LOAD 14
//STA $2000 ;Put in first location on HIRES PAGE 1 in AUX RAM.
backed_region hires_page1 = {"hires_page1", 0x2000, 0x2000, RAM, &regions, read_from_main_hires1, write_to_main_hires1};
backed_region hires_page1x = {"hires_page1x", 0x2000, 0x2000, RAM, &regions, read_from_aux_hires1, write_to_aux_hires1};
backed_region hires_page2 = {"hires_page2", 0x4000, 0x2000, RAM, &regions, read_from_main_ram, write_to_main_ram};
@ -1335,10 +1351,6 @@ struct MAINboard : board_base
static std::map<uint16_t, std::string> MMIO_named_locations;
set<int> ignore_mmio = {
0xC058, // CLRAN0 through Apple //e
0xC05A, // CLRAN1 through Apple //e
0xC05D, // SETAN2 through Apple //e
0xC05F, // SETAN3 through Apple //e
0xC060, // TAPEIN through Apple //e
0xC061, // RDBTN0 Open Apple on and after Apple //e
0xC062, // BUTN1 Solid Apple on and after Apple //e
@ -1438,13 +1450,15 @@ struct MAINboard : board_base
{
APPLE2Einterface::DisplayMode mode = TEXT ? APPLE2Einterface::TEXT : (HIRES ? APPLE2Einterface::HIRES : APPLE2Einterface::LORES);
int page = (PAGE2 && !STORE80) ? 1 : 0;
if(0)printf("mode %s, mixed %s, page %d, vid80 %s, altchar %s\n",
bool dhgr = (!AN[3]) && VID80;
if(0)printf("mode %s, mixed %s, page %d, vid80 %s, dhgr %s, altchar %s\n",
(mode == APPLE2Einterface::TEXT) ? "TEXT" : ((mode == APPLE2Einterface::LORES) ? "LORES" : "HIRES"),
MIXED ? "true" : "false",
page,
VID80 ? "true" : "false",
dhgr ? "true" : "false",
ALTCHAR ? "true" : "false");
return APPLE2Einterface::ModeSettings(mode, MIXED, page, VID80, ALTCHAR);
return APPLE2Einterface::ModeSettings(mode, MIXED, page, VID80, dhgr, ALTCHAR);
}
APPLE2Einterface::ModeSettings old_mode_settings;
@ -1689,6 +1703,15 @@ struct MAINboard : board_base
tie(value, button) = get_paddle(num);
data = button ? 0xff : 0x0;
return true;
} else if(addr >= 0xC058 && addr <= 0xC05F) {
/* annunciators & DHGR enable */
int num = (addr - 0xC058) / 2;
bool set = addr & 1;
if(true /*debug & DEBUG_RW*/) printf("read %04X, %s annunciator %d\n", addr, set ? "set" : "clear", num);
AN[num] = set;
// Should also do something here if we are emulating something attached to AN{0,1,2,3}
data = 0;
return true;
}
if(ignore_mmio.find(addr) != ignore_mmio.end()) {
if(debug & DEBUG_RW) printf("read %04X, ignored, return 0x00\n", addr);
@ -1807,21 +1830,12 @@ struct MAINboard : board_base
return true;
}
#endif
#if 0
if(text_page1.write(addr, data) ||
text_page1x.write(addr, data) ||
text_page2.write(addr, data) ||
text_page2x.write(addr, data) ||
hires_page1.write(addr, data) ||
hires_page1x.write(addr, data) ||
hires_page2.write(addr, data) ||
hires_page2x.write(addr, data))
#else
if(((addr >= 0x400) && (addr <= 0xBFF)) || ((addr >= 0x2000) && (addr <= 0x5FFF)))
#endif
{
if((addr >= 0x400) && (addr <= 0xBFF)) {
display_write(addr, write_to_aux_text1(), data);
}
if((addr >= 0x2000) && (addr <= 0x5FFF)) {
display_write(addr, write_to_aux_hires1(), data);
}
for(auto b : boards) {
if(b->write(addr, data)) {
return true;
@ -1893,6 +1907,15 @@ struct MAINboard : board_base
speaker_transitioning_to_high = !speaker_transitioning_to_high;
return true;
}
if(addr >= 0xC058 && addr <= 0xC05F) {
/* annunciators & DHGR enable */
int num = (addr - 0xC058) / 2;
bool set = addr & 1;
if(true /*debug & DEBUG_RW*/) printf("write %04X, %s annunciator %d\n", addr, set ? "set" : "clear", num);
AN[num] = set;
// Should also do something here if we are emulating something attached to AN{0,1,2,3}
return true;
}
if(MMIO_named_locations.count(addr) > 0) {
printf("unhandled MMIO Write at %04X (%s)\n", addr, MMIO_named_locations.at(addr).c_str());
} else {

View File

@ -95,6 +95,26 @@ event dequeue_event()
return {NONE, 0};
}
GLuint artifact_colors_texture;
uint8_t artifact_colors[][3] = {
{ 0, 0, 0}, // 0 "black" -> 0,0,0,0 -> {0.000000, 0.000000, 0.000000}
{208, 0, 50}, // 1 "red" -> 1,0,0,0 -> {0.815901, 0.000000, 0.197238}
{ 72, 11, 255}, // 2 "dark blue" -> 0,1,0,0 -> {0.283288, 0.043435, 1.000000}
{255, 3, 255}, // 3 "purple" -> 1,1,0,0 -> {1.000000, 0.015525, 1.000000}
{ 0, 134, 77}, // 4 "dark green" -> 0,0,1,0 -> {0.000000, 0.527909, 0.302762}
{127, 127, 127}, // 5 "gray 1" -> 1,0,1,0 -> {0.500000, 0.500000, 0.500000}
{ 0, 145, 255}, // 6 "medium blue" -> 0,1,1,0 -> {0.000000, 0.571344, 1.000000}
{199, 138, 255}, // 7 "light blue" -> 1,1,1,0 -> {0.783288, 0.543435, 1.000000}
{ 55, 116, 0}, // 8 "brown" -> 0,0,0,1 -> {0.216712, 0.456565, 0.000000}
{255, 109, 0}, // 9 "orange" -> 1,0,0,1 -> {1.000000, 0.428656, 0.000000}
{127, 127, 127}, // 10 "gray 2" -> 0,1,0,1 -> {0.500000, 0.500000, 0.500000}
{255, 120, 177}, // 11 "pink" -> 1,1,0,1 -> {1.000000, 0.472091, 0.697238}
{ 0, 251, 0}, // 12 "light green" -> 0,0,1,1 -> {0.000000, 0.984475, 0.000000}
{182, 243, 0}, // 13 "yello" -> 1,0,1,1 -> {0.716712, 0.956565, 0.000000}
{ 46, 255, 204}, // 14 "aqua" -> 0,1,1,1 -> {0.184099, 1.000000, 0.802762}
{255, 255, 255}, // 15 "white" -> 1,1,1,1 -> {1.000000, 1.000000, 1.000000}
};
opengl_texture font_texture;
constexpr uint32_t fonttexture_w = 7;
constexpr uint32_t fonttexture_h = 8 * 96;
@ -130,6 +150,7 @@ GLuint textport80_font_texture_coord_scale_location;
GLuint lores_program;
GLuint lores_texture_location;
GLuint lores_artifact_colors_texture_location;
GLuint lores_texture_coord_scale_location;
GLuint lores_x_offset_location;
GLuint lores_y_offset_location;
@ -137,7 +158,7 @@ GLuint lores_to_screen_location;
const uint32_t hires_w = 320; // MSBit is color chooser, Apple ][ weirdness
const uint32_t hires_h = 192;
opengl_texture hires_texture[2];
opengl_texture hires_texture[2][2]; // [aux][page]
GLuint hires_program;
GLuint hires_texture_location;
@ -149,6 +170,7 @@ GLuint hires_y_offset_location;
GLuint hirescolor_program;
GLuint hirescolor_texture_location;
GLuint hirescolor_texture_coord_scale_location;
GLuint hirescolor_artifact_colors_texture_location;
GLuint hirescolor_to_screen_location;
GLuint hirescolor_x_offset_location;
GLuint hirescolor_y_offset_location;
@ -223,6 +245,7 @@ static const char *hirescolor_fragment_shader = R"(
in vec2 raster_coords;
uniform vec2 hires_texture_coord_scale;
uniform sampler2D hires_texture;
uniform sampler1D artifact_colors_texture;
out vec4 color;
@ -233,10 +256,12 @@ static const char *hirescolor_fragment_shader = R"(
int texturex = byte * 8 + bit;
return vec2(texturex + .01f, y + .01f) * hires_texture_coord_scale;
}
void main()
{
int x = int(raster_coords.x);
int y = int(raster_coords.y);
int colorIndex;
uint left = (x < 1) ? 0u : uint(255 * texture(hires_texture, raster_to_texture(x - 1, y)).x);
uint pixel = uint(255 * texture(hires_texture, raster_to_texture(x, y)).x);
@ -244,37 +269,36 @@ static const char *hirescolor_fragment_shader = R"(
if((pixel == 255u) && ((left == 255u) || (right == 255u))) {
/* Okay, first of all, if this pixel's on and its left or right are on, it's white. */
color = vec4(1.0, 1.0, 1.0, 1.0);
colorIndex = 15;
} else if((pixel == 0u) && (left == 0u) && (right == 0u)) {
/* If none are on, it's black */
color = vec4(0.0, 0.0, 0.0, 1.0);
colorIndex = 0;
} else {
uint even = (x % 2 == 1) ? left : pixel;
uint odd = (x % 2 == 1) ? pixel : right;
uint palette = uint(texture(hires_texture, vec2((x / 7) * 8 + 7 + .01f, raster_coords.y + .01f) * hires_texture_coord_scale).x);
if(palette == 0u) {
if((even == 0u) && (odd == 255u)) {
/* green 0, 251, 0 */
color = vec4(0.0/255.0, 251.0/255.0, 0.0/255.0, 1.0);
colorIndex = 12; /* green */
} else if((even == 255u) && (odd == 0u)) {
/* purple 255, 3, 255 */
color = vec4(255.0/255.0, 3.0/255.0, 255.0/255.0, 1.0);
colorIndex = 3; /* purple */
} else if((even == 0u) && (odd == 0u)) {
color = vec4(0, 0, 0, 1);
colorIndex = 0;
} /* handled 1,1 above */
} else {
if((even == 0u) && (odd == 255u)) {
/* orange 255, 109, 0 */
color = vec4(255.0/255.0, 109.0/255.0, 0.0/255.0, 1.0);
colorIndex = 9; /* orange */
} else if((even == 255u) && (odd == 0u)) {
/* blue 0, 145, 255 */
color = vec4(0.0/255.0, 145.0/255.0, 255.0/255.0, 1.0);
colorIndex = 6; /* "medium" blue */
} else if((even == 0u) && (odd == 0u)) {
color = vec4(0, 0, 0, 1);
colorIndex = 0;
} /* handled 1,1 above */
}
}
color = texture(artifact_colors_texture, colorIndex/16.0 + .01f);
})";
static const char *text_vertex_shader = R"(
@ -406,6 +430,7 @@ static const char *lores_fragment_shader = R"(
in vec2 raster_coords;
uniform vec2 lores_texture_coord_scale;
uniform sampler2D lores_texture;
uniform sampler1D artifact_colors_texture;
out vec4 color;
@ -414,61 +439,12 @@ static const char *lores_fragment_shader = R"(
uint byte;
byte = uint(texture(lores_texture, (uvec2(uint(raster_coords.x) / 7u, uint(raster_coords.y) / 8u) + vec2(.01f, .01f)) * lores_texture_coord_scale).x * 255.0);
uint inglyph_y = uint(raster_coords.y) % 8u;
uint lorespixel;
uint colorIndex;
if(inglyph_y < 4u)
lorespixel = byte % 16u;
colorIndex = byte % 16u;
else
lorespixel = byte / 16u;
switch(lorespixel) {
case 0u:
color = vec4(0, 0, 0, 1);
break;
case 1u:
color = vec4(227.0/255.0, 30.0/255.0, 96.0/255.0, 1);
break;
case 2u:
color = vec4(96.0/255.0, 78.0/255.0, 189.0/255.0, 1);
break;
case 3u:
color = vec4(255.0/255.0, 68.0/255.0, 253.0/255.0, 1);
break;
case 4u:
color = vec4(9.0/255.0, 163.0/255.0, 96.0/255.0, 1);
break;
case 5u:
color = vec4(156.0/255.0, 156.0/255.0, 156.0/255.0, 1);
break;
case 6u:
color = vec4(20.0/255.0, 207.0/255.0, 253.0/255.0, 1);
break;
case 7u:
color = vec4(208.0/255.0, 195.0/255.0, 255.0/255.0, 1);
break;
case 8u:
color = vec4(96.0/255.0, 114.0/255.0, 3.0/255.0, 1);
break;
case 9u:
color = vec4(255.0/255.0, 106.0/255.0, 60.0/255.0, 1);
break;
case 10u:
color = vec4(156.0/255.0, 156.0/255.0, 156.0/255.0, 1);
break;
case 11u:
color = vec4(255.0/255.0, 160.0/255.0, 208.0/255.0, 1);
break;
case 12u:
color = vec4(20.0/255.0, 245.0/255.0, 60.0/255.0, 1);
break;
case 13u:
color = vec4(208.0/255.0, 221.0/255.0, 141.0/255.0, 1);
break;
case 14u:
color = vec4(114.0/255.0, 255.0/255.0, 208.0/255.0, 1);
break;
case 15u:
color = vec4(255.0/255.0, 255.0/255.0, 255.0/255.0, 1);
break;
}
colorIndex = byte / 16u;
color = texture(artifact_colors_texture, colorIndex/16.0 + .01f);
})";
void set_image_shader(float to_screen[9], const opengl_texture& texture, float x, float y)
@ -499,6 +475,12 @@ void set_hires_shader(float to_screen[9], const opengl_texture& texture, bool co
glBindTexture(GL_TEXTURE_2D, texture);
glUniform2f(hirescolor_texture_coord_scale_location, 1.0 / texture.w, 1.0 / texture.h);
glUniform1i(hirescolor_texture_location, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_1D, artifact_colors_texture);
glUniform1i(hirescolor_artifact_colors_texture_location, 1);
CheckOpenGL(__FILE__, __LINE__);
glUniformMatrix3fv(hirescolor_to_screen_location, 1, GL_FALSE, to_screen);
glUniform1f(hirescolor_x_offset_location, x);
glUniform1f(hirescolor_y_offset_location, y);
@ -507,10 +489,12 @@ void set_hires_shader(float to_screen[9], const opengl_texture& texture, bool co
} else {
glUseProgram(hires_program);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform2f(hires_texture_coord_scale_location, 1.0 / texture.w, 1.0 / texture.h);
glUniform1i(hires_texture_location, 0);
glUniformMatrix3fv(hires_to_screen_location, 1, GL_FALSE, to_screen);
glUniform1f(hires_x_offset_location, x);
glUniform1f(hires_y_offset_location, y);
@ -597,13 +581,19 @@ void set_shader(float to_screen[9], DisplayMode display_mode, bool mixed_mode, i
glBindTexture(GL_TEXTURE_2D, textport_texture[0][display_page]);
glUniform1i(lores_texture_location, 0);
glUniform2f(lores_texture_coord_scale_location, 1.0 / (textport_w), 1.0 / (textport_h));
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_1D, artifact_colors_texture);
glUniform1i(lores_artifact_colors_texture_location, 1);
CheckOpenGL(__FILE__, __LINE__);
glUniformMatrix3fv(lores_to_screen_location, 1, GL_FALSE, to_screen);
glUniform1f(lores_x_offset_location, x);
glUniform1f(lores_y_offset_location, y);
} else if(display_mode == HIRES) {
set_hires_shader(to_screen, hires_texture[display_page], draw_using_color, x, y);
set_hires_shader(to_screen, hires_texture[0][display_page], draw_using_color, x, y); // XXX should switch aux
}
}
@ -1037,13 +1027,24 @@ void initialize_gl(void)
glClearColor(0, 0, 0, 1);
CheckOpenGL(__FILE__, __LINE__);
glGenTextures(1, &artifact_colors_texture);
glBindTexture(GL_TEXTURE_1D, artifact_colors_texture);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 16, 0, GL_RGB, GL_UNSIGNED_BYTE, artifact_colors);
CheckOpenGL(__FILE__, __LINE__);
glBindTexture(GL_TEXTURE_1D, GL_NONE);
font_texture = initialize_texture(fonttexture_w, fonttexture_h, font_bytes);
textport_texture[0][0] = initialize_texture(textport_w, textport_h);
textport_texture[0][1] = initialize_texture(textport_w, textport_h);
textport_texture[1][0] = initialize_texture(textport_w, textport_h);
textport_texture[1][1] = initialize_texture(textport_w, textport_h);
hires_texture[0] = initialize_texture(hires_w, hires_h);
hires_texture[1] = initialize_texture(hires_w, hires_h);
hires_texture[0][0] = initialize_texture(hires_w, hires_h);
hires_texture[0][1] = initialize_texture(hires_w, hires_h);
hires_texture[1][0] = initialize_texture(hires_w, hires_h);
hires_texture[1][1] = initialize_texture(hires_w, hires_h);
CheckOpenGL(__FILE__, __LINE__);
image_program = GenerateProgram("image", hires_vertex_shader, image_fragment_shader);
@ -1071,6 +1072,8 @@ void initialize_gl(void)
assert(hirescolor_program != 0);
hirescolor_texture_location = glGetUniformLocation(hirescolor_program, "hires_texture");
hirescolor_texture_coord_scale_location = glGetUniformLocation(hirescolor_program, "hires_texture_coord_scale");
hirescolor_artifact_colors_texture_location = glGetUniformLocation(hirescolor_program, "artifact_colors_texture");
assert(hirescolor_artifact_colors_texture_location != -1);
hirescolor_to_screen_location = glGetUniformLocation(hirescolor_program, "to_screen");
hirescolor_x_offset_location = glGetUniformLocation(hirescolor_program, "x_offset");
hirescolor_y_offset_location = glGetUniformLocation(hirescolor_program, "y_offset");
@ -1111,6 +1114,7 @@ void initialize_gl(void)
assert(lores_program != 0);
lores_texture_location = glGetUniformLocation(lores_program, "lores_texture");
lores_texture_coord_scale_location = glGetUniformLocation(lores_program, "lores_texture_coord_scale");
lores_artifact_colors_texture_location = glGetUniformLocation(lores_program, "artifact_colors_texture");
lores_x_offset_location = glGetUniformLocation(lores_program, "x_offset");
lores_y_offset_location = glGetUniformLocation(lores_program, "y_offset");
lores_to_screen_location = glGetUniformLocation(lores_program, "to_screen");
@ -1901,7 +1905,7 @@ void write2(uint16_t addr, bool aux, uint8_t data)
uint16_t scanout_address = hires_memory_to_scanout_address[within_page];
uint16_t row = scanout_address / 40;
uint16_t col = scanout_address % 40;
glBindTexture(GL_TEXTURE_2D, hires_texture[page]);
glBindTexture(GL_TEXTURE_2D, hires_texture[aux][page]);
if(page == 0) hgr_page1[addr - 0x2000] = data; // XXX hack
uint8_t pixels[8];
for(int i = 0; i < 8 ; i++)

View File

@ -57,19 +57,22 @@ struct ModeSettings
bool mixed;
int page; // Apple //e page minus 1 (so 0,1 not 1,2)
bool vid80;
bool dhgr;
bool altchar;
ModeSettings() :
mode(TEXT),
mixed(false),
page(0),
vid80(false),
dhgr(false),
altchar(false)
{}
ModeSettings(DisplayMode mode_, bool mixed_, int page_, bool vid80_, bool altchar_) :
ModeSettings(DisplayMode mode_, bool mixed_, int page_, bool vid80_, bool dhgr, bool altchar_) :
mode(mode_),
mixed(mixed_),
page(page_),
vid80(vid80_),
dhgr(false),
altchar(altchar_)
{}
bool operator !=(const ModeSettings& ms)
@ -79,6 +82,7 @@ struct ModeSettings
(ms.mixed != mixed) ||
(ms.page != page) ||
(ms.vid80 != vid80) ||
(ms.dhgr != dhgr) ||
(ms.altchar != altchar);
}
};