1
0
mirror of https://github.com/pevans/erc-c.git synced 2024-06-16 06:29:37 +00:00

First crack at lo-res graphics

This commit is contained in:
Peter Evans 2018-03-11 23:28:28 -05:00
parent 5a43ca9a7a
commit df960220ef
10 changed files with 192 additions and 36 deletions

9
include/apple2.lores.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef _APPLE2_LORES_H_
#define _APPLE2_LORES_H_
#include "apple2.h"
extern void apple2_lores_draw(apple2 *, size_t);
extern vm_color apple2_lores_color(vm_8bit);
#endif

View File

@ -8,6 +8,8 @@
extern char apple2_text_alternate(vm_8bit);
extern char apple2_text_primary(vm_8bit);
extern int apple2_text_area(vm_area *, vm_bitfont *, size_t);
extern int apple2_text_col(size_t);
extern int apple2_text_row(size_t);
extern void apple2_text_draw(apple2 *, size_t);
#endif

View File

@ -7,6 +7,20 @@
#include "vm_area.h"
#include "vm_bits.h"
typedef struct {
/*
* Red, green, blue
*/
vm_8bit r, g, b;
/*
* This is alpha, which would be the degree of transparency of the
* graphics. This is here only if needed--for example, the Apple II
* doesn't have any alpha channel.
*/
vm_8bit a;
} vm_color;
typedef struct {
/*
* This is the window in SDL that we're displaying. It's fine for a
@ -65,7 +79,7 @@ extern void vm_screen_finish();
extern void vm_screen_free(vm_screen *);
extern void vm_screen_prepare(vm_screen *);
extern void vm_screen_refresh(vm_screen *);
extern void vm_screen_set_color(vm_screen *, uint8_t, uint8_t, uint8_t, uint8_t);
extern void vm_screen_set_color(vm_screen *, vm_color);
extern void vm_screen_set_logical_coords(vm_screen *, int, int);
#endif

View File

@ -7,6 +7,7 @@ set(erc_sources
apple2.draw.c
apple2.enc.c
apple2.kb.c
apple2.lores.c
apple2.mem.c
apple2.pc.c
apple2.reflect.c

View File

@ -7,33 +7,9 @@
*/
#include "apple2.h"
#include "apple2.lores.h"
#include "apple2.text.h"
/*
* These are the color codes for the lo-res colors that are available.
* Each pixel in lo-res indicates one color. These are colors I found
* somewhere online -- I'm not sure if they are exact matches, and are
* subject to change.
*/
static int lores_colors[][3] = {
{ 0x00, 0x00, 0x00 }, // black
{ 0xff, 0x28, 0x97 }, // magenta
{ 0x60, 0x4d, 0xbc }, // dark blue
{ 0xff, 0x44, 0xfd }, // purple
{ 0x00, 0xa3, 0x60 }, // dark green
{ 0x9c, 0x9c, 0x9c }, // gray
{ 0x14, 0xcf, 0xfd }, // medium blue
{ 0xd0, 0xc3, 0xff }, // light blue
{ 0x60, 0x72, 0x03 }, // brown
{ 0xff, 0x6a, 0x3c }, // orange
{ 0x9c, 0x9c, 0x9c }, // gray
{ 0xff, 0xa0, 0xd0 }, // pink
{ 0x14, 0xf5, 0x3c }, // light green
{ 0xd0, 0xdd, 0x81 }, // yellow
{ 0x72, 0xff, 0xd0 }, // aquamarine
{ 0xff, 0xff, 0xff }, // white
};
/*
* Draw a pixel on screen at the given address.
* FIXME: we do not draw anything D:
@ -55,6 +31,7 @@ apple2_draw_pixel(apple2 *mach, vm_16bit addr)
void
apple2_draw_pixel_lores(apple2 *mach, vm_16bit addr)
{
#if 0
vm_8bit color = vm_segment_get(mach->main, addr);
vm_8bit top, bottom;
vm_area loc;
@ -85,6 +62,7 @@ apple2_draw_pixel_lores(apple2 *mach, vm_16bit addr)
colors = lores_colors[bottom];
vm_screen_set_color(mach->screen, colors[0], colors[1], colors[2], 255);
vm_screen_draw_rect(mach->screen, &loc);
#endif
}
/*
@ -103,6 +81,21 @@ apple2_draw_40col(apple2 *mach)
}
}
/*
* Draw low-resolution graphics on the screen
*/
void
apple2_draw_lores(apple2 *mach)
{
size_t addr;
vm_screen_prepare(mach->screen);
for (addr = 0x400; addr < 0x800; addr++) {
apple2_lores_draw(mach, addr);
}
}
/*
* Find the right draw method for the machine, based on its display
* mode, and use that to refresh the screen.
@ -112,5 +105,8 @@ apple2_draw(apple2 *mach)
{
if (mach->display_mode & DISPLAY_TEXT) {
apple2_draw_40col(mach);
return;
}
apple2_draw_lores(mach);
}

11
src/apple2.grid.c Normal file
View File

@ -0,0 +1,11 @@
/*
* apple2.grid.c
*
* Each of the display modes in the Apple II work off of a grid, but the
* grids are generally interleaved, so there's no simple formula to
* follow.
*
* In here we define tables which map addresses to rows or columns
* within a grid, and some functions to pull that information from those
* tables.
*/

94
src/apple2.lores.c Normal file
View File

@ -0,0 +1,94 @@
/*
* 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.h"
#include "apple2.lores.h"
#include "apple2.text.h"
/*
* These are the color codes for the lo-res colors that are available.
* Each pixel in lo-res indicates one color. These are colors I found
* somewhere online -- I'm not sure if they are exact matches, and are
* subject to change.
*/
static vm_color lores_colors[] = {
{ 0x00, 0x00, 0x00, 0x00 }, // black
{ 0xff, 0x28, 0x97, 0x00 }, // magenta
{ 0x60, 0x4d, 0xbc, 0x00 }, // dark blue
{ 0xff, 0x44, 0xfd, 0x00 }, // purple
{ 0x00, 0xa3, 0x60, 0x00 }, // dark green
{ 0x9c, 0x9c, 0x9c, 0x00 }, // gray
{ 0x14, 0xcf, 0xfd, 0x00 }, // medium blue
{ 0xd0, 0xc3, 0xff, 0x00 }, // light blue
{ 0x60, 0x72, 0x03, 0x00 }, // brown
{ 0xff, 0x6a, 0x3c, 0x00 }, // orange
{ 0x9c, 0x9c, 0x9c, 0x00 }, // gray
{ 0xff, 0xa0, 0xd0, 0x00 }, // pink
{ 0x14, 0xf5, 0x3c, 0x00 }, // light green
{ 0xd0, 0xdd, 0x81, 0x00 }, // yellow
{ 0x72, 0xff, 0xd0, 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);
// 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);
}
vm_color
apple2_lores_color(vm_8bit byte)
{
return lores_colors[byte & 0xf];
}

View File

@ -225,6 +225,24 @@ static char alternate_display[] = {
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', ' ',
};
/*
* Return the row where the given address will be displayed.
*/
int
apple2_text_row(size_t addr)
{
return buffer_rows[addr];
}
/*
* Return the column where the given address will be displayed.
*/
int
apple2_text_col(size_t addr)
{
return buffer_cols[addr];
}
/*
* Return the primary character set representation matching the given
* character code.

View File

@ -258,6 +258,7 @@ mos6502_dis_opcode(mos6502 *cpu, FILE *stream, int address)
int addr_mode;
int inst_code;
int expected;
char status[9];
memset(s_bytes, 0, sizeof(s_bytes));
memset(s_inst, 0, sizeof(s_inst));
@ -326,8 +327,18 @@ mos6502_dis_opcode(mos6502 *cpu, FILE *stream, int address)
snprintf(s_bytes, sizeof(s_bytes) - 1, "%02X", opcode);
}
fprintf(stream, "%04X:%-9s%20s %s\n",
cpu->PC, s_bytes, s_inst, s_operand);
snprintf(status, sizeof(status), "%c%c_%c%c%c%c%c",
cpu->P & MOS_NEGATIVE ? 'N' : '_',
cpu->P & MOS_OVERFLOW ? 'V' : '_',
cpu->P & MOS_BREAK ? 'B' : '_',
cpu->P & MOS_DECIMAL ? 'D' : '_',
cpu->P & MOS_INTERRUPT ? 'I' : '_',
cpu->P & MOS_ZERO ? 'Z' : '_',
cpu->P & MOS_CARRY ? 'C' : '_');
fprintf(stream, "%04X:%-9s%20s %-20s; A:%02X X:%02X Y:%02X P:%02X<%s> S:%02X\n",
cpu->PC, s_bytes, s_inst, s_operand,
cpu->A, cpu->X, cpu->Y, cpu->P, status, cpu->S);
}
// The expected number of bytes here is for the operand, but we need

View File

@ -129,7 +129,10 @@ vm_screen_add_window(vm_screen *screen, int width, int height)
// the set_logical_coords function with different values.
vm_screen_set_logical_coords(screen, width, height);
vm_screen_set_color(screen, 0, 0, 0, 0);
vm_color clr;
memset(&clr, 0, sizeof(vm_color));
vm_screen_set_color(screen, clr);
vm_screen_prepare(screen);
return OK;
@ -210,14 +213,11 @@ vm_screen_refresh(vm_screen *screen)
* Set the color of a screen screen to a given RGBA value.
*/
void
vm_screen_set_color(vm_screen *screen,
uint8_t red,
uint8_t green,
uint8_t blue,
uint8_t alpha)
vm_screen_set_color(vm_screen *scr, vm_color clr)
{
if (screen->render) {
SDL_SetRenderDrawColor(screen->render, red, green, blue, alpha);
if (scr->render) {
SDL_SetRenderDrawColor(scr->render, clr.r, clr.g, clr.g,
SDL_ALPHA_OPAQUE);
}
}