diff --git a/include/apple2.draw.h b/include/apple2.draw.h new file mode 100644 index 0000000..bba8853 --- /dev/null +++ b/include/apple2.draw.h @@ -0,0 +1,7 @@ +#ifndef _APPLE2_DRAW_H_ +#define _APPLE2_DRAW_H_ + +extern void apple2_draw_pixel(apple2 *, vm_16bit); +extern void apple2_draw_text(apple2 *, vm_16bit); + +#endif diff --git a/sources.cmake b/sources.cmake index 87f9467..30f3f9f 100644 --- a/sources.cmake +++ b/sources.cmake @@ -1,6 +1,7 @@ set(erc_sources apple2.c apple2.dd.c + apple2.draw.c log.c mos6502.c mos6502.addr.c diff --git a/src/apple2.c b/src/apple2.c index a3664d4..412f09f 100644 --- a/src/apple2.c +++ b/src/apple2.c @@ -6,6 +6,7 @@ */ #include "apple2.h" +#include "apple2.draw.h" #include "option.h" #include "vm_segment.h" @@ -86,21 +87,10 @@ apple2_set_color(apple2 *mach, int mode) // correct color interpretation } -#define SHOW(ch) \ - vm_bitfont_render(mach->sysfont, mach->screen, &area, ch); \ - area.x += 7 - void apple2_run_loop(apple2 *mach) { - SDL_Rect area; - - while (vm_screen_active(mach->screen)) { - area.x = 50; - area.y = 50; - SHOW('H'); SHOW('e'); SHOW('l'); SHOW('l'); SHOW('o'); SHOW(' '); - SHOW('w'); SHOW('o'); SHOW('r'); SHOW('l'); SHOW('d'); SHOW('!'); vm_screen_refresh(mach->screen); } } diff --git a/src/apple2.draw.c b/src/apple2.draw.c index 53f9346..b0048d7 100644 --- a/src/apple2.draw.c +++ b/src/apple2.draw.c @@ -2,15 +2,82 @@ * apple2.draw.c */ +#include "apple2.h" + void apple2_draw_pixel(apple2 *mach, vm_16bit addr) { } +// Drawing text is a two-step process; first you need to wipe out +// the block on the screen at that point. Then you need to draw the +// text in over that. + void apple2_draw_text(apple2 *mach, vm_16bit addr) { - // Drawing text is a two-step process; first you need to wipe out - // the block on the screen at that point. Then you need to draw the - // text in over that. + vm_8bit lsb, msb; + vm_16bit page_base; + SDL_Rect dest; + char ch; + + // The text display buffers are located at "Page 1" and "Page 2", + // which are at byte 1024-2047 (0x0400-0x07FF) and byte 2048-3071 + // (0x0800-0x0BFF) respectively. If the given address is not in + // those (contiguous) ranges, then let's bail. + if (addr < 0x0400 || addr > 0x0BFF) { + return; + } + + // In a given page for 40-column mode, you get 960 grid parts that + // you may use. In 80-column mode, it's more like 1920 grid parts + // (40x24 = 960, 80x24 = 1920). The way we look at this is the + // address indicates the place on the grid where text should go. We + // don't care how it got there. Let's figure out that position + // on-screen. + msb = (addr >> 8) & 0xff; // row + lsb = addr & 0xff; // column + + // Regardless of which page we're rendering into, we can only use 40 + // cells on the grid (that is, 0-39 from whatever value the msb is). + // It's possible to have an lsb greater than that, but if so, it's + // not anything we can render to the screen. + if (lsb > 39) { + return; + } + + if ((addr & 0xff80) % 128 != 0) { + return; + } + + // By default, we assume we're in text page 1. If the address ends + // up being greater than 0x07FF, then we must be in page 2. + page_base = 0x0400; + if (addr > 0x07FF) { + page_base = 0x0800; + } + + // The absolute column position will be the font width times the + // lsb. + dest.x = lsb * mach->sysfont->width; + + // The absolute row position will be the font height times the msb + // minus the page base (because the height is the same regardless of + // what page we're in). So if we're msb $0400, then we're starting + // on pixel row 0; but if we're msb $0480, then we are starting on + // pixel row 8 (where the font height is 8); etc. + dest.y = ((addr & 0xff80) - page_base) * mach->sysfont->height; + + // Our width and height must be that of the font. + dest.w = mach->sysfont->width; + dest.h = mach->sysfont->height; + + // And...lastly...what's in the address? + ch = (char)vm_segment_get(mach->memory, addr); + + // Let's firstly blank out that space on screen. + //vm_bitfont_render(mach->sysfont, mach->screen, &dest, ' '); + + // Now show the goddamned thing + vm_bitfont_render(mach->sysfont, mach->screen, &dest, ch); }