erc-c/src/apple2/draw.c

131 lines
3.2 KiB
C

/*
* apple2.draw.c
*
* Draw pretty pixels on the screen in the way that Apple II would work.
* NB: this code is pretty rough, and I expect some changes as we get
* further into development.
*/
#include "apple2/apple2.h"
#include "apple2/hires.h"
#include "apple2/lores.h"
#include "apple2/text.h"
/*
* Draw a pixel on screen at the given address.
* FIXME: we do not draw anything D:
*/
void
apple2_draw_pixel(apple2 *mach, vm_16bit addr)
{
}
/*
* In single lo-res mode, pixels are 40x40 on the screen. But since our
* single mode has 280 pixels that _we_ show, this means that a pixel in
* single lo-res is really 7 columns wide. (Confusing yet?) Each "row" in
* text page 1 is just a row of visible dots, and 4 rows are equivalent
* to one "pixel" in lo-res mode.
*
* Without text, you get 40x48 pixels.
*/
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;
int *colors;
// The top color is the low order nibble, so we can blank out the
// high order nibble by AND-ing a mask of 0x0f (which is b00001111,
// 15 decimal). The bottom color, ergo, is the high order nibble;
// for that, we simply shift the color 4 positions to the right.
top = color & 0x0F;
bottom = color >> 4;
// The next thing we need to consider is where we draw the pixel
loc.xoff = (addr & 0xff) * mach->sysfont->width;
loc.yoff = (addr >> 8) * mach->sysfont->height;
loc.width = mach->sysfont->width;
loc.height = mach->sysfont->height / 2;
colors = lores_colors[top];
vm_screen_set_color(mach->screen, colors[0], colors[1], colors[2], 255);
vm_screen_draw_rect(mach->screen, &loc);
// The bottom pixel we need to draw now must be offset by the height
// of the pixel we just drew. (Remember, positive equals down in the
// y-axis.)
loc.yoff += loc.height;
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
}
/*
* Draw the 40-column text necessary to render everything on the screen
* with the machine in its current state.
*/
void
apple2_draw_40col(apple2 *mach)
{
size_t addr;
vm_screen_prepare(mach->screen);
for (addr = 0x400; addr < 0x800; addr++) {
apple2_text_draw(mach, addr);
}
}
/*
* 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);
}
}
/*
* Draw high-resolution graphics on the screen
*/
void
apple2_draw_hires(apple2 *mach)
{
vm_screen_prepare(mach->screen);
for (int row = 0; row < 192; row++) {
apple2_hires_draw(mach, row);
}
}
/*
* Find the right draw method for the machine, based on its display
* mode, and use that to refresh the screen.
*/
void
apple2_draw(apple2 *mach)
{
if (mach->display_mode & DISPLAY_TEXT) {
apple2_draw_40col(mach);
return;
} else if (mach->memory_mode & MEMORY_HIRES) {
apple2_draw_hires(mach);
return;
}
// The fallback mode is to draw lores graphics
apple2_draw_lores(mach);
}