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