mirror of
https://github.com/pevans/erc-c.git
synced 2025-01-03 00:29:38 +00:00
First crack at lo-res graphics
This commit is contained in:
parent
5a43ca9a7a
commit
df960220ef
9
include/apple2.lores.h
Normal file
9
include/apple2.lores.h
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
11
src/apple2.grid.c
Normal 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
94
src/apple2.lores.c
Normal 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];
|
||||
}
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user