erc-c/src/apple2/lores.c

111 lines
3.6 KiB
C

/*
* apple2.lores.c
*
* The Apple II has several modes of display, and one of those modes is
* low-resolution graphics. Graphics are shown on a 40x48 grid, where
* each cell in the grid consumes 4 rows or columns of pixels.
*
* It's possible in low-resolution graphics (and high-resolution, for
* that matter) to show text with graphics--that is to say, exactly the
* kind of text that would be seen in 40-column text mode. If text is
* shown (this is indicated through a "mixed" mode flag), then it will
* be rendered at the bottom of the screen, and the rows of pixels that
* would have been rendered in full graphical mode will be skipped.
*/
#include "apple2/apple2.h"
#include "apple2/lores.h"
#include "apple2/text.h"
/*
* These are the color codes for the lo-res colors that are available.
* Each byte in lo-res represents two visual cells, each 4 bytes high,
* which are indicated by considering the low and high 4 bits separately
* and matching them against the colors in the table below.
*
* These color values are the "NTSC Corrected" colors as defined in the
* Apple II Forever Anthology, v0.3, Hires reference (pulled from
* archive.org).
*/
static vm_color lores_colors[] = {
{ 0x00, 0x00, 0x00, 0x00 }, // black
{ 0x90, 0x17, 0x40, 0x00 }, // magenta
{ 0x40, 0x2c, 0xa5, 0x00 }, // dark blue
{ 0xd0, 0x43, 0xe5, 0x00 }, // purple
{ 0x00, 0x69, 0x40, 0x00 }, // dark green
{ 0x80, 0x80, 0x80, 0x00 }, // gray
{ 0x2f, 0x95, 0xe5, 0x00 }, // medium blue
{ 0xbf, 0xab, 0xff, 0x00 }, // light blue
{ 0x40, 0x54, 0x00, 0x00 }, // brown
{ 0xd0, 0x6a, 0x1a, 0x00 }, // orange
{ 0x80, 0x80, 0x80, 0x00 }, // gray
{ 0xff, 0x96, 0xbf, 0x00 }, // pink
{ 0x2f, 0xbc, 0x1a, 0x00 }, // light green
{ 0xbf, 0xd3, 0x5a, 0x00 }, // yellow
{ 0x6f, 0xe8, 0xbf, 0x00 }, // aquamarine
{ 0xff, 0xff, 0xff, 0x00 }, // white
};
/*
* Draw two cells on the low-resolution grid. Each byte address holds
* two cells-worth of data. We may delegate the render to the text
* render code if we're in mixed mode.
*/
void
apple2_lores_draw(apple2 *mach, size_t addr)
{
int row = apple2_text_row(addr),
col = apple2_text_col(addr);
if (row == -1 || col == -1) {
return;
}
// In low-resolution mode, the row number is analagous to the text
// row number, like so:
row *= 2;
// In mixed display mode, we have to render text in the lower rows
// of the screen
if ((mach->display_mode & DISPLAY_MIXED) && row >= 40) {
apple2_text_draw(mach, addr);
return;
}
vm_8bit byte = mos6502_get(mach->cpu, addr);
vm_8bit topcell = byte & 0xF,
botcell = byte >> 4;
vm_area dest;
// Cells are more like rectangles than squares
dest.width = 7;
dest.height = 4;
dest.xoff = 7 * col;
dest.yoff = 4 * row;
// Draw the top cell
vm_screen_set_color(mach->screen, apple2_lores_color(topcell));
vm_screen_draw_rect(mach->screen, &dest);
// And draw the bottom cell
dest.yoff += 4;
vm_screen_set_color(mach->screen, apple2_lores_color(botcell));
vm_screen_draw_rect(mach->screen, &dest);
}
/*
* Return the color that corresponds to the value in the given byte.
* Even though we receive a byte, lores color data is stored two cells
* to a byte, so all we ever get here will be contained within the first
* four bits; therefore we mask the byte as we index the lores colors
* table, to ensure a bad value doesn't end up returning a value out of
* bounds.
*/
vm_color
apple2_lores_color(vm_8bit byte)
{
return lores_colors[byte & 0xf];
}