-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathP98.C
153 lines (125 loc) · 3.65 KB
/
P98.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 <stdio.h>
#include <limits.h>
#include <dos.h>
#include <sys/farptr.h>
#include <sys/movedata.h>
#include <go32.h>
#include <dpmi.h>
#include "P98.H"
#include "PEGC.H"
#include "BUZZER.H"
#define RETURN_OK (1)
#define RETURN_ERR (0)
__dpmi_meminfo pegc_dpmi;
int pegc_sel = -1;
int init_get_fb_location() {
int status = inportb(MEMHOLE_STAT_ADDR);
if (status & 0x04){
printf("No hole... VRAM FB @ 0x%x\n", PEGC_FB_LOCATION_HIGH);
return PEGC_FB_LOCATION_HIGH;
} else {
printf("Hole! VRAM FB @ 0x%x\n", PEGC_FB_LOCATION_LOW);
return PEGC_FB_LOCATION_LOW;
}
}
int init_pegc_dpmi(int fb_location) {
if (!__djgpp_nearptr_enable()) {
printf("DPMI: failed to enable nearptrs");
return RETURN_ERR;
}
pegc_dpmi.address = fb_location;
pegc_dpmi.size = PEGC_FB_SIZE;
if (__dpmi_physical_address_mapping(&pegc_dpmi)) {
printf("DPMI: couldn't map PEGC\n");
return RETURN_ERR;
}
pegc_sel = __dpmi_allocate_ldt_descriptors(1);
if (pegc_sel < 0){
printf("DPMI: can't allocate PEGC descriptor\n");
__dpmi_free_physical_address_mapping(&pegc_dpmi);
return RETURN_ERR;
}
__dpmi_set_segment_base_address(pegc_sel, pegc_dpmi.address);
__dpmi_set_segment_limit(pegc_sel, pegc_dpmi.size - 1);
printf("DPMI: mapped PEGC FB!\n");
return RETURN_OK;
}
inline void pegc_push(unsigned char* buffer) {
movedata(_my_ds(), buffer, pegc_sel, 0, PEGC_SIZE);
}
inline void pegc_vsync() {
while ((inportb(PEGC_STAT_ADDR) & PEGC_STAT_VSYNC) == 0);
}
void pegc_gfx_on() {
outportb(PEGC_CMD_ADDR, PEGC_CMD_START);
}
void pegc_gfx_off() {
outportb(PEGC_CMD_ADDR, PEGC_CMD_STOP1);
}
void pegc_text_on() {
outportb(PEGC_TEXT_CMD_ADDR, PEGC_CMD_START);
}
void pegc_text_off() {
outportb(PEGC_TEXT_CMD_ADDR, PEGC_CMD_STOP1);
}
inline void pegc_col_set_sep(unsigned char idx, unsigned char r, unsigned char g, unsigned char b) {
outportb(PEGC_PAL_SEL_ADDR, idx);
outportb(PEGC_PAL_R_ADDR, r);
outportb(PEGC_PAL_G_ADDR, g);
outportb(PEGC_PAL_B_ADDR, b);
}
inline void pegc_col_set(unsigned char idx, unsigned int col) {
outportb(PEGC_PAL_SEL_ADDR, idx);
outportb(PEGC_PAL_R_ADDR, (col >> 16));
outportb(PEGC_PAL_G_ADDR, (col >> 8));
outportb(PEGC_PAL_B_ADDR, col);
}
void pegc_pal_set(const unsigned int* pal, unsigned char size) {
int i;
for (i = 0; i < size; i++)
pegc_col_set(i, pal[i]);
}
void pegc_setmode() {
outportb(PEGC_SCANFREQ_ADDR, PEGC_SCANFREQ_31);
outportb(PEGC_DEPTH_ADDR, PEGC_DEPTH_UNLOCK);
outportb(PEGC_DEPTH_ADDR, PEGC_DEPTH_8);
outportb(PEGC_DEPTH_ADDR, PEGC_DEPTH_PAGES_1);
outportb(PEGC_DEPTH_ADDR, PEGC_DEPTH_LOCK);
_farpokeb(_dos_ds, PEGC_FORMAT_ADDR, PEGC_FORMAT_LINEAR);
}
int pegc_start(int retain_text) {
pegc_setmode();
// setup dpmi mapping
if (!init_pegc_dpmi(init_get_fb_location())) {
pegc_stop();
return RETURN_ERR;
}
if (!retain_text)
pegc_text_off();
// enable framebuffer, select+write page 0, go.
_farpokeb(_dos_ds, PEGC_FB_CTRL_ADDR, PEGC_FB_ON);
outportb(PEGC_DRAW_PAGE_SEL_ADDR, PEGC_PAGE0);
outportb(PEGC_DISP_PAGE_SEL_ADDR, PEGC_PAGE0);
pegc_gfx_on();
return RETURN_OK;
}
void pegc_stop() {
_farpokeb(_dos_ds, PEGC_FB_CTRL_ADDR, PEGC_FB_OFF);
// return to 16 color mode, disable graphics
outportb(PEGC_DEPTH_ADDR, PEGC_DEPTH_UNLOCK);
outportb(PEGC_DEPTH_ADDR, PEGC_DEPTH_4);
outportb(PEGC_DEPTH_ADDR, PEGC_DEPTH_LOCK);
pegc_gfx_off();
// remove mapping
__dpmi_free_physical_address_mapping(&pegc_dpmi);
pegc_text_on();
}
inline void buz_on(unsigned char tone) {
unsigned char buz_status = inportb(BUZ_ADDR);
outportb(BUZ_ADDR, buz_status & BUZ_BIT_ON);
outportb(BUZ_TONE_ADDR, tone);
}
inline void buz_off() {
unsigned char buz_status = inportb(BUZ_ADDR);
outportb(BUZ_ADDR, buz_status | BUZ_BIT_OFF);
}