// 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 r; if (c == 0x08) // If c is backspace return 0xDF; if (c < 0x20) { if (c != 0x0D // CR && c != 0x1B) // Exit return -1; } //switch(c) //{ // Convert special characters /*case KEY_F(1): //backspace r = 0xDF; break; case KEY_F(2): //enter r = 0x8D; break; case KEY_F(3): //exit, for escape. TODO: Figure out if this is Esc or not. r = 0x9B; break;*/ // Convert regular characters /*default: if (c < 0x20 || c >= 0x60) return -1; if (c >= 0x40) r = c - 0x40; else r = c; break; }*/ return c; } #define FlagVisual(x, c) (getFlag(x)) ? c : '.' void PrintInfo() { mvprintw(2, 43, " acc : %02x", acc); mvprintw(3, 43, " X : %02x", X ); mvprintw(4, 43, " Y : %02x", Y ); mvprintw(5, 43, " PC : %04x", PC); mvprintw(6, 43, " S : %02x", S ); mvprintw(7, 43, "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':'.' ); mvprintw(2, 65, "Stack"); int count = 3; for (int i = 0x1ff; i > 0x1e8; i--) { if (i == (0x1ff-S)) // Indicate the stack pointer! attron(A_REVERSE); mvprintw(count, 65, "%x : %x", i, GetMemory(i)); attroff(A_REVERSE); count++; } 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); }