mirror of
https://github.com/bradgrantham/apple2a.git
synced 2024-10-31 23:09:39 +00:00
Scroll screen; remove volatile.
This commit is contained in:
parent
6d7af284a1
commit
5d453e8f58
61
main.c
61
main.c
@ -1,3 +1,5 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "exporter.h"
|
||||
#include "platform.h"
|
||||
#include "runtime.h"
|
||||
@ -47,40 +49,6 @@ void (*g_compiled_function)() = (void (*)()) g_compiled;
|
||||
// - Nul.
|
||||
uint8_t g_program[1024];
|
||||
|
||||
|
||||
/**
|
||||
* Copy a memory buffer. Source and destination may overlap.
|
||||
*/
|
||||
static void memmove(uint8_t *dest, uint8_t *src, uint16_t count) {
|
||||
// See if we overlap.
|
||||
if (dest > src && dest < src + count) {
|
||||
// Overlapping with src before dest, we have to copy backward.
|
||||
dest += count;
|
||||
src += count;
|
||||
while (count-- > 0) {
|
||||
*--dest = *--src;
|
||||
}
|
||||
} else {
|
||||
// No overlap, or dest before src, which is fine.
|
||||
while (count-- > 0) {
|
||||
*dest++ = *src++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the length of a nul-terminated string.
|
||||
*/
|
||||
static int16_t strlen(uint8_t *s) {
|
||||
uint8_t *original = s;
|
||||
|
||||
while (*s != '\0') {
|
||||
s += 1;
|
||||
}
|
||||
|
||||
return s - original;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the tokenized string, with tokens displayed as their full text.
|
||||
* Prints a newline at the end.
|
||||
@ -190,20 +158,6 @@ static void add_return() {
|
||||
g_compiled[g_compiled_length++] = I_RTS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Advance s over whitespace, which is just a space, returning
|
||||
* the new pointer.
|
||||
*/
|
||||
/* Unused.
|
||||
static uint8_t *skip_whitespace(uint8_t *s) {
|
||||
while (*s == ' ') {
|
||||
s += 1;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Parse an unsigned integer, returning the value and moving the pointer
|
||||
* past the end of the number. The pointer must already be at the beginning
|
||||
@ -421,7 +375,7 @@ static void process_input_buffer() {
|
||||
// Dump compiled buffer to the terminal.
|
||||
{
|
||||
int i;
|
||||
volatile uint8_t *debug_port = (uint8_t *) 0xBFFE;
|
||||
uint8_t *debug_port = (uint8_t *) 0xBFFE;
|
||||
debug_port[0] = g_compiled_length;
|
||||
for (i = 0; i < g_compiled_length; i++) {
|
||||
debug_port[1] = g_compiled[i];
|
||||
@ -522,7 +476,7 @@ int16_t main(void)
|
||||
if (1) {
|
||||
int16_t i;
|
||||
for (i = 0; i < 256; i++) {
|
||||
volatile uint8_t *loc;
|
||||
uint8_t *loc;
|
||||
// Fails with: unhandled instruction B2
|
||||
move_cursor(i % 16, i >> 4);
|
||||
// Works.
|
||||
@ -540,6 +494,9 @@ int16_t main(void)
|
||||
|
||||
// Prompt.
|
||||
print("\n\n]");
|
||||
// TODO crashes 6502. Delete:
|
||||
// asm("ldy #1");
|
||||
// asm("sta $FFFF,y");
|
||||
|
||||
// Keyboard input.
|
||||
blink = 0;
|
||||
@ -572,7 +529,7 @@ int16_t main(void)
|
||||
}
|
||||
} else if (key == 13) {
|
||||
// Return.
|
||||
move_cursor(0, g_cursor_y + 1);
|
||||
print_char('\n');
|
||||
|
||||
process_input_buffer();
|
||||
|
||||
@ -580,7 +537,7 @@ int16_t main(void)
|
||||
g_input_buffer_length = 0;
|
||||
} else {
|
||||
if (g_input_buffer_length < sizeof(g_input_buffer) - 1) {
|
||||
volatile uint8_t *loc = cursor_pos();
|
||||
uint8_t *loc = cursor_pos();
|
||||
*loc = key | 0x80;
|
||||
move_cursor(g_cursor_x + 1, g_cursor_y);
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "platform.h"
|
||||
|
||||
#define KBD_STATUS_OR_KEY ((volatile unsigned char *)0xC000)
|
||||
#define KBD_CLEAR_CURRENT_KEY ((volatile unsigned char *)0xC010)
|
||||
#define KBD_STATUS_OR_KEY ((unsigned char *)0xC000)
|
||||
#define KBD_CLEAR_CURRENT_KEY ((unsigned char *)0xC010)
|
||||
|
||||
#define KEY_READY_MASK 0x80
|
||||
#define KEY_VALUE_MASK 0x7F
|
||||
|
@ -1,8 +1,8 @@
|
||||
#ifndef __PLATFORM_H__
|
||||
#define __PLATFORM_H__
|
||||
|
||||
#define TEXT_PAGE1_BASE ((volatile unsigned char *)0x400)
|
||||
#define TEXT_PAGE2_BASE ((volatile unsigned char *)0x800)
|
||||
#define TEXT_PAGE1_BASE ((unsigned char *)0x400)
|
||||
#define TEXT_PAGE2_BASE ((unsigned char *)0x800)
|
||||
|
||||
// Standard types.
|
||||
typedef signed char int8_t;
|
||||
|
59
runtime.c
59
runtime.c
@ -1,7 +1,9 @@
|
||||
|
||||
#include <string.h>
|
||||
#include "runtime.h"
|
||||
|
||||
#define CURSOR_GLYPH 127
|
||||
#define SCREEN_HEIGHT 24
|
||||
#define SCREEN_WIDTH 40
|
||||
#define SCREEN_STRIDE (3*SCREEN_WIDTH + 8)
|
||||
|
||||
@ -13,14 +15,21 @@ uint16_t g_showing_cursor = 0;
|
||||
// Character at the cursor location.
|
||||
uint8_t g_cursor_ch = 0;
|
||||
|
||||
/**
|
||||
* Return the memory location of the zero-based (x,y) position on the screen.
|
||||
*/
|
||||
static uint8_t *screen_pos(uint16_t x, uint16_t y) {
|
||||
int16_t block = y >> 3;
|
||||
int16_t line = y & 0x07;
|
||||
|
||||
return TEXT_PAGE1_BASE + line*SCREEN_STRIDE + block*SCREEN_WIDTH + x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the memory location of the cursor.
|
||||
*/
|
||||
volatile uint8_t *cursor_pos(void) {
|
||||
int16_t block = g_cursor_y >> 3;
|
||||
int16_t line = g_cursor_y & 0x07;
|
||||
|
||||
return TEXT_PAGE1_BASE + line*SCREEN_STRIDE + block*SCREEN_WIDTH + g_cursor_x;
|
||||
uint8_t *cursor_pos(void) {
|
||||
return screen_pos(g_cursor_x, g_cursor_y);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -28,7 +37,7 @@ volatile uint8_t *cursor_pos(void) {
|
||||
*/
|
||||
void show_cursor(void) {
|
||||
if (!g_showing_cursor) {
|
||||
volatile uint8_t *pos = cursor_pos();
|
||||
uint8_t *pos = cursor_pos();
|
||||
g_cursor_ch = *pos;
|
||||
*pos = CURSOR_GLYPH | 0x80;
|
||||
g_showing_cursor = 1;
|
||||
@ -40,7 +49,7 @@ void show_cursor(void) {
|
||||
*/
|
||||
void hide_cursor(void) {
|
||||
if (g_showing_cursor) {
|
||||
volatile uint8_t *pos = cursor_pos();
|
||||
uint8_t *pos = cursor_pos();
|
||||
*pos = g_cursor_ch;
|
||||
g_showing_cursor = 0;
|
||||
}
|
||||
@ -60,27 +69,45 @@ void move_cursor(int16_t x, int16_t y) {
|
||||
* Clear the screen with non-reversed spaces.
|
||||
*/
|
||||
void home(void) {
|
||||
volatile uint8_t *p = TEXT_PAGE1_BASE;
|
||||
uint8_t ch = ' ' | 0x80;
|
||||
int16_t i;
|
||||
memset(TEXT_PAGE1_BASE, ' ' | 0x80, SCREEN_STRIDE*8);
|
||||
move_cursor(0, 0);
|
||||
}
|
||||
|
||||
// TODO: Could write these as words, not chars.
|
||||
for (i = SCREEN_STRIDE*8; i >= 0; i--) {
|
||||
*p++ = ch;
|
||||
/**
|
||||
* Screen the screen up one line, blanking out the bottom
|
||||
* row. Does not affect the cursor.
|
||||
*/
|
||||
static void scroll_up(void) {
|
||||
int i;
|
||||
uint8_t *previous_line = 0;
|
||||
|
||||
for (i = 0; i < SCREEN_HEIGHT; i++) {
|
||||
uint8_t *this_line = screen_pos(0, i);
|
||||
if (i > 0) {
|
||||
memmove(previous_line, this_line, SCREEN_WIDTH);
|
||||
}
|
||||
previous_line = this_line;
|
||||
}
|
||||
|
||||
move_cursor(0, 0);
|
||||
// This is provided by cc65:
|
||||
memset(previous_line, ' ' | 0x80, SCREEN_WIDTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the character and advances the cursor. Handles newlines.
|
||||
*/
|
||||
void print_char(uint8_t c) {
|
||||
volatile uint8_t *loc = cursor_pos();
|
||||
uint8_t *loc = cursor_pos();
|
||||
|
||||
if (c == '\n') {
|
||||
// TODO: Scroll.
|
||||
if (g_cursor_y == SCREEN_HEIGHT - 1) {
|
||||
// Scroll.
|
||||
hide_cursor();
|
||||
scroll_up();
|
||||
move_cursor(0, g_cursor_y);
|
||||
} else {
|
||||
move_cursor(0, g_cursor_y + 1);
|
||||
}
|
||||
} else {
|
||||
// Print character.
|
||||
*loc = c | 0x80;
|
||||
|
Loading…
Reference in New Issue
Block a user