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@9
|
41 unsigned int sdl_flags = SDL_HWPALETTE;
|
nuclear@0
|
42
|
nuclear@0
|
43 if(getenv("DOSEMU_DOUBLESIZE")) {
|
nuclear@0
|
44 resx *= 2;
|
nuclear@0
|
45 resy *= 2;
|
nuclear@0
|
46 }
|
nuclear@0
|
47
|
nuclear@9
|
48 if(getenv("DOSEMU_FULLSCREEN")) {
|
nuclear@9
|
49 sdl_flags |= SDL_FULLSCREEN;
|
nuclear@9
|
50 }
|
nuclear@9
|
51
|
nuclear@0
|
52 switch(mode) {
|
nuclear@0
|
53 case 0x13:
|
nuclear@0
|
54 SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
|
nuclear@9
|
55 if(!(fbsurf = SDL_SetVideoMode(resx, resy, 8, sdl_flags))) {
|
nuclear@0
|
56 fprintf(stderr, "failed to set video mode\n");
|
nuclear@0
|
57 abort();
|
nuclear@0
|
58 }
|
nuclear@0
|
59 SDL_ShowCursor(0);
|
nuclear@11
|
60 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
|
nuclear@0
|
61 break;
|
nuclear@0
|
62
|
nuclear@0
|
63 case 3:
|
nuclear@0
|
64 SDL_ShowCursor(1);
|
nuclear@11
|
65 SDL_EnableKeyRepeat(0, 0);
|
nuclear@0
|
66 SDL_Quit();
|
nuclear@0
|
67 break;
|
nuclear@0
|
68
|
nuclear@0
|
69 default:
|
nuclear@0
|
70 break;
|
nuclear@0
|
71 }
|
nuclear@0
|
72 }
|
nuclear@0
|
73
|
nuclear@0
|
74 void set_palette(unsigned char c, unsigned char r, unsigned char g, unsigned char b)
|
nuclear@0
|
75 {
|
nuclear@0
|
76 SDL_Color col;
|
nuclear@0
|
77 col.r = r;
|
nuclear@0
|
78 col.g = g;
|
nuclear@0
|
79 col.b = b;
|
nuclear@0
|
80
|
nuclear@0
|
81 if(SDL_SetPalette(fbsurf, SDL_LOGPAL | SDL_PHYSPAL, &col, c, 1) != 1) {
|
nuclear@0
|
82 fprintf(stderr, "set_palette failed to set the required color\n");
|
nuclear@0
|
83 }
|
nuclear@0
|
84 }
|
nuclear@0
|
85
|
nuclear@0
|
86 void copy_frame(unsigned char *frame)
|
nuclear@0
|
87 {
|
nuclear@0
|
88 if(SDL_MUSTLOCK(fbsurf)) {
|
nuclear@0
|
89 SDL_LockSurface(fbsurf);
|
nuclear@0
|
90 }
|
nuclear@0
|
91
|
nuclear@0
|
92 if(DOUBLESZ) {
|
nuclear@0
|
93 int i, j;
|
nuclear@0
|
94 Uint16 *dest = fbsurf->pixels;
|
nuclear@0
|
95
|
nuclear@0
|
96 for(i=0; i<200; i++) {
|
nuclear@0
|
97 for(j=0; j<320; j++) {
|
nuclear@0
|
98 Uint16 twopix = ((Uint16)*frame << 8) | (Uint16)*frame;
|
nuclear@0
|
99 dest[j] = dest[j + 320] = twopix;
|
nuclear@0
|
100 frame++;
|
nuclear@0
|
101 }
|
nuclear@0
|
102 dest += fbsurf->pitch;
|
nuclear@0
|
103 }
|
nuclear@0
|
104 } else {
|
nuclear@0
|
105 memcpy(fbsurf->pixels, frame, 64000);
|
nuclear@0
|
106 }
|
nuclear@0
|
107
|
nuclear@0
|
108 if(SDL_MUSTLOCK(fbsurf)) {
|
nuclear@0
|
109 SDL_UnlockSurface(fbsurf);
|
nuclear@0
|
110 }
|
nuclear@0
|
111 SDL_Flip(fbsurf);
|
nuclear@0
|
112 }
|
nuclear@0
|
113
|
nuclear@0
|
114 void wait_vsync(void)
|
nuclear@0
|
115 {
|
nuclear@0
|
116 }
|
nuclear@0
|
117
|
nuclear@0
|
118 /* ----- event handling (conio.h) ----- */
|
nuclear@0
|
119 static SDL_Event *keybev;
|
nuclear@0
|
120 static int mousex, mousey, bnmask;
|
nuclear@0
|
121
|
nuclear@0
|
122 int kbhit(void)
|
nuclear@0
|
123 {
|
nuclear@0
|
124 if(!keybev) {
|
nuclear@0
|
125 proc_events();
|
nuclear@0
|
126 }
|
nuclear@0
|
127 return keybev != 0;
|
nuclear@0
|
128 }
|
nuclear@0
|
129
|
nuclear@9
|
130 int getch(void)
|
nuclear@0
|
131 {
|
nuclear@9
|
132 int res;
|
nuclear@0
|
133
|
nuclear@0
|
134 while(!keybev) {
|
nuclear@0
|
135 SDL_Event ev;
|
nuclear@0
|
136 SDL_WaitEvent(&ev);
|
nuclear@0
|
137 SDL_PushEvent(&ev);
|
nuclear@0
|
138 proc_events();
|
nuclear@0
|
139 }
|
nuclear@0
|
140 res = keybev->key.keysym.sym;
|
nuclear@0
|
141 keybev = 0;
|
nuclear@0
|
142 return res;
|
nuclear@0
|
143 }
|
nuclear@0
|
144
|
nuclear@0
|
145 /* mouse handling (mouse.c implementation) */
|
nuclear@0
|
146 int have_mouse(void)
|
nuclear@0
|
147 {
|
nuclear@0
|
148 return 1;
|
nuclear@0
|
149 }
|
nuclear@0
|
150
|
nuclear@0
|
151 int read_mouse(int *xp, int *yp)
|
nuclear@0
|
152 {
|
nuclear@0
|
153 if(xp) *xp = mousex;
|
nuclear@0
|
154 if(yp) *yp = mousey;
|
nuclear@0
|
155 return bnmask;
|
nuclear@0
|
156 }
|
nuclear@0
|
157
|
nuclear@0
|
158 static void proc_events(void)
|
nuclear@0
|
159 {
|
nuclear@0
|
160 static SDL_Event ev;
|
nuclear@0
|
161
|
nuclear@0
|
162 while(SDL_PollEvent(&ev)) {
|
nuclear@0
|
163 switch(ev.type) {
|
nuclear@0
|
164 case SDL_KEYDOWN:
|
nuclear@0
|
165 keybev = &ev;
|
nuclear@0
|
166 return;
|
nuclear@0
|
167
|
nuclear@0
|
168 case SDL_MOUSEMOTION:
|
nuclear@0
|
169 mousex = ev.motion.x;
|
nuclear@0
|
170 mousey = ev.motion.y;
|
nuclear@0
|
171
|
nuclear@0
|
172 if(DOUBLESZ) {
|
nuclear@0
|
173 mousex /= 2;
|
nuclear@0
|
174 mousey /= 2;
|
nuclear@0
|
175 }
|
nuclear@0
|
176 break;
|
nuclear@0
|
177
|
nuclear@0
|
178 case SDL_MOUSEBUTTONDOWN:
|
nuclear@0
|
179 case SDL_MOUSEBUTTONUP:
|
nuclear@0
|
180 {
|
nuclear@0
|
181 int mask = 0;
|
nuclear@0
|
182 switch(ev.button.button) {
|
nuclear@0
|
183 case SDL_BUTTON_LEFT:
|
nuclear@0
|
184 mask = MOUSE_LEFT;
|
nuclear@0
|
185 break;
|
nuclear@0
|
186 case SDL_BUTTON_MIDDLE:
|
nuclear@0
|
187 mask = MOUSE_MIDDLE;
|
nuclear@0
|
188 break;
|
nuclear@0
|
189 case SDL_BUTTON_RIGHT:
|
nuclear@0
|
190 mask = MOUSE_RIGHT;
|
nuclear@0
|
191 default:
|
nuclear@0
|
192 break;
|
nuclear@0
|
193 }
|
nuclear@0
|
194 if(!mask) {
|
nuclear@0
|
195 break;
|
nuclear@0
|
196 }
|
nuclear@0
|
197
|
nuclear@0
|
198 if(ev.button.state == SDL_PRESSED) {
|
nuclear@0
|
199 bnmask |= mask;
|
nuclear@0
|
200 } else {
|
nuclear@0
|
201 bnmask &= ~mask;
|
nuclear@0
|
202 }
|
nuclear@0
|
203 }
|
nuclear@0
|
204 break;
|
nuclear@0
|
205
|
nuclear@0
|
206 default:
|
nuclear@0
|
207 break;
|
nuclear@0
|
208 }
|
nuclear@0
|
209 }
|
nuclear@0
|
210 }
|
nuclear@0
|
211
|
nuclear@0
|
212 /* ---- timer.c implementation ---- */
|
nuclear@0
|
213 static Uint32 start_time;
|
nuclear@0
|
214
|
nuclear@0
|
215 void init_timer(int res_hz)
|
nuclear@0
|
216 {
|
nuclear@0
|
217 reset_timer();
|
nuclear@0
|
218 }
|
nuclear@0
|
219
|
nuclear@0
|
220 void reset_timer(void)
|
nuclear@0
|
221 {
|
nuclear@0
|
222 start_time = SDL_GetTicks();
|
nuclear@0
|
223 }
|
nuclear@0
|
224
|
nuclear@0
|
225 unsigned long get_msec(void)
|
nuclear@0
|
226 {
|
nuclear@0
|
227 return (unsigned long)(SDL_GetTicks() - start_time);
|
nuclear@0
|
228 }
|