1 // Software blitter effects via SDL
2 #include "burner.h"
3 #include "vid_support.h"
4 #include "vid_softfx.h"
5
6 static int nInitedSubsytems = 0;
7
8 static int nGameWidth = 0, nGameHeight = 0; // screen size
9 SDL_Surface* sdlsBlitFX[2] = {NULL, }; // The image surfaces
10 SDL_Surface* sdlsFramebuf = NULL;
11
12 static int nSize;
13 static int nUseBlitter;
14
15 static int nUseSys;
16 static int nDirectAccess = 1;
17 static int nRotateGame = 0;
18
PrimClear()19 static int PrimClear()
20 {
21 SDL_FillRect(sdlsFramebuf, NULL, 0);
22
23 if (nVidFullscreen) {
24 SDL_Flip(sdlsFramebuf);
25 SDL_FillRect(sdlsFramebuf, NULL, 0);
26 }
27
28 return 0;
29 }
30
31 // Create a secondary DD surface for the screen
BlitFXMakeSurf()32 static int BlitFXMakeSurf()
33 {
34 sdlsBlitFX[0] = NULL;
35 sdlsBlitFX[1] = NULL;
36
37 // Try to allocate buffer in Video memory if required, always allocate one in System memory
38 if (nUseSys == 0) {
39 sdlsBlitFX[0] = SDL_CreateRGBSurface(SDL_HWSURFACE, nGameWidth * nSize, nGameHeight * nSize, sdlsFramebuf->format->BitsPerPixel, sdlsFramebuf->format->Rmask, sdlsFramebuf->format->Gmask, sdlsFramebuf->format->Bmask, sdlsFramebuf->format->Amask);
40 if (sdlsBlitFX[0] == NULL) {
41 nDirectAccess = 0;
42 nUseSys = 1;
43 }
44 }
45
46 if (nDirectAccess == 0) {
47 sdlsBlitFX[1] = SDL_CreateRGBSurface(SDL_SWSURFACE, nGameWidth * nSize, nGameHeight * nSize, sdlsFramebuf->format->BitsPerPixel, sdlsFramebuf->format->Rmask, sdlsFramebuf->format->Gmask, sdlsFramebuf->format->Bmask, sdlsFramebuf->format->Amask);
48 if (sdlsBlitFX[1] == NULL) {
49 return 1;
50 }
51 }
52
53 SDL_FillRect(sdlsBlitFX[1 ^ nDirectAccess], NULL, 0);
54
55 return 0;
56 }
57
BlitFXExit()58 static int BlitFXExit()
59 {
60 SDL_FreeSurface(sdlsBlitFX[0]);
61 sdlsBlitFX[0] = NULL;
62 SDL_FreeSurface(sdlsBlitFX[1]);
63 sdlsBlitFX[1] = NULL;
64
65 VidSFreeVidImage();
66
67 nRotateGame = 0;
68
69 return 0;
70 }
71
BlitFXInit()72 static int BlitFXInit()
73 {
74 if (nRotateGame & 1) {
75 nVidImageWidth = nGameHeight;
76 nVidImageHeight = nGameWidth;
77 } else {
78 nVidImageWidth = nGameWidth;
79 nVidImageHeight = nGameHeight;
80 }
81
82 if (nUseBlitter >= 7 && nUseBlitter <= 9) {
83 nVidImageDepth = 16; // Use 565 format
84 } else {
85 nVidImageDepth = sdlsFramebuf->format->BitsPerPixel;// Use color depth of primary surface
86 }
87 nVidImageBPP = sdlsFramebuf->format->BytesPerPixel;
88 nBurnBpp = nVidImageBPP; // Set Burn library Bytes per pixel
89
90 // Use our callback to get colors:
91 SetBurnHighCol(nVidImageDepth);
92
93 // Make the normal memory buffer
94 if (VidSAllocVidImage()) {
95 BlitFXExit();
96 return 1;
97 }
98
99 if (BlitFXMakeSurf()) {
100 BlitFXExit();
101 return 1;
102 }
103
104 return 0;
105 }
106
Exit()107 static int Exit()
108 {
109 BlitFXExit();
110
111 if (!(nInitedSubsytems & SDL_INIT_VIDEO)) {
112 SDL_QuitSubSystem(SDL_INIT_VIDEO);
113 }
114 nInitedSubsytems = 0;
115
116 return 0;
117 }
118
Init()119 static int Init()
120 {
121 nInitedSubsytems = SDL_WasInit(SDL_INIT_VIDEO);
122
123 if (!(nInitedSubsytems & SDL_INIT_VIDEO)) {
124 SDL_InitSubSystem(SDL_INIT_VIDEO);
125 }
126
127 nUseBlitter = nVidBlitterOpt[nVidSelect] & 0xFF;
128
129 nGameWidth = nVidImageWidth; nGameHeight = nVidImageHeight;
130
131 nRotateGame = 0;
132 if (bDrvOkay) {
133 // Get the game screen size
134 BurnDrvGetVisibleSize(&nGameWidth, &nGameHeight);
135
136 if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) {
137 if (nVidRotationAdjust & 1) {
138 int n = nGameWidth;
139 nGameWidth = nGameHeight;
140 nGameHeight = n;
141 nRotateGame |= (nVidRotationAdjust & 2);
142 } else {
143 nRotateGame |= 1;
144 }
145 }
146
147 if (BurnDrvGetFlags() & BDF_ORIENTATION_FLIPPED) {
148 nRotateGame ^= 2;
149 }
150 }
151
152 nSize = VidSoftFXGetZoom(nUseBlitter);
153 bVidScanlines = 0; // !!!
154
155 if (nVidFullscreen) {
156
157 nVidScrnWidth = nVidWidth; nVidScrnHeight = nVidHeight;
158
159 if ((sdlsFramebuf = SDL_SetVideoMode(nVidWidth, nVidHeight, nVidDepth, SDL_HWSURFACE | SDL_ANYFORMAT | SDL_DOUBLEBUF | SDL_FULLSCREEN)) == NULL) {
160 dprintf(_T("*** Couldn't enter fullscreen mode.\n"));
161 return 1;
162 }
163 } else {
164 if ((sdlsFramebuf = SDL_SetVideoMode(nGameWidth * nSize, nGameHeight * nSize, 0, SDL_RESIZABLE | SDL_HWSURFACE)) == NULL) {
165 return 1;
166 }
167 }
168
169 SDL_SetClipRect(sdlsFramebuf, NULL);
170
171 // Initialize the buffer surfaces
172 BlitFXInit();
173
174 if (VidSoftFXInit(nUseBlitter, nRotateGame)) {
175 if (VidSoftFXInit(0, nRotateGame)) {
176 Exit();
177 return 1;
178 }
179 }
180
181 return 0;
182 }
183
vidScale(RECT *,int,int)184 static int vidScale(RECT* , int, int)
185 {
186 return 0;
187 }
188
MemToSurf()189 static int MemToSurf()
190 {
191 VidSoftFXApplyEffectSDL(sdlsBlitFX[1 ^ nDirectAccess]);
192
193 if (nUseSys == 0 && nDirectAccess == 0) {
194
195 // Lock the surface so we can write to it
196 if (SDL_LockSurface(sdlsBlitFX[1])) {
197 return 1;
198 }
199 unsigned char* Surf = (unsigned char*)sdlsBlitFX[1]->pixels;
200 int nPitch = sdlsBlitFX[1]->pitch;
201
202 // Lock the surface so we can write to it
203 if (SDL_LockSurface(sdlsBlitFX[0])) {
204 return 1;
205 }
206 unsigned char* VidSurf = (unsigned char*)sdlsBlitFX[0]->pixels;
207 int nVidPitch = sdlsBlitFX[0]->pitch;
208
209 unsigned char *pd, *ps;
210
211 int nHeight = nGameHeight * nSize;
212
213 pd = VidSurf; ps = Surf;
214 for (int y = 0; y < nHeight; y++, pd += nVidPitch, ps += nPitch) {
215 memcpy(pd, ps, nPitch);
216 }
217
218 SDL_UnlockSurface(sdlsBlitFX[0]);
219 SDL_UnlockSurface(sdlsBlitFX[1]);
220 }
221
222 return 0;
223 }
224
225 // Run one frame and render the screen
Frame(bool bRedraw)226 static int Frame(bool bRedraw) // bRedraw = 0
227 {
228 if (pVidImage == NULL) {
229 return 1;
230 }
231
232 if (bDrvOkay) {
233 if (bRedraw) { // Redraw current frame
234 if (BurnDrvRedraw()) {
235 BurnDrvFrame(); // No redraw function provided, advance one frame
236 }
237 } else {
238 BurnDrvFrame(); // Run one frame and draw the screen
239 }
240
241 if ((BurnDrvGetFlags() & BDF_16BIT_ONLY) && pVidTransCallback)
242 pVidTransCallback();
243 }
244
245 MemToSurf(); // Copy the memory buffer to the directdraw buffer for later blitting
246
247 return 0;
248 }
249
250 // Paint the BlitFX surface onto the primary surface
Paint(int bValidate)251 static int Paint(int bValidate)
252 {
253 SDL_Rect sdlrDest = { 0, 0, nGameWidth * nSize, nGameHeight * nSize };
254
255 if (bValidate & 2) {
256 MemToSurf(); // Copy the memory buffer to the directdraw buffer for later blitting
257 }
258
259 if (nVidFullscreen) {
260 // Double bufferring
261
262 sdlrDest.x = (nVidScrnWidth - nGameWidth * nSize) / 2;
263 sdlrDest.y = (nVidScrnHeight - nGameHeight * nSize) / 2;
264
265 if (SDL_BlitSurface(sdlsBlitFX[nUseSys], NULL, sdlsFramebuf, &sdlrDest)) {
266 return 1;
267 }
268 SDL_Flip(sdlsFramebuf);
269 } else {
270 // Normal
271
272 if (SDL_BlitSurface(sdlsBlitFX[nUseSys], NULL, sdlsFramebuf, &sdlrDest)) {
273 return 1;
274 }
275 SDL_UpdateRect(sdlsFramebuf, 0, 0, 0, 0);
276 }
277
278 return 0;
279 }
280
GetSettings(InterfaceInfo * pInfo)281 static int GetSettings(InterfaceInfo* pInfo)
282 {
283 TCHAR szString[MAX_PATH] = _T("");
284
285 _sntprintf(szString, MAX_PATH, _T("Prescaling using %s (%i� zoom)"), VidSoftFXGetEffect(nUseBlitter), nSize);
286 IntInfoAddStringModule(pInfo, szString);
287
288 if (nRotateGame) {
289 IntInfoAddStringModule(pInfo, _T("Using software rotation"));
290 }
291
292 return 0;
293 }
294
295 // The Video Output plugin:
296 struct VidOut VidOutSDLFX = { Init, Exit, Frame, Paint, vidScale, GetSettings, _T("SDL Software Effects video output") };
297
298