aboutsummaryrefslogtreecommitdiff
path: root/oldcurses.c
blob: c8702d55c8ccd77546e91c24c5e49f8cbea3570e (plain)
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
154
155
156
157
158
159
160
161
/* curses wrappers.
	The original code uses curses, cc65 uses conio, so I wrote this stuff
	to map the curses calls to conio ones.
	Later on, just replaced all the curses stuff (except clrtobot() and
	clrtoeol()) with direct calls to conio.
	Keeping this around in case it's useful for porting some other
	curses app to cc65. */

/* original plan was to use time() or _systime(). It turns out that
	these are not implemented on the Atari, and always return -1.
	So, use the OS's countdown timer instead.
	Anyone porting to another cc65 platform needs to rewrite this.

	TODO: rewrite in terms of clock() and CLOCKS_PER_SEC. Will make it
	less atari-specific, plus auto-adjust for pal/ntsc.

	TODO: there is atari-specific stuff elsewhere in the code :(
 */

static unsigned int tmout_jiffies = 0;

/*
void timeout(unsigned int msec) {
	if(msec > 0)
		tmout_jiffies = (msec / 100) * 6; // TODO: should be 5 for PAL
	else
		tmout_jiffies = 0;
}
*/

/* set timer with interrupts disabled, to avoid race condition
   where an interrupt happens between setting the high & low bytes. */
void start_timer() {
	__asm__("SEI");
	POKE(541, tmout_jiffies / 256);
	POKE(540, tmout_jiffies % 256);
	__asm__("CLI");
}

/* this getch() works like curses, except it always acts
	like it's in cbreak mode. */
int getch() {
	int ret = -1;

	if(tmout_jiffies == 0) return cgetc();

	start_timer();

	do {
		if(kbhit()) {
			ret = cgetc();
			break;
		}
	} while (timer_running());

	return ret;
}

#define timer_running() (PEEK(541) || PEEK(540))
#define timer_expired() (!timer_running())

int flushinp() {
	POKE(764, 255);
	return 0;
}

void clrtobot() {
	unsigned char rows, cols, y, oldx, oldy;
	oldx = wherex();
	oldy = wherey();
	screensize(&cols, &rows);
	cclear(cols - wherex()); /* leaves cursor at start of next line */
	for(y = wherey(); y < rows; y++)
		cclearxy(0, y, cols);
	gotoxy(oldx, oldy);
}

/* TODO: rewrite in asm */
void clrtobot() {
	unsigned char rows, cols, y, oldx, oldy;
	oldx = wherex();
	oldy = wherey();
	screensize(&cols, &rows);
	cclear(cols - wherex()); /* leaves cursor at start of next line */
	for(y = wherey(); y < rows; y++)
		cclearxy(0, y, cols);
	gotoxy(oldx, oldy);
}

/* TODO: rewrite in asm */
void clrtoeol() {
	unsigned char cols, rows, oldx, oldy;
	oldx = wherex();
	oldy = wherey();
	screensize(&cols, &rows);
	cclear(cols - wherex());
	gotoxy(oldx, oldy);
}


/* one-to-one mapping between some of the conio API and the curses one */
#define clear() clrscr()
#define printw cprintf
#define curs_set(x) cursor(x)

/* conio doesn't do deferred printing, refresh() is a no-op */
#define refresh()

/* we don't support cooked or raw mode, cbreak() is a no-op */
#define cbreak()

/* we don't support echo mode */
#define noecho()

/* curses move() takes args in the opposite order to gotoxy() */
#define move(a, b) gotoxy(b, a)

/* our attrset() only supports A_NORMAL and A_REVERSE, since
	the Atari can only print normal and reverse video. */
#define A_NORMAL 0
#define A_REVERSE 1
#define attrset(x) revers(x)

/**** atari-specific stuff */

/* original plan was to use time() or _systime(). It turns out that
	these are not implemented on the Atari, and always return -1.
	So, use the OS's countdown timer instead.
	Anyone porting to another cc65 platform needs to rewrite this.

	TODO: rewrite in terms of clock() and CLOCKS_PER_SEC. Will make it
	less atari-specific, plus auto-adjust for pal/ntsc.

	TODO: there is atari-specific stuff elsewhere in the code :(
 */

static unsigned int tmout_jiffies = 0;

void timeout(unsigned int msec) {
	if(msec > 0)
		tmout_jiffies = (msec / 100) * 6; // TODO: should be 5 for PAL
	else
		tmout_jiffies = 0;
}

/* set timer with interrupts disabled, to avoid race condition
   where an interrupt happens between setting the high & low bytes. */
void start_timer() {
	__asm__("SEI");
	POKE(541, tmout_jiffies / 256);
	POKE(540, tmout_jiffies % 256);
	__asm__("CLI");
}

#define timer_running() (PEEK(541) || PEEK(540))
#define timer_expired() (!timer_running())

int flushinp() {
	POKE(764, 255);
	return 0;
}