// ncurses.c // Implements interface.h // Provides an in-terminal interface to the emulator. #include #include"interface.h" #include"signetics.c" #include"../apple.h" int TermX = 0; int TermY = 0; WINDOW *AppleWindow; byte UserInput() { int c = getch(); switch(c) { // Convert special characters case KEY_BACKSPACE: return 0xDF; case KEY_ENTER: return 0x8D; case KEY_EXIT: //TODO: Figure out if this is Esc or not. return 0x9B; // Convert regular characters default: if (c < 0x20 || c >= 0x60) return -1; if (c >= 0x40) c -= 0x40; break; } return c; } 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) { // Handle special characters and conversion. switch (n) { case 0xDF: // Backslash case 0x8D: // Enter case 0x9B: // Escape return; default: // Convert to ASCII if (n < 0x20) n += 0x40; } // Place character mvwaddch(AppleWindow, TermY, TermX, ' '); mvwaddch(AppleWindow, TermY, TermX, 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, (*offset < 0x20) ? *offset + 0x40 : *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); }