rev |
line source |
nuclear@0
|
1 /*
|
nuclear@0
|
2 256-color 3D graphics hack for real-mode DOS.
|
nuclear@0
|
3 Copyright (C) 2011 John Tsiombikas <nuclear@member.fsf.org>
|
nuclear@0
|
4
|
nuclear@0
|
5 This program is free software: you can redistribute it and/or modify
|
nuclear@0
|
6 it under the terms of the GNU General Public License as published by
|
nuclear@0
|
7 the Free Software Foundation, either version 3 of the License, or
|
nuclear@0
|
8 (at your option) any later version.
|
nuclear@0
|
9
|
nuclear@0
|
10 This program is distributed in the hope that it will be useful,
|
nuclear@0
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
nuclear@0
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
nuclear@0
|
13 GNU General Public License for more details.
|
nuclear@0
|
14
|
nuclear@0
|
15 You should have received a copy of the GNU General Public License
|
nuclear@0
|
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
nuclear@0
|
17 */
|
nuclear@0
|
18
|
nuclear@0
|
19 /* This file implements all calls made to dos-specific code using SDL
|
nuclear@0
|
20 * Don't ask why ...
|
nuclear@0
|
21 */
|
nuclear@0
|
22
|
nuclear@0
|
23 #include <stdlib.h>
|
nuclear@0
|
24 #include <assert.h>
|
nuclear@0
|
25 #include <SDL.h>
|
nuclear@0
|
26 #include "vga.h"
|
nuclear@0
|
27 #include "conio.h"
|
nuclear@0
|
28 #include "mouse.h"
|
nuclear@0
|
29 #include "timer.h"
|
nuclear@0
|
30
|
nuclear@0
|
31 static void proc_events(void);
|
nuclear@0
|
32
|
nuclear@0
|
33 /* ----- graphics (vga.c implementation) ----- */
|
nuclear@0
|
34 static SDL_Surface *fbsurf;
|
nuclear@0
|
35
|
nuclear@0
|
36 #define DOUBLESZ (fbsurf->w != 320)
|
nuclear@0
|
37
|
nuclear@0
|
38 void set_video_mode(int mode)
|
nuclear@0
|
39 {
|
nuclear@0
|
40 int resx = 320, resy = 200;
|
nuclear@0
|
41
|
nuclear@0
|
42 if(getenv("DOSEMU_DOUBLESIZE")) {
|
nuclear@0
|
43 resx *= 2;
|
nuclear@0
|
44 resy *= 2;
|
nuclear@0
|
45 }
|
nuclear@0
|
46
|
nuclear@0
|
47 switch(mode) {
|
nuclear@0
|
48 case 0x13:
|
nuclear@0
|
49 SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
|
nuclear@0
|
50 if(!(fbsurf = SDL_SetVideoMode(resx, resy, 8, SDL_HWPALETTE))) {
|
nuclear@0
|
51 fprintf(stderr, "failed to set video mode\n");
|
nuclear@0
|
52 abort();
|
nuclear@0
|
53 }
|
nuclear@0
|
54 SDL_ShowCursor(0);
|
nuclear@0
|
55 break;
|
nuclear@0
|
56
|
nuclear@0
|
57 case 3:
|
nuclear@0
|
58 SDL_ShowCursor(1);
|
nuclear@0
|
59 SDL_Quit();
|
nuclear@0
|
60 break;
|
nuclear@0
|
61
|
nuclear@0
|
62 default:
|
nuclear@0
|
63 break;
|
nuclear@0
|
64 }
|
nuclear@0
|
65 }
|
nuclear@0
|
66
|
nuclear@0
|
67 void set_palette(unsigned char c, unsigned char r, unsigned char g, unsigned char b)
|
nuclear@0
|
68 {
|
nuclear@0
|
69 SDL_Color col;
|
nuclear@0
|
70 col.r = r;
|
nuclear@0
|
71 col.g = g;
|
nuclear@0
|
72 col.b = b;
|
nuclear@0
|
73
|
nuclear@0
|
74 if(SDL_SetPalette(fbsurf, SDL_LOGPAL | SDL_PHYSPAL, &col, c, 1) != 1) {
|
nuclear@0
|
75 fprintf(stderr, "set_palette failed to set the required color\n");
|
nuclear@0
|
76 }
|
nuclear@0
|
77 }
|
nuclear@0
|
78
|
nuclear@0
|
79 void copy_frame(unsigned char *frame)
|
nuclear@0
|
80 {
|
nuclear@0
|
81 if(SDL_MUSTLOCK(fbsurf)) {
|
nuclear@0
|
82 SDL_LockSurface(fbsurf);
|
nuclear@0
|
83 }
|
nuclear@0
|
84
|
nuclear@0
|
85 if(DOUBLESZ) {
|
nuclear@0
|
86 int i, j;
|
nuclear@0
|
87 Uint16 *dest = fbsurf->pixels;
|
nuclear@0
|
88
|
nuclear@0
|
89 for(i=0; i<200; i++) {
|
nuclear@0
|
90 for(j=0; j<320; j++) {
|
nuclear@0
|
91 Uint16 twopix = ((Uint16)*frame << 8) | (Uint16)*frame;
|
nuclear@0
|
92 dest[j] = dest[j + 320] = twopix;
|
nuclear@0
|
93 frame++;
|
nuclear@0
|
94 }
|
nuclear@0
|
95 dest += fbsurf->pitch;
|
nuclear@0
|
96 }
|
nuclear@0
|
97 } else {
|
nuclear@0
|
98 memcpy(fbsurf->pixels, frame, 64000);
|
nuclear@0
|
99 }
|
nuclear@0
|
100
|
nuclear@0
|
101 if(SDL_MUSTLOCK(fbsurf)) {
|
nuclear@0
|
102 SDL_UnlockSurface(fbsurf);
|
nuclear@0
|
103 }
|
nuclear@0
|
104 SDL_Flip(fbsurf);
|
nuclear@0
|
105 }
|
nuclear@0
|
106
|
nuclear@0
|
107 void wait_vsync(void)
|
nuclear@0
|
108 {
|
nuclear@0
|
109 }
|
nuclear@0
|
110
|
nuclear@0
|
111 /* ----- event handling (conio.h) ----- */
|
nuclear@0
|
112 static SDL_Event *keybev;
|
nuclear@0
|
113 static int mousex, mousey, bnmask;
|
nuclear@0
|
114
|
nuclear@0
|
115 int kbhit(void)
|
nuclear@0
|
116 {
|
nuclear@0
|
117 if(!keybev) {
|
nuclear@0
|
118 proc_events();
|
nuclear@0
|
119 }
|
nuclear@0
|
120 return keybev != 0;
|
nuclear@0
|
121 }
|
nuclear@0
|
122
|
nuclear@0
|
123 char getch(void)
|
nuclear@0
|
124 {
|
nuclear@0
|
125 char res;
|
nuclear@0
|
126
|
nuclear@0
|
127 while(!keybev) {
|
nuclear@0
|
128 SDL_Event ev;
|
nuclear@0
|
129 SDL_WaitEvent(&ev);
|
nuclear@0
|
130 SDL_PushEvent(&ev);
|
nuclear@0
|
131 proc_events();
|
nuclear@0
|
132 }
|
nuclear@0
|
133 res = keybev->key.keysym.sym;
|
nuclear@0
|
134 keybev = 0;
|
nuclear@0
|
135 return res;
|
nuclear@0
|
136 }
|
nuclear@0
|
137
|
nuclear@0
|
138 /* mouse handling (mouse.c implementation) */
|
nuclear@0
|
139 int have_mouse(void)
|
nuclear@0
|
140 {
|
nuclear@0
|
141 return 1;
|
nuclear@0
|
142 }
|
nuclear@0
|
143
|
nuclear@0
|
144 int read_mouse(int *xp, int *yp)
|
nuclear@0
|
145 {
|
nuclear@0
|
146 if(xp) *xp = mousex;
|
nuclear@0
|
147 if(yp) *yp = mousey;
|
nuclear@0
|
148 return bnmask;
|
nuclear@0
|
149 }
|
nuclear@0
|
150
|
nuclear@0
|
151 static void proc_events(void)
|
nuclear@0
|
152 {
|
nuclear@0
|
153 static SDL_Event ev;
|
nuclear@0
|
154
|
nuclear@0
|
155 while(SDL_PollEvent(&ev)) {
|
nuclear@0
|
156 switch(ev.type) {
|
nuclear@0
|
157 case SDL_KEYDOWN:
|
nuclear@0
|
158 keybev = &ev;
|
nuclear@0
|
159 return;
|
nuclear@0
|
160
|
nuclear@0
|
161 case SDL_MOUSEMOTION:
|
nuclear@0
|
162 mousex = ev.motion.x;
|
nuclear@0
|
163 mousey = ev.motion.y;
|
nuclear@0
|
164
|
nuclear@0
|
165 if(DOUBLESZ) {
|
nuclear@0
|
166 mousex /= 2;
|
nuclear@0
|
167 mousey /= 2;
|
nuclear@0
|
168 }
|
nuclear@0
|
169 break;
|
nuclear@0
|
170
|
nuclear@0
|
171 case SDL_MOUSEBUTTONDOWN:
|
nuclear@0
|
172 case SDL_MOUSEBUTTONUP:
|
nuclear@0
|
173 {
|
nuclear@0
|
174 int mask = 0;
|
nuclear@0
|
175 switch(ev.button.button) {
|
nuclear@0
|
176 case SDL_BUTTON_LEFT:
|
nuclear@0
|
177 mask = MOUSE_LEFT;
|
nuclear@0
|
178 break;
|
nuclear@0
|
179 case SDL_BUTTON_MIDDLE:
|
nuclear@0
|
180 mask = MOUSE_MIDDLE;
|
nuclear@0
|
181 break;
|
nuclear@0
|
182 case SDL_BUTTON_RIGHT:
|
nuclear@0
|
183 mask = MOUSE_RIGHT;
|
nuclear@0
|
184 default:
|
nuclear@0
|
185 break;
|
nuclear@0
|
186 }
|
nuclear@0
|
187 if(!mask) {
|
nuclear@0
|
188 break;
|
nuclear@0
|
189 }
|
nuclear@0
|
190
|
nuclear@0
|
191 if(ev.button.state == SDL_PRESSED) {
|
nuclear@0
|
192 bnmask |= mask;
|
nuclear@0
|
193 } else {
|
nuclear@0
|
194 bnmask &= ~mask;
|
nuclear@0
|
195 }
|
nuclear@0
|
196 }
|
nuclear@0
|
197 break;
|
nuclear@0
|
198
|
nuclear@0
|
199 default:
|
nuclear@0
|
200 break;
|
nuclear@0
|
201 }
|
nuclear@0
|
202 }
|
nuclear@0
|
203 }
|
nuclear@0
|
204
|
nuclear@0
|
205 /* ---- timer.c implementation ---- */
|
nuclear@0
|
206 static Uint32 start_time;
|
nuclear@0
|
207
|
nuclear@0
|
208 void init_timer(int res_hz)
|
nuclear@0
|
209 {
|
nuclear@0
|
210 reset_timer();
|
nuclear@0
|
211 }
|
nuclear@0
|
212
|
nuclear@0
|
213 void reset_timer(void)
|
nuclear@0
|
214 {
|
nuclear@0
|
215 start_time = SDL_GetTicks();
|
nuclear@0
|
216 }
|
nuclear@0
|
217
|
nuclear@0
|
218 unsigned long get_msec(void)
|
nuclear@0
|
219 {
|
nuclear@0
|
220 return (unsigned long)(SDL_GetTicks() - start_time);
|
nuclear@0
|
221 }
|