Work-in-progress support for Apple //e auxmem

This commit is contained in:
Bobbi Webber-Manners 2020-08-05 22:30:55 -04:00
parent f0e6d9a376
commit 6c6c187cba

View File

@ -5,8 +5,9 @@
// Note: Use my fork of cc65 to get a flashing cursor!! // Note: Use my fork of cc65 to get a flashing cursor!!
// TODO: Make use of aux mem. Need to move all functions that access gapbuf[] // TODO: Finish off auxmem support. See TODOs below
// to LC segment
#define AUXMEM // HIGHLY EXPERIMENTAL
#include <conio.h> #include <conio.h>
#include <ctype.h> #include <ctype.h>
@ -31,10 +32,15 @@
#define ESC 0x1b #define ESC 0x1b
#define DELETE 0x7f #define DELETE 0x7f
#ifdef AUXMEM
#define BUFSZ 0xb7fe // All of aux from 0x800 to 0xbfff, minus a byte
char iobuf[RDSZ]; // Buffer for disk I/O
#else
#define BUFSZ (20480 - 1024) // 19KB #define BUFSZ (20480 - 1024) // 19KB
char gapbuf[BUFSZ]; char gapbuf[BUFSZ];
char padding = 0; // To null terminate for strstr() char padding = 0; // To null terminate for strstr()
#endif
uint16_t gapbegin = 0; uint16_t gapbegin = 0;
uint16_t gapend = BUFSZ - 1; uint16_t gapend = BUFSZ - 1;
@ -79,6 +85,59 @@ char openapple[] = "\x0f\x1b""A\x18\x0e";
*/ */
#define GETPOS() (gapbegin) #define GETPOS() (gapbegin)
/*
* Obtain one byte from the gapbuf[] in aux memory
* Must be in LC
*/
#pragma code-name (push, "LC")
char get_gapbuf(uint16_t i) {
#ifdef AUXMEM
*(uint16_t*)(0xfe) = (uint16_t)0x0800 + i; // Stuff address in Zero Page
__asm__("sta $c003"); // Read aux mem
__asm__("lda ($fe)");
__asm__("sta $ff");
__asm__("sta $c002"); // Read main mem
return *(uint8_t*)(0xff);
#else
return gapbuf[i];
#endif
}
#pragma code-name (pop)
/*
* Set one byte in the gapbuf[] in aux memory
* Must be in LC
*/
#pragma code-name (push, "LC")
void set_gapbuf(uint16_t i, char c) {
#ifdef AUXMEM
__asm__("sta $c005"); // Write aux mem
(*(char*)((char*)0x800 + i)) = c;
__asm__("sta $c004"); // Write main mem
#else
gapbuf[i] = c;
#endif
}
#pragma code-name (pop)
/*
* Do a memmove() on aux memory. Uses indices into gapbuf[].
* Must be in LC
*/
#pragma code-name (push, "LC")
void move_in_gapbuf(uint16_t dest, uint16_t src, size_t n) {
#ifdef AUXMEM
__asm__("sta $c005"); // Write aux mem
__asm__("sta $c003"); // Read aux mem
// TODO DO STUFF
__asm__("sta $c002"); // Read main mem
__asm__("sta $c004"); // Write main mem
#else
memmove(gapbuf + dest, gapbuf + src, n);
#endif
}
#pragma code-name (pop)
/* /*
* Annoying beep * Annoying beep
*/ */
@ -266,7 +325,6 @@ esc_pressed:
/* /*
* Prompt ok? * Prompt ok?
*/ */
#pragma code-name (push, "LC")
char prompt_okay(char *msg) { char prompt_okay(char *msg) {
char c; char c;
cursor(0); cursor(0);
@ -288,12 +346,10 @@ char prompt_okay(char *msg) {
update_status_line(); update_status_line();
return c; return c;
} }
#pragma code-name (pop)
/* /*
* Error message * Error message
*/ */
#pragma code-name (push, "LC")
void show_error(char *msg) { void show_error(char *msg) {
cursor(0); cursor(0);
goto_prompt_row(); goto_prompt_row();
@ -305,7 +361,6 @@ void show_error(char *msg) {
cgetc(); cgetc();
update_status_line(); update_status_line();
} }
#pragma code-name (pop)
/* /*
* Insert a character into gapbuf at current position * Insert a character into gapbuf at current position
@ -313,7 +368,7 @@ void show_error(char *msg) {
*/ */
void insert_char(char c) { void insert_char(char c) {
if (FREESPACE()) { if (FREESPACE()) {
gapbuf[gapbegin++] = c; set_gapbuf(gapbegin++, c);
return; return;
} }
beep(); beep();
@ -359,12 +414,12 @@ void jump_pos(uint16_t pos) {
return; return;
if (pos > GETPOS()) { if (pos > GETPOS()) {
l = pos - gapbegin; l = pos - gapbegin;
memmove(gapbuf + gapbegin, gapbuf + gapend + 1, l); move_in_gapbuf(gapbegin, gapend + 1, l);
gapbegin += l; gapbegin += l;
gapend += l; gapend += l;
} else { } else {
l = gapbegin - pos; l = gapbegin - pos;
memmove(gapbuf + gapend - l + 1, gapbuf + gapbegin - l, l); move_in_gapbuf(gapend - l + 1, gapbegin - l, l);
gapbegin -= l; gapbegin -= l;
gapend -= l; gapend -= l;
} }
@ -407,7 +462,11 @@ uint8_t load_file(char *filename, uint8_t replace) {
gapend = BUFSZ - 1; gapend = BUFSZ - 1;
col = 0; col = 0;
} }
#ifdef AUXMEM
p = iobuf;
#else
p = gapbuf + gapend - RDSZ; // Read to just before gapend p = gapbuf + gapend - RDSZ; // Read to just before gapend
#endif
do { do {
if (FREESPACE() < RDSZ * 2) { if (FREESPACE() < RDSZ * 2) {
show_error("File truncated"); show_error("File truncated");
@ -420,17 +479,17 @@ uint8_t load_file(char *filename, uint8_t replace) {
switch (p[i]) { switch (p[i]) {
case '\r': // Native Apple2 files case '\r': // Native Apple2 files
case '\n': // UNIX files case '\n': // UNIX files
gapbuf[gapbegin++] = '\r'; set_gapbuf(gapbegin++, '\r');
col = 0; col = 0;
break; break;
case '\t': case '\t':
c = next_tabstop(col) - col; c = next_tabstop(col) - col;
for (j = 0; j < c; ++j) for (j = 0; j < c; ++j)
gapbuf[gapbegin++] = ' '; set_gapbuf(gapbegin++, ' ');
col += c; col += c;
break; break;
default: default:
gapbuf[gapbegin++] = p[i]; set_gapbuf(gapbegin++, p[i]);
++col; ++col;
} }
if (FREESPACE() < RDSZ * 2) { if (FREESPACE() < RDSZ * 2) {
@ -473,7 +532,11 @@ uint8_t save_file(char *filename) {
goto done; goto done;
jump_pos(0); jump_pos(0);
goto_prompt_row(); goto_prompt_row();
#ifdef AUXMEM
p = iobuf;
#else
p = gapbuf + gapend + 1; p = gapbuf + gapend + 1;
#endif
for (i = 0; i < DATASIZE() / WRTSZ; ++i) { for (i = 0; i < DATASIZE() / WRTSZ; ++i) {
cputc('.'); cputc('.');
if (fwrite(p, WRTSZ, 1, fp) != 1) if (fwrite(p, WRTSZ, 1, fp) != 1)
@ -504,7 +567,7 @@ done:
uint8_t read_char_update_pos(void) { uint8_t read_char_update_pos(void) {
uint16_t delta = gapend - gapbegin; uint16_t delta = gapend - gapbegin;
char c; char c;
if ((c = gapbuf[pos++]) == EOL) { if ((c = get_gapbuf(pos++)) == EOL) {
if (do_print) { if (do_print) {
rowlen[row] = col + 1; rowlen[row] = col + 1;
clreol_wrap(); clreol_wrap();
@ -616,7 +679,7 @@ void scroll_down() {
uint8_t is_last_line(void) { uint8_t is_last_line(void) {
uint16_t p = gapend + 1; uint16_t p = gapend + 1;
while (p < BUFSZ) { while (p < BUFSZ) {
if (gapbuf[p++] == '\r') if (get_gapbuf(p++) == '\r')
return 0; return 0;
} }
return 1; return 1;
@ -642,7 +705,7 @@ void update_after_delete_char_right(void) {
clreol_wrap(); clreol_wrap();
// If necessary, print rest of screen // If necessary, print rest of screen
if ((gapbuf[gapend] == EOL) || (i == NCOLS - 1)) { if ((get_gapbuf(gapend) == EOL) || (i == NCOLS - 1)) {
while ((pos < BUFSZ) && (row < NROWS)) while ((pos < BUFSZ) && (row < NROWS))
read_char_update_pos(); read_char_update_pos();
@ -668,7 +731,7 @@ void update_after_delete_char(void) {
col = curscol; col = curscol;
row = cursrow; row = cursrow;
if (gapbuf[gapbegin] == EOL) { if (get_gapbuf(gapbegin) == EOL) {
// Special handling if we deleted an EOL // Special handling if we deleted an EOL
if (row > 0) if (row > 0)
col = rowlen[--row] - 1; col = rowlen[--row] - 1;
@ -710,7 +773,7 @@ void update_after_delete_char(void) {
clreol_wrap(); clreol_wrap();
// If necessary, print rest of screen // If necessary, print rest of screen
if ((gapbuf[gapbegin] == EOL) || (i == NCOLS - 1)) { if ((get_gapbuf(gapbegin) == EOL) || (i == NCOLS - 1)) {
while ((pos < BUFSZ) && (row < NROWS)) while ((pos < BUFSZ) && (row < NROWS))
read_char_update_pos(); read_char_update_pos();
@ -758,7 +821,7 @@ void update_after_insert_char(void) {
} }
// If necessary, print rest of screen // If necessary, print rest of screen
if ((gapbuf[gapbegin - 1] == EOL) || (prevcol == 0)) if ((get_gapbuf(gapbegin - 1) == EOL) || (prevcol == 0))
while ((pos < BUFSZ) && (row < NROWS)) while ((pos < BUFSZ) && (row < NROWS))
read_char_update_pos(); read_char_update_pos();
@ -772,7 +835,7 @@ void update_after_insert_char(void) {
#pragma code-name (push, "LC") #pragma code-name (push, "LC")
void cursor_left(void) { void cursor_left(void) {
if (gapbegin > 0) if (gapbegin > 0)
gapbuf[gapend--] = gapbuf[--gapbegin]; set_gapbuf(gapend--, get_gapbuf(--gapbegin));
else { else {
beep(); beep();
gotoxy(curscol, cursrow); gotoxy(curscol, cursrow);
@ -794,7 +857,7 @@ void cursor_left(void) {
if (mode > SEL_MOVE2) { if (mode > SEL_MOVE2) {
endsel = gapbegin; endsel = gapbegin;
revers(gapbegin < startsel ? 1 : 0); revers(gapbegin < startsel ? 1 : 0);
cputc(gapbuf[gapbegin]); cputc(get_gapbuf(gapbegin));
} }
revers(0); revers(0);
gotoxy(curscol, cursrow); gotoxy(curscol, cursrow);
@ -807,7 +870,7 @@ void cursor_left(void) {
#pragma code-name (push, "LC") #pragma code-name (push, "LC")
void cursor_right(void) { void cursor_right(void) {
if (gapend < BUFSZ - 1) if (gapend < BUFSZ - 1)
gapbuf[gapbegin++] = gapbuf[++gapend]; set_gapbuf(gapbegin++, get_gapbuf(++gapend));
else { else {
beep(); beep();
goto done; goto done;
@ -825,7 +888,7 @@ done:
if (mode > SEL_MOVE2) { if (mode > SEL_MOVE2) {
endsel = gapbegin; endsel = gapbegin;
revers(gapbegin > startsel ? 1 : 0); revers(gapbegin > startsel ? 1 : 0);
cputc(gapbuf[gapbegin - 1]); cputc(get_gapbuf(gapbegin - 1));
} }
revers(0); revers(0);
gotoxy(curscol, cursrow); gotoxy(curscol, cursrow);
@ -848,11 +911,11 @@ uint8_t cursor_up(void) {
} }
} }
for (i = curscol; i > 0; --i) { for (i = curscol; i > 0; --i) {
gapbuf[gapend--] = gapbuf[--gapbegin]; set_gapbuf(gapend--, get_gapbuf(--gapbegin));
if (mode > SEL_MOVE2) { if (mode > SEL_MOVE2) {
gotoxy(i - 1, cursrow); gotoxy(i - 1, cursrow);
revers(gapbegin < startsel ? 1 : 0); revers(gapbegin < startsel ? 1 : 0);
cputc(gapbuf[gapbegin]); cputc(get_gapbuf(gapbegin));
} }
} }
--cursrow; --cursrow;
@ -860,11 +923,11 @@ uint8_t cursor_up(void) {
if (curscol > rowlen[cursrow] - 1) if (curscol > rowlen[cursrow] - 1)
curscol = rowlen[cursrow] - 1; curscol = rowlen[cursrow] - 1;
for (i = rowlen[cursrow]; i > curscol; --i) { for (i = rowlen[cursrow]; i > curscol; --i) {
gapbuf[gapend--] = gapbuf[--gapbegin]; set_gapbuf(gapend--, get_gapbuf(--gapbegin));
if (mode > SEL_MOVE2) { if (mode > SEL_MOVE2) {
gotoxy(i - 1, cursrow); gotoxy(i - 1, cursrow);
revers(gapbegin < startsel ? 1 : 0); revers(gapbegin < startsel ? 1 : 0);
cputc(gapbuf[gapbegin]); cputc(get_gapbuf(gapbegin));
} }
} }
if (mode > SEL_MOVE2) { if (mode > SEL_MOVE2) {
@ -885,16 +948,16 @@ uint8_t cursor_down(void) {
uint8_t i; uint8_t i;
if (cursrow == NROWS - 1) if (cursrow == NROWS - 1)
scroll_down(); scroll_down();
if ((gapbuf[gapend + rowlen[cursrow] - curscol] != EOL) && if ((get_gapbuf(gapend + rowlen[cursrow] - curscol) != EOL) &&
(rowlen[cursrow] != NCOLS)) (rowlen[cursrow] != NCOLS))
return 1; // Last line return 1; // Last line
for (i = 0; i < rowlen[cursrow] - curscol; ++i) { for (i = 0; i < rowlen[cursrow] - curscol; ++i) {
if (gapend < BUFSZ - 1) { if (gapend < BUFSZ - 1) {
gapbuf[gapbegin++] = gapbuf[++gapend]; set_gapbuf(gapbegin++, get_gapbuf(++gapend));
if (mode > SEL_MOVE2) { if (mode > SEL_MOVE2) {
revers(gapbegin > startsel ? 1 : 0); revers(gapbegin > startsel ? 1 : 0);
cputc(gapbuf[gapbegin - 1]); cputc(get_gapbuf(gapbegin - 1));
} }
} }
else { else {
@ -909,10 +972,10 @@ uint8_t cursor_down(void) {
gotoxy(0, cursrow); gotoxy(0, cursrow);
for (i = 0; i < curscol; ++i) { for (i = 0; i < curscol; ++i) {
if (gapend < BUFSZ - 1) { if (gapend < BUFSZ - 1) {
gapbuf[gapbegin++] = gapbuf[++gapend]; set_gapbuf(gapbegin++, get_gapbuf(++gapend));
if (mode > SEL_MOVE2) { if (mode > SEL_MOVE2) {
revers(gapbegin > startsel ? 1 : 0); revers(gapbegin > startsel ? 1 : 0);
cputc(gapbuf[gapbegin - 1]); cputc(get_gapbuf(gapbegin - 1));
} }
} }
} }
@ -952,7 +1015,7 @@ void goto_eol(void) {
void word_left(void) { void word_left(void) {
do { do {
cursor_left(); cursor_left();
} while ((gapbuf[gapbegin] != ' ') && (gapbuf[gapbegin] != EOL) && } while ((get_gapbuf(gapbegin) != ' ') && (get_gapbuf(gapbegin) != EOL) &&
(gapbegin > 0)); (gapbegin > 0));
} }
#pragma code-name (pop) #pragma code-name (pop)
@ -964,7 +1027,7 @@ void word_left(void) {
void word_right(void) { void word_right(void) {
do { do {
cursor_right(); cursor_right();
} while ((gapbuf[gapbegin] != ' ') && (gapbuf[gapbegin] != EOL) && } while ((get_gapbuf(gapbegin) != ' ') && (get_gapbuf(gapbegin) != EOL) &&
(gapend < BUFSZ - 1)); (gapend < BUFSZ - 1));
} }
#pragma code-name (pop) #pragma code-name (pop)
@ -1001,7 +1064,7 @@ void word_wrap_para(uint8_t addbreaks) {
// Find start of paragraph ("\r\r" delimiter) // Find start of paragraph ("\r\r" delimiter)
while (i > 0) { while (i > 0) {
--i; --i;
if (gapbuf[i] == '\r') if (get_gapbuf(i) == '\r')
++rets; ++rets;
else else
rets = 0; rets = 0;
@ -1013,18 +1076,18 @@ void word_wrap_para(uint8_t addbreaks) {
// Iterate through para, up to the cursor // Iterate through para, up to the cursor
i = startpara; i = startpara;
while (i < gapbegin) { while (i < gapbegin) {
if (gapbuf[i] == '\r') if (get_gapbuf(i) == '\r')
gapbuf[i] = ' '; set_gapbuf(i, ' ');
++col; ++col;
if (addbreaks && (col == 76)) { if (addbreaks && (col == 76)) {
// Backtrack to find a space // Backtrack to find a space
while ((gapbuf[i] != ' ') && (i > startpara)) while ((get_gapbuf(i) != ' ') && (i > startpara))
--i; --i;
if (i == startpara) { if (i == startpara) {
beep(); beep();
return; return;
} }
gapbuf[i] = '\r'; // Break line set_gapbuf(i, '\r'); // Break line
col = 0; col = 0;
} }
++i; ++i;
@ -1040,7 +1103,7 @@ void help(void) {
FILE *fp = fopen("EDITHELP.TXT", "rb"); FILE *fp = fopen("EDITHELP.TXT", "rb");
char *p; char *p;
char c; char c;
uint16_t i, j, s; uint16_t i, s;
uint8_t cont; uint8_t cont;
revers(0); revers(0);
cursor(0); cursor(0);
@ -1049,7 +1112,11 @@ void help(void) {
printf("Can't open EDITHELP.TXT\n\n"); printf("Can't open EDITHELP.TXT\n\n");
goto done; goto done;
} }
#ifdef AUXMEM
p = iobuf;
#else
p = gapbuf + gapend - RDSZ; // Read to just before gapend p = gapbuf + gapend - RDSZ; // Read to just before gapend
#endif
do { do {
if (FREESPACE() < RDSZ) { if (FREESPACE() < RDSZ) {
beep(); beep();
@ -1265,35 +1332,58 @@ int edit(char *fname) {
} }
mode = SRCH1; mode = SRCH1;
update_status_line(); update_status_line();
#ifdef AUXMEM
// TODO
#else
p = strstr(gapbuf + gapend + 1, search); p = strstr(gapbuf + gapend + 1, search);
#endif
if (!p) { if (!p) {
mode = SRCH2; mode = SRCH2;
update_status_line(); update_status_line();
gapbuf[gapbegin] = '\0'; set_gapbuf(gapbegin, '\0');
#ifdef AUXMEM
// TODO
#else
p = strstr(gapbuf, search); p = strstr(gapbuf, search);
#endif
mode = SEL_NONE; mode = SEL_NONE;
if (!p) { if (!p) {
mode = SRCH3; mode = SRCH3;
update_status_line(); update_status_line();
break; break;
} }
#ifdef AUXMEM
// TODO
#else
jump_pos(p - gapbuf); jump_pos(p - gapbuf);
#endif
if (tmp == 0) { // Replace mode if (tmp == 0) { // Replace mode
for (i = 0; i < strlen(search); ++i) for (i = 0; i < strlen(search); ++i)
delete_char_right(); delete_char_right();
#ifdef AUXMEM
// TODO
#else
memcpy(gapbuf + gapbegin, replace, strlen(userentry)); memcpy(gapbuf + gapbegin, replace, strlen(userentry));
gapbegin += strlen(replace); gapbegin += strlen(replace);
#endif
} }
draw_screen(); draw_screen();
break; break;
} }
mode = SEL_NONE; mode = SEL_NONE;
#ifdef AUXMEM
// TODO
#else
jump_pos(gapbegin + p - (gapbuf + gapend + 1)); jump_pos(gapbegin + p - (gapbuf + gapend + 1));
#endif
if (tmp == 0) { // Replace mode if (tmp == 0) { // Replace mode
for (i = 0; i < strlen(search); ++i) for (i = 0; i < strlen(search); ++i)
delete_char_right(); delete_char_right();
#ifdef AUXMEM
#else
memcpy(gapbuf + gapbegin, replace, strlen(userentry)); memcpy(gapbuf + gapbegin, replace, strlen(userentry));
gapbegin += strlen(replace); gapbegin += strlen(replace);
#endif
} }
draw_screen(); draw_screen();
break; break;
@ -1467,10 +1557,11 @@ int edit(char *fname) {
sprintf(userentry, "%s selection - ", mode == SEL_COPY2 ? "Copy" : "Move"); sprintf(userentry, "%s selection - ", mode == SEL_COPY2 ? "Copy" : "Move");
if (prompt_okay(userentry)) { if (prompt_okay(userentry)) {
if (gapbegin >= endsel) if (gapbegin >= endsel)
memcpy(gapbuf + gapbegin, gapbuf + startsel, endsel - startsel); move_in_gapbuf(gapbegin, startsel, endsel - startsel);
else else
memcpy(gapbuf + gapbegin, move_in_gapbuf(gapbegin,
gapbuf + gapend + startsel - gapbegin + 1, endsel - startsel); gapend + startsel - gapbegin + 1,
endsel - startsel);
gapbegin += (endsel - startsel); gapbegin += (endsel - startsel);
if (mode == SEL_MOVE2) { if (mode == SEL_MOVE2) {
jump_pos((gapbegin >= endsel) ? startsel : endsel); jump_pos((gapbegin >= endsel) ? startsel : endsel);
@ -1498,6 +1589,10 @@ copymove2_cleanup:
} }
void main(int argc, char *argv[]) { void main(int argc, char *argv[]) {
#ifdef AUXMEM
char *pad = 0xbfff;
*pad = '\0'; // Null termination for strstr()
#endif
if (argc == 2) { if (argc == 2) {
quit_to_email = 1; quit_to_email = 1;
edit(argv[1]); edit(argv[1]);