// ncurses.c // Implements interface.h // Provides an in-terminal interface to the emulator. #include #include"interface.h" #include"signetics.c" #include"../apple.h" #include"../cpu/6502.h" int TermX = 0; int TermY = 0; WINDOW *AppleWindow; byte UserInput() { int c = getch(); byte C; switch(c) { // Convert special characters case KEY_BACKSPACE: C = 0xDF; case KEY_ENTER: C = 0x8D; case KEY_EXIT: //TODO: Figure out if this is Esc or not. C = 0x9B; // Convert regular characters default: if (c < 0x20 || c >= 0x60) return -1; if (c >= 0x40) C = c - 0x40; else C = c; break; } SetMemory(KBD, C); TerminalInput(c); return c; } #define FlagVisual(x, c) (getFlag(x)) ? c : '.' void PrintInfo() { move(2, 43); printf("acc : %x", acc); move(3, 43); printf(" X : %x", X ); move(4, 43); printf(" Y : %x", Y ); move(5, 43); printf(" PC : %x", PC); move(6, 43); printf("Flags : %c%c_%c%c%c%c%c", getFlag(flag_N) ? 'N':'.' , getFlag(flag_V) ? 'V':'.' , getFlag(flag_B) ? 'B':'.' , getFlag(flag_D) ? 'D':'.' , getFlag(flag_I) ? 'I':'.' , getFlag(flag_Z) ? 'Z':'.' , getFlag(flag_C) ? 'C':'.' ); refresh(); } void TerminalInit() { // ncurses initialization functions. initscr(); cbreak(); noecho(); curs_set(0); keypad(stdscr, TRUE); // Draw decorative border. attron(A_REVERSE); move(0, 0); printw(" "); for (int i = 1; i <= 24; i++) { mvaddch(i, 0, ' '); mvaddch(i, 41, ' '); } mvprintw(25, 0, " ~ "); mvprintw(26, 0, " Alekseis Apple I "); mvprintw(27, 0, " "); attroff(A_REVERSE); // Create seperate Apple screen window. AppleWindow = newwin(24, 40, 1, 1); // @ prompt. mvwaddch(AppleWindow, TermY, TermX, '@' | A_BLINK); // Initialize the terminal shift register variables. TerminalShiftRegister = (byte*)malloc(960); TerminalShiftRegisterPosition = TerminalShiftRegister; TerminalShiftRegisterOffset = 0; refresh(); } void TerminalClose() { free(TerminalShiftRegister); curs_set(1); endwin(); } void TerminalInput(byte n) { // Place character mvwaddch(AppleWindow, TermY, TermX, ' '); mvwaddch(AppleWindow, TermY, TermX, CharacterROM[n]); // Add character to register *TerminalShiftRegisterPosition = n; TerminalShiftRegisterPosition++; if (TerminalShiftRegisterPosition >= (TerminalShiftRegister + 960)) TerminalShiftRegisterPosition = TerminalShiftRegister; TermX++; // If X is past width.. if (TermX >= 40) { //.. move to start of next line. TermX = 0; TermY++; } // If Y is past height.. if (TermY >= 24) { //.. discard the first line.. TerminalShiftRegisterOffset += 40; //.. verify the register offset.. if (TerminalShiftRegisterOffset >= 960) TerminalShiftRegisterOffset = TerminalShiftRegister; //.. and create an offset variable to cycle through memory with. byte *offset = TerminalShiftRegister + TerminalShiftRegisterOffset; // Then, for every cell of the screen, fill with the contents of the video memory. for (int i = 0; i < 23; i++) { for (int j = 0; j < 40; j++) { if (offset >= (TerminalShiftRegister + 960)) offset -= TerminalShiftRegister; mvwaddch(AppleWindow, i, j, CharacterROM[*offset] ); offset++; }} // Set to start of final line, and clear line. TermY = 23; TermX = 0; mvwprintw(AppleWindow, TermY, TermX, " "); } // @ prompt. mvwaddch(AppleWindow, TermY, TermX, '@' | A_BLINK); wrefresh(AppleWindow); }