From 6bad8fa605f5011cadab428156c18b4067922185 Mon Sep 17 00:00:00 2001 From: mrb0nk500 Date: Tue, 24 Mar 2020 18:46:44 -0400 Subject: Added support in SuBEditor for true backspace, and inserting characters without replacing the old ones. --- programs/c-ports/subasm.c | 484 +++++++++++++++++++++++++++++++++++++++++-- programs/c-ports/subeditor.c | 38 +++- programs/c-ports/subeditor.h | 7 +- programs/subeditor.s | 191 ++++++++++++++--- 4 files changed, 658 insertions(+), 62 deletions(-) (limited to 'programs') diff --git a/programs/c-ports/subasm.c b/programs/c-ports/subasm.c index a996e3a..89d1507 100644 --- a/programs/c-ports/subasm.c +++ b/programs/c-ports/subasm.c @@ -1,33 +1,475 @@ #include "subeditor.h" -int16_t str_cmp(const char *s0, uint16_t i, const char *s1, uint16_t j) { - for (; s0[i] == s1[j]; i++, j++); - return i-j; + +struct line { + uint8_t dir; + uint8_t mne; + uint8_t am; + uint8_t opbase; + uint16_t com; + uint16_t label; + uint64_t op; +}; +char *label[0x1000]; +uint64_t label_addr[0x1000]; +/*char *comment[0x1000];*/ +/*char *string[0x1000];*/ + +enum dir { + DIR_ORG, + DIR_BYTE, + DIR_WORD, + DIR_DWORD, + DIR_QWORD +}; + +enum type { + TOK_DIR, + TOK_LABEL, + TOK_STRING, + TOK_OPCODE, + TOK_COMMENT, + TOK_HEX, + TOK_DEC, + TOK_BIN +}; + +enum am { + IMPL, + IMM, + ZM, + ZMX, + ZMY, + ABS, + IND, + INDX, + INDY +}; + +enum base { + HEX, + DEC, + BIN +}; + + +char lexeme[0x100]; +uint8_t lex_type; +struct line tokline[0x1000]; +uint16_t linenum = 10; + +static const char *mne_t[90] = { + [ 0] = "CPS", + [ 1] = "ADC", + [ 2] = "AAB", + [ 3] = "PHP", + [ 4] = "CPB", + [ 5] = "PHB", + [ 6] = "DEC", + [ 7] = "JMP", + [ 8] = "SBC", + [ 9] = "SAB", + [10] = "ENT", + [11] = "CPY", + [12] = "PLB", + [13] = "INC", + [14] = "JSR", + [15] = "JSL", + [16] = "AND", + [17] = "ABA", + [18] = "PLP", + [19] = "CPX", + [20] = "PHY", + [21] = "BPO", + [22] = "ORA", + [23] = "OAB", + [24] = "STT", + [25] = "PLY", + [26] = "BNG", + [27] = "XOR", + [28] = "XAB", + [29] = "PHA", + [30] = "PHX", + [31] = "BCS", + [32] = "LSL", + [33] = "LLB", + [34] = "CLC", + [35] = "PLX", + [36] = "BCC", + [37] = "LSR", + [38] = "LRB", + [39] = "PLA", + [40] = "TAB", + [41] = "BEQ", + [42] = "ROL", + [43] = "RLB", + [44] = "SEC", + [45] = "TBA", + [46] = "BNE", + [47] = "ROR", + [48] = "RRB", + [49] = "DEY", + [50] = "TAY", + [51] = "BVS", + [52] = "MUL", + [53] = "MAB", + [54] = "CLI", + [55] = "TYA", + [56] = "BVC", + [57] = "DIV", + [58] = "DAB", + [59] = "INY", + [60] = "TAX", + [61] = "RTS", + [62] = "RTL", + [63] = "CMP", + [64] = "CAB", + [65] = "SEI", + [66] = "LDX", + [67] = "TXA", + [68] = "RTI", + [69] = "LDA", + [70] = "DEX", + [71] = "CLV", + [72] = "TYX", + [73] = "STA", + [74] = "TSX", + [75] = "LDB", + [76] = "INX", + [77] = "WAI", + [78] = "TXY", + [79] = "STB", + [80] = "TXS", + [81] = "LDY", + [82] = "BRK", + [83] = "NOP", + [84] = "STY", + [85] = "DEB", + [86] = "ASR", + [87] = "ARB", + [88] = "STX", + [89] = "INB" +}; + +static const char *dir_t[5] = { + [0] = "org", + [1] = "byte", + [2] = "word", + [3] = "dword", + [4] = "qword" +}; + +int isalpha(int c) { + return ((unsigned)c|32)-'a' < 26; +} + +int isdigit(int c) { + return (unsigned)c-'0' < 10; +} + +int isxdigit(int c) { + return isdigit(c) || ((unsigned)c|32)-'a' < 6; +} + +int islower(int c) { + return (unsigned)c-'a' < 26; +} + +int isupper(int c) { + return (unsigned)c-'A' < 26; +} + +int toupper(int c) { + if (islower(c)) + return c & 0x5F; + return c; +} + +uint64_t tohex(char *str) { + uint8_t i = 0; + uint8_t digit; + uint64_t value = 0; + for (; str[i] != '\0';) { + if (isdigit(str[i])) { + digit = str[i] - '0'; + } else if (isupper(str[i])) { + digit = str[i] - ('A' - 10); + } else if (islower(str[i])) { + digit = str[i] - ('a' - 10); + } else { + break; + } + value = (value << 4) + digit; + ++i; + } + return value; +} + +uint64_t todec(char *str) { + uint8_t i = 0; + uint8_t digit; + uint64_t value = 0; + for (; str[i] != '\0';) { + if (isdigit(str[i])) { + digit = str[i] - '0'; + } else { + break; + } + + value = (value << 3) + (value << 1) + digit; + ++i; + } + return value; +} + +uint64_t tobin(char *str) { + uint8_t i = 0; + uint8_t digit; + uint64_t value = 0; + for (; str[i] != '\0';) { + if (isdigit(str[i])) { + digit = str[i] - '0'; + } else { + break; + } + value = (value << 1) + digit; + ++i; + } + return value; +} + +int str_cmp(const char *s0, const char *s1) { + for (; *s0 == *s1 && *s0; s0++, s1++); + return *s0-*s1; } -void tokenize(char *str) { +int str_casecmp(const char *s0, const char *s1) { + for (; *s0 && *s1 && (*s0 == *s1 || toupper(*s0) == toupper(*s1)); s0++, s1++); + return toupper(*s0) - toupper(*s1); +} + +uint8_t is_white(char ch) { + return (ch == ' ' || ch == '\t'); +} + + + +uint8_t lex(char *str) { uint16_t i = 0; - uint16_t skip = 0; + uint16_t j = 0; + lex_type = 0xFF; + uint8_t k = 0; + int line = 40; + int16_t ln = -1; + int y, x; + char lnum[6]; + uint8_t islinenum; + while (isdigit(str[i]) && !is_white(str[i])) { + lnum[j++] = str[i++]; + } + islinenum = i; + if (i) { + lnum[j] = '\0'; + ln = todec(lnum); + j = 0; + } else { + ln = linenum; + } + getyx(scr, y, x); uint8_t done = 0; - while (!done) { - if (!cmd_buf[i]) { - done = 1; - } else { - switch (cmd_buf[i]) { - case '.': - if (skip = str_cmp(cmd_buf, i+1, "org", 0) > 0) { - f = TOK_ORG; - i += skip; - } else if (skip = str_cmp(cmd_buf, i+1, "byte", 0) > 0) { - f = TOK_BYTE; - i+=skip; - } - break; + while (str[i] != '\0') { + if (is_white(str[i])) { + while (is_white(str[i])) { + i++; } } + switch (str[i]) { + case '.': + i++; + while (!is_white(str[i])) { + lexeme[j++] = str[i++]; + } + lexeme[j] = '\0'; + for (k = 0; k < 5; k++) { + if (!str_casecmp(lexeme, dir_t[k])) { + lex_type = TOK_DIR; + break; + } + } + i++; + tokline[ln].dir = k; + break; + case '\"': + i++; + while (str[i] != '\"') { + lexeme[j] = str[i]; + /*string[linenum][j] = str[i];*/ + j++, i++; + } + i++; + lexeme[j] = '\0'; + /*string[linenum][j] = '\0';*/ + lex_type = TOK_STRING; + break; + case '$': + i++; + while (isxdigit(str[i]) && str[i] != '\0') { + lexeme[j++] = str[i++]; + } + lexeme[j] = '\0'; + tokline[ln].op = tohex(lexeme); + tokline[ln].opbase = HEX; + lex_type = TOK_HEX; + break; + case '%': + i++; + while (isdigit(str[i]) && str[i] != '\0') { + lexeme[j++] = str[i++]; + } + lexeme[j] = '\0'; + tokline[ln].op = tobin(lexeme); + tokline[ln].opbase = BIN; + lex_type = TOK_BIN; + break; + case ';': + i++; + while (str[i] != '\0') { + lexeme[j++] = str[i++]; + /*comment[linenum][j] = str[i];*/ + /*j++, i++;*/ + } + lexeme[j] = '\0'; + /*comment[linenum][j] = '\0';*/ + lex_type = TOK_COMMENT; + break; + case '#': + lexeme[j] = '#'; + lexeme[j+1] = '\0'; + lexeme[j+2] = '\0'; + tokline[ln].am = IMM; + break; + case '(': + lexeme[j] = '('; + lexeme[j+1] = '\0'; + lexeme[j+2] = '\0'; + tokline[ln].am = IND; + break; + case ')': + i++; + if (str[i] == ',') { + i++; + while (is_white(str[i])) { + lexeme[j++] = str[i++]; + } + if (tokline[ln].am == IND && toupper(str[i]) == 'Y') { + lexeme[j++] = 'y'; + tokline[ln].am = INDY; + } + lexeme[j] = '\0'; + } else { + lexeme[j] = ')'; + lexeme[j+1] = '\0'; + lexeme[j+2] = '\0'; + } + break; + case ',': + i++; + while (is_white(str[i])) { + lexeme[j++] = str[i++]; + } + if (tokline[ln].am == IND && toupper(str[i]) == 'X') { + tokline[ln].am = INDX; + lexeme[j++] = 'x'; + i++; + } else { + switch (toupper(str[i])) { + case 'X': + tokline[ln].am = ZMX; + lexeme[j++] = 'x'; + break; + case 'Y': + tokline[ln].am = ZMY; + lexeme[j++] = 'y'; + break; + } + } + lexeme[j] = '\0'; + break; + default: + if (isalpha(str[i]) || isdigit(str[i])) { + while (!is_white(str[i]) && str[i] != '\0') { + lexeme[j++] = str[i++]; + } + for (k = 0; k < 90; k++) { + if (!str_casecmp(lexeme, mne_t[k])) { + lex_type = TOK_OPCODE; + tokline[ln].mne = k; + break; + } + } + for (k = 0; lexeme[k] != '\0';) { + if (isdigit(lexeme[k])) { + k++; + } else { + break; + } + } + if (lexeme[k] == '\0') { + tokline[ln].op = todec(lexeme); + tokline[ln].opbase = DEC; + lex_type = TOK_DEC; + } + + } + break; + } + wmove(scr, line++, 0); + wclrtoeol(scr); + wprintw(scr, "lexeme: %s, lex_type: %u\r", lexeme, lex_type); + j = 0, lex_type = 0xFF; + /*lex_type = 0xFF;*/ + if (str[i] != ')' && str[i] != ',') { + i++; + } + } + line++; + uint16_t ix = 0; + wmove(scr, line, 0); + wclrtoeol(scr); + wprintw(scr, "dir: %u" + ", mne: $%02X" + ", am: %u" + ", opbase: %u" + ", com: $%04X" + ", label: $%04X" + ", op: $%016X" + ", ln: %i\r" + , tokline[ln].dir + , tokline[ln].mne + , tokline[ln].am + , tokline[ln].opbase + , tokline[ln].com + , tokline[ln].label + , tokline[ln].op + , ln); + wmove(scr, y, x); + wrefresh(scr); + if (ln > linenum) { + linenum+=(10+(ln & 10)); + } else if (!islinenum) { + linenum += 10; + } + for (ix = 0; lexeme[ix] != '\0';) { + lexeme[ix] = 0; + ++ix; } + return i; } -void subasm() { +uint8_t subasm() { + uint16_t i; uint64_t address = 0; - tokenize(cmd_buf); + lex(cmd_buf); + /*if (dir != 0xFF) { + }*/ + return 0; } diff --git a/programs/c-ports/subeditor.c b/programs/c-ports/subeditor.c index 313c49a..76ee544 100644 --- a/programs/c-ports/subeditor.c +++ b/programs/c-ports/subeditor.c @@ -1,4 +1,3 @@ -#include #include "subeditor.h" #define clr_bitabl() {\ bitabl[0x00] = 0;\ @@ -45,6 +44,7 @@ uint8_t scr_col = 0; uint8_t scr_trow = 0; uint8_t scr_tcol = 0; uint16_t scr_ptr = 0; +uint16_t scr_ptr2 = 0; uint8_t byte = 0; uint8_t mask = 0; @@ -202,7 +202,7 @@ void bitpos(uint8_t row) { mask = bits[bit]; byte = bitmask >> 3; #if debug - mvwprintw(scr, 2, 0, "bit: $%02X, row: $%02X, byte: $%02X, mask: $%02X, bitmask: $%02X\r", bit, row, byte, mask, bitmask); + /*mvwprintw(scr, 2, 0, "bit: $%02X, row: $%02X, byte: $%02X, mask: $%02X, bitmask: $%02X\r", bit, row, byte, mask, bitmask);*/ #endif } @@ -240,11 +240,28 @@ void findst() { } } +void shftln(uint16_t src, uint16_t dst, uint8_t flag) { + if (!flag) { + while (buffer[src] != '\0') { + buffer[dst++] = buffer[src]; + buffer[src++] = '\0'; + } + } else { + while (scr_ptr <= src) { + mvwprintw(scr, 2, 0, "buffer[0x%04X]: $%02X, buffer[0x%04X]: $%02X, src: $%04X, dst: $%04X, scr_ptr: $%04X\r", src, buffer[src], dst, buffer[dst], src, dst, scr_ptr); + wrefresh(scr); + buffer[dst--] = buffer[src]; + buffer[src--] = '\0'; + } + } +} + void print_char(char ch) { uint8_t is_wrap = 0; uint8_t is_scroll = 0; uint8_t is_esc = 0; uint8_t done = 0; + uint16_t i = 0; a = ch; switch (ch) { case 0x1B: @@ -286,11 +303,9 @@ void print_char(char ch) { ++scr_row; if (getbit()) { scr_col = 0; - if (scr_row >= 23) { - if (scr_str) { - wrapped = 1; - scrl_down(); - } + if (scr_row > 23) { + wrapped = 1; + scrl_down(); is_wrap = 0; done = 1; } else { @@ -405,11 +420,18 @@ void print_char(char ch) { scr_col--; update_pos(); buffer[scr_ptr] = 0; + shftln(scr_ptr+1, scr_ptr, 0); #if !debug wdelch(scr); #endif break; default: + if (buffer[scr_ptr] != '\0') { + for (i = scr_ptr; buffer[i] != '\0'; i++); + scr_ptr2 = scr_ptr-1; + shftln(i-1, i, 1); + i = 0; + } a = ch; buffer[scr_ptr] = ch; scr_col++; @@ -557,7 +579,7 @@ int main() { continue; } if (!getkey(ch)) { - if (dabbed()) { + if (subasm()) { print_str(string2); print_str(cmd_buf); print_char('\n'); diff --git a/programs/c-ports/subeditor.h b/programs/c-ports/subeditor.h index ee5536e..ddb8947 100644 --- a/programs/c-ports/subeditor.h +++ b/programs/c-ports/subeditor.h @@ -2,10 +2,13 @@ #include #include #include +#include #define debug 0 #define debug_cmd_buf 0 +extern WINDOW *scr; + extern char *buffer; extern char *cmd_buf; @@ -33,5 +36,5 @@ extern uint8_t scr_end; extern uint8_t wrapped; extern void print_str(const char *str); -int16_t str_cmp(const char *s0, uint16_t i, const char *s1, uint16_t j); -extern void subasm(); +extern int str_cmp(const char *s0, const char *s1); +extern uint8_t subasm(); diff --git a/programs/subeditor.s b/programs/subeditor.s index 5769936..1001f83 100644 --- a/programs/subeditor.s +++ b/programs/subeditor.s @@ -46,6 +46,8 @@ scr_tcol: .byte $0 scr_ptr: .word $0 +scr_ptr2: + .word $0 ; Registers. a: .byte $0 @@ -151,6 +153,8 @@ start: tay jsl clr_cbuf ply #2 + ;lda #1 + ;sta $C010 lda.w #string jsl print_str lda.w zero @@ -204,6 +208,8 @@ print_str: sta.q ptr ldb #0 tba + inb + stb b pntstr_st: phy #2 txy @@ -215,6 +221,8 @@ pntstr_st: jmp pntstr_st pntstr_end: ply #2 + ldb #0 + stb b rtl @@ -278,6 +286,7 @@ getchar: lda $C002 ; Get typed character. ldb #0 stb e + stb b pha #1 phy #2 cmp #10 @@ -363,8 +372,72 @@ print_char: beq bs ; Did the user type a backspace? sta a printc: + lda (ptr5), y ; Are we at the end of the string? + beq printc_save ; Yes, so just print the character. + lda b ; No, but was the flag set? + bne printc_save ; Yes, so don't shift the line. + sty.w scr_ptr ; No, so save the cursor index for later. +prntc_fndnd: + lda (ptr5), y ; Are we at the end of the string? + beq prntc_movln ; Yes, so make room for the next character. + iny ; No, so increment the cursor index. + jmp prntc_fndnd ; Keep looping. +printc_updt: + jmp prntc_updt2 +prntc_updt1: + pla #1 + clc + adc scr_row + sta scr_row + jsl update_pos +prntc_updt2: + lda scr_row + pha #1 + lda scr_col + pha #1 + jsl rdrw_row + pla #1 + sta scr_col + pla #1 + sta scr_row + jsl update_pos +prntc_updt3: + ldb scr_row + lda scr_trow + sec + sab + pha #1 + tab + sec + sab + clc + sta scr_row +prntc_updt4: + jsl getbit + bcs prntc_updt1 + pla #1 + lda scr_trow + sta scr_row + jsl update_pos + dec d + jmp printc_sav1 +prntc_movln: + tyx + dey + ldb #1 + stb d + jsl shftln + ldb #1 + stb d + lda scr_row + sta scr_trow +printc_save: + ldb d + bne printc_updt +printc_sav1: lda a sta (ptr5), y ; Store typed character into the input buffer. +printc_inc: inc scr_col ; Increment the cursor's x coordinate. iny printc_2: @@ -414,7 +487,10 @@ printc_end: nl: lda #0 + ldb (ptr5), y + bne nl1 sta (ptr5), y ; Store said terminator into the input buffer. +nl1: sta scr_col lda scr_row cmp #23 @@ -468,11 +544,16 @@ stp_end: jmp printc_end back: - lda #$7F ; Print a backspace to the screen. - sta $C001 ; dey ; Decrement the buffer's offset. lda #0 ; Place a null terminator sta (ptr5), y ; into the buffer. + tyx ; Copy the current cursor index to X. + iny ; Increment cursor index. + ldb #0 + stb d + jsl shftln ; Move/Shift line back by one character. + lda #$7F ; Print a backspace to the screen. + sta $C001 ; dec scr_col ; Move the cursor back by one column, jsl update_pos ; and update it's position. jmp printc_end ; We are done. @@ -510,6 +591,49 @@ backwrp2: jsl update_pos ; Update the cursor's position. jmp back ; Delete the previous character. +shftln: + ldb d ; Is the flag set? + beq shftln_lp1 ; Yes, so shift, and increment. + jmp shftln_lp0 ; No, so shift, and decrement. +shftln_neg: + ldy.w zero ; Set the source poition to 0. + lda #0 ; Clear the character + sta (ptr5), y ; that is in the source. + jmp shftln_end ; We are done. +shftln_lp0: + sty.w scr_ptr2 ; Save the source position for later. + ldy.w scr_ptr ; Get the previous cursor index. + cpy.w scr_ptr2 ; Is the source position, at, or below the cursor index? + beq shftln_lp01 ; Yes, so keep looping. + bcs shftln_end ; No, so we're done. +shftln_lp01: + ldy.w scr_ptr2 ; Get the source position. + lda (ptr5), y ; Get the character from the source position. + phy #2 ; Save the source position for later. + txy ; Set our position to the destination. + sta (ptr5), y ; Place the character from the source position, to the destination position. + ply #2 ; Set our position back to the source. + lda #0 ; Clear the character + sta (ptr5), y ; that is in the source. + dey ; Decrement the source position. + bng shftln_neg ; The source underflowed, so set it back to zero, + dex ; Decrement the destination position. + jmp shftln_lp0 ; Keep looping. +shftln_lp1: + lda (ptr5), y ; Is the character at the source position, a null terminator? + beq shftln_end ; Yes, so we're done. + phy #2 ; No, so save the source position for later. + txy ; Set our position to the destination. + sta (ptr5), y ; Place the character from the source position, to the destination position. + inx ; Increment the destination position. + ply #2 ; Set our position back to the source. + lda #0 ; Clear the character + sta (ptr5), y ; that is in the source. + iny ; Increment the source position. + jmp shftln_lp1 ; Keep looping. +shftln_end: + rtl ; We are done. + esc: lda $C000 ; Get the next character. lda $C002 ; @@ -611,8 +735,8 @@ isright_wrp: dec scr_row ; No, so move the cursor back up a row. jmp isright_dne ; We are done. isright_scr: - lda scr_str ; Are we at the top of the screen buffer? - beq isright_end ; Yes, so we're done. +; lda scr_str ; Are we at the top of the screen buffer? +; beq isright_end ; Yes, so we're done. lda #1 ; No, so scroll down. sta wrapped ; Set the wrapped flag. jsl scrl_down ; Scroll down. @@ -622,6 +746,7 @@ wrap_inc: sta scr_col ; lda scr_row ; Get the current row number. cmp #23 ; Are we at the bottom of the screen? + beq isright_nd2 ; No, so we're done. bcs isright_scr ; Yes, so check if we are scrolling down. jmp isright_nd2 ; We are done. isright_end: @@ -741,8 +866,13 @@ update_pos: clc lda scr_row adc scr_str + tay clc - mul #80 + lsl #6 + tab + tya + lsl #4 + aab clc adc scr_col tay @@ -781,7 +911,6 @@ getcol: rtl ; End of getrow. scrl_down: - inc scr_str inc scr_end lda #$1B ; Print an escape character @@ -851,14 +980,16 @@ rdrow_inc: inc scr_col lda (ptr5), y beq rdrow_skip - iny rdrow_inc1: + iny +rdrow_inc2: lda scr_col cmp #80 bcs rdrow_end jmp rdrow_st rdrow_skip: - jsl update_pos + lda #$20 + sta $C001 ; to the screen. jmp rdrow_inc1 rdrow_end: lda #0 @@ -867,26 +998,32 @@ rdrow_end: rdrow_done: rtl - ;rdrw_scr: -; lda #$C -; sta $C001 -; lda scr_col -; sta scr_tcol ; lda scr_row -; sta scr_trow +; sta e ; lda #0 -; sta scr_col ; sta scr_row -; phy #2 +; lda scr_col +; sta f +; jsl update_pos +;rdscr_st: +; jsl rdrw_row +; lda scr_row +; cmp #23 +; beq rdscr_inc +; bcs rdscr_done +;rdscr_inc: +; inc scr_row +; jmp rdscr_st +;rdscr_done: +; lda e +; sta scr_row +; lda f +; sta scr_col ; jsl update_pos -; ply #2 -; ldx scr_ptr -; phy #2 -; txy -; lda (ptr), y -; sta $C001 -; ply #2 +; lda #0 +; sta e +; sta f ; rtl result: @@ -945,14 +1082,6 @@ cmd_clr: .org $FFC0 .qword reset -.org $FF50 -.qword spin -.qword spin -.qword spin -.qword spin -.qword spin -.qword spin -.qword spin r ;.org $8000 ;v -- cgit v1.2.3-13-gbd6f