-
Notifications
You must be signed in to change notification settings - Fork 27
/
io.c
153 lines (130 loc) · 3.92 KB
/
io.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include "io.h"
#include <ncurses.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
#include <sys/time.h>
#include "functions.h"
#define VTERM_ROWS 25
#define VTERM_COLS 40
uint8_t io_modeflags = 0x00;
uint8_t io_supports_paint;
FILE *blck0 = NULL;
WINDOW *window = NULL;
void init_vterm();
void update_vterm(cpu *, uint16_t);
void finish_vterm();
void set_block_source(FILE *source) {
blck0 = source;
}
void init_io() {
initscr();
cbreak();
noecho();
nodelay(stdscr, TRUE);
keypad(stdscr, TRUE);
curs_set(0);
io_supports_paint = (has_colors() != FALSE);
if (io_supports_paint) {
start_color();
for (int i = 0; i < 8; i++) {
init_pair(i, i, COLOR_BLACK);
}
}
}
void finish_io() {
if (io_modeflags & IO_MODEFLAG_WAIT_HALT) {
nodelay(stdscr, FALSE);
printw("\nterminated, press any key to exit.\n");
getch();
}
endwin();
}
void init_vterm() {
window = newwin(VTERM_ROWS + 2, VTERM_COLS + 2, 0, 0);
box(window, 0, 0);
wrefresh(window);
}
void finish_vterm() {
endwin();
}
void update_modeflags(uint8_t old_flags, uint8_t new_flags) {
io_modeflags = new_flags;
// if the vterm flag changed (avoids reinit every time flags change)
if ((new_flags ^ old_flags) & IO_MODEFLAG_VTERM) {
if (new_flags & IO_MODEFLAG_VTERM) {
init_vterm();
} else {
finish_vterm();
}
}
}
void update_paint(uint8_t paint) {
wattrset(window,
COLOR_PAIR(paint & 0x0F) |
(paint & IO_PAINT_DIM ? A_DIM : 0) |
(paint & IO_PAINT_UNDERLINE ? A_UNDERLINE : 0) |
(paint & IO_PAINT_BOLD ? A_BOLD : 0));
}
void update_vterm(cpu *m, uint16_t dirty) {
uint16_t offset = dirty - IO_VTERM_START;
if (offset >= 1000) {
// this is in the unused 24 bytes at the end of the page, ignore it
return;
}
// 1 offsets to avoid overwriting the border
uint8_t r = offset / VTERM_COLS + 1;
uint8_t c = offset % VTERM_COLS + 1;
mvwprintw(window, r, c, "%c", m->mem[dirty]);
wrefresh(window);
}
void handle_io(cpu *m) {
int read;
if ((read = getch()) != ERR) {
m->interrupt_waiting = 0x01;
m->mem[IO_GETCHAR] = read;
}
if (get_emu_flag(m, EMU_FLAG_DIRTY)) {
uint16_t addr = m->dirty_mem_addr;
debugf("dirty address %04X has value %02x\n", addr, m->mem[addr]);
if (addr == IO_PUTCHAR) {
if (io_modeflags & IO_MODEFLAG_VTERM) {
wprintw(window, "%c", m->mem[addr]);
wrefresh(window);
} else {
addch(m->mem[addr]);
}
} else if (addr == IO_MODEFLAGS) {
update_modeflags(io_modeflags, m->mem[IO_MODEFLAGS]);
} else if (addr == IO_PAINT) {
update_paint(m->mem[addr]);
} else if (IO_VTERM_START <= addr && addr < IO_VTERM_END) {
update_vterm(m, addr);
} else if (addr == IO_BLCK0_ADDRL
|| addr == IO_BLCK0_ADDRH
|| addr == IO_BLCK0_READ) {
if (blck0 == NULL) {
finish_vterm();
fprintf(stderr, "tried to read from unattached block device\n");
exit(-1);
return;
}
uint16_t read_addr =
m->mem[IO_BLCK0_ADDRH] << 8 | m->mem[IO_BLCK0_ADDRL];
int res = fseek(blck0, read_addr, SEEK_SET);
if (res) {
debugf("ERROR: fseek returned %d\n", res);
m->mem[IO_BLCK0_ERR] = IO_BLCK_ERR_SEEK;
return;
}
res = fgetc(blck0);
if (res == EOF) {
debugf("ERROR: fgetc returned EOF\n");
m->mem[IO_BLCK0_ERR] = IO_BLCK_ERR_EOF;
return;
}
m->mem[IO_BLCK0_READ] = 0xFF & res;
m->mem[IO_BLCK0_ERR] = 0x00;
}
}
}