|
|
1.1 root 1: /*
2: Hatari - screen.c
3:
4: This file is distributed under the GNU Public License, version 2 or at your
5: option any later version. Read the file gpl.txt for details.
6: */
7:
8: #include <SDL.h>
9:
10: #include "main.h"
11: #include "configuration.h"
1.1.1.2 ! root 12: #include "../m68000.h"
1.1 root 13: #include "memAlloc.h"
14: #include "misc.h"
15: #include "screen.h"
16: #include "screenConvert.h"
17: #include "scalebit.h"
18:
1.1.1.2 ! root 19: unsigned long VideoBase; /* Base address in ST Ram for screen(read on each VBL) */
! 20: unsigned char *VideoRaster; /* Pointer to Video raster, after VideoBase in PC address space. Use to copy data on HBL */
! 21:
1.1 root 22: int len_main_palette;
23: unsigned short MainPalette[256];
24: unsigned short CtrlPalette[16];
25:
26: SCREENDRAW ScreenDraw; /* Set up with details of drawing functions */
27: unsigned char *pScreenBitmap=NULL; /* Screen pixels in PC RGB format, allocated with 'CreateDIBSection' */
28: unsigned char *pPCScreenDest; /* Destination PC buffer */
29: int STScreenStartHorizLine,STScreenEndHorizLine; /* Start/End lines to be converted */
30: int PCScreenBytesPerLine, STScreenWidthBytes, STScreenLeftSkipBytes;
31: BOOL bInFullScreen=FALSE; /* TRUE if in full screen */
32: BOOL bFullScreenHold = FALSE; /* TRUE if hold display while full screen */
33: BOOL bScreenContentsChanged; /* TRUE if buffer changed and requires blitting */
34: BOOL bTooSlowSoSkipAFlip = FALSE;
35: int nDroppedFrames=0; /* Number of dropped frames during emulation run */
36: int prevChosenDisplayMode = -1;
37:
38: int STScreenLineOffset[SCREEN_HEIGHT_HBL]; /* Offsets for ST screen lines eg, 0,160,320... */
39: unsigned long MainRGBPalette[256];
40: unsigned long CtrlRGBPalette[16];
41:
42: SDL_Surface *sdlscrn; /* The SDL screen surface */
43: BOOL bGrabMouse = FALSE; /* Grab the mouse cursor in the window */
44:
45:
46: /*-----------------------------------------------------------------------*/
47: /*
48: Set window size
49: */
50: void Screen_SetWindowRes()
51: {
52: prevChosenDisplayMode = ConfigureParams.Screen.ChosenDisplayMode;
53: switch (ConfigureParams.Screen.ChosenDisplayMode) {
54: case DISPLAYMODE_HICOL_1X:
55: sdlscrn=SDL_SetVideoMode(320, 200, 16, SDL_DOUBLEBUF | SDL_ANYFORMAT);
56: break;
57: default:
58: sdlscrn=SDL_SetVideoMode(640, 400, 16, SDL_DOUBLEBUF | SDL_ANYFORMAT);
59: break;
60: }
61: if ((sdlscrn == NULL) || (sdlscrn->format->BytesPerPixel < 2))
62: {
63: fprintf(stderr, "Could not set video mode:\n %s\n", SDL_GetError() );
64: SDL_Quit();
65: exit(-2);
66: }
67: pScreenBitmap=sdlscrn->pixels;
68:
69: if(!bGrabMouse)
70: {
71: SDL_WM_GrabInput(SDL_GRAB_OFF); /* Un-grab mouse pointer in windowed mode */
72: }
73: Screen_SetDrawModes(); /* Set draw modes(store which modes to use!) */
74: }
75:
76: /*-----------------------------------------------------------------------*/
77: /*
78: Init Screen bitmap and buffers/tables needed for ST to PC screen conversion
79: */
80: void Screen_Init(void)
81: {
82: Screen_SetWindowRes();
83:
84: Screen_SetScreenLineOffsets(); /* Store offset to each horizontal line */
85:
86: /* Configure some SDL stuff: */
87: SDL_WM_SetCaption(PROG_NAME, "Frontier");
88: SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
89: SDL_EventState(SDL_MOUSEBUTTONDOWN, SDL_ENABLE);
90: SDL_EventState(SDL_MOUSEBUTTONUP, SDL_ENABLE);
91: SDL_ShowCursor(SDL_DISABLE);
92: }
93:
94:
95: /*-----------------------------------------------------------------------*/
96: /*
97: Free screen bitmap and allocated resources
98: */
99: void Screen_UnInit(void)
100: {
101: }
102:
103:
104: /*-----------------------------------------------------------------------*/
105: /*
106: Reset screen
107: */
108: void Screen_Reset(void)
109: {
110: }
111:
112: /*-----------------------------------------------------------------------*/
113: /*
114: Store Y offset for each horizontal line in our source ST screen for each reference in assembler(no multiply)
115: */
116: void Screen_SetScreenLineOffsets(void)
117: {
118: int i;
119:
120: for(i=0; i<SCREEN_HEIGHT_HBL; i++)
121: STScreenLineOffset[i] = i * SCREENBYTES_LINE;
122: }
123:
124:
125: /*-----------------------------------------------------------------------*/
126:
127: /*-----------------------------------------------------------------------*/
128: /*
129: Enter Full screen mode
130: */
131:
132: static SDL_Surface *set_new_sdl_fsmode() {
133: SDL_Surface *newsdlscrn;
134:
135: newsdlscrn = SDL_SetVideoMode(sdlscrn->w, sdlscrn->h,
136: ScreenDraw.BitDepth, SDL_DOUBLEBUF | SDL_ANYFORMAT | SDL_FULLSCREEN);
137: return newsdlscrn;
138: }
139:
140: void Screen_EnterFullScreen(void)
141: {
142: SDL_Surface *newsdlscrn;
143:
144: if (!bInFullScreen)
145: {
146: Main_PauseEmulation(); /* Hold things... */
147: SDL_Delay(20); /* To give sound time to clear! */
148:
149: newsdlscrn = set_new_sdl_fsmode();
150: Screen_SetDrawModes(); /* Set draw modes(store which modes to use!) */
151:
152: if( newsdlscrn==NULL )
153: {
154: fprintf(stderr, "Could not set video mode:\n %s\n", SDL_GetError() );
155: }
156: else
157: {
158: sdlscrn = newsdlscrn;
159: pScreenBitmap = newsdlscrn->pixels;
160: bInFullScreen = TRUE;
161:
162: Screen_ClearScreen(); /* Black out screen bitmap as will be invalid when return */
163: }
164: Main_UnPauseEmulation(); /* And off we go... */
165:
166: SDL_WM_GrabInput(SDL_GRAB_ON); /* Grab mouse pointer in fullscreen */
167: }
168: }
169:
170:
171: /*-----------------------------------------------------------------------*/
172: /*
173: Return from Full screen mode back to a window
174: */
175: void Screen_ReturnFromFullScreen(void)
176: {
177: if (bInFullScreen)
178: {
179: Main_PauseEmulation(); /* Hold things... */
180: SDL_Delay(20); /* To give sound time to clear! */
181:
182: bInFullScreen = FALSE;
183:
184: Screen_SetWindowRes();
185: Screen_SetDrawModes();
186:
187: Main_UnPauseEmulation(); /* And off we go... */
188: }
189: }
190:
191:
192: /*-----------------------------------------------------------------------*/
193: /*
194: Clear Window display memory
195: */
196: void Screen_ClearScreen(void)
197: {
198: SDL_FillRect(sdlscrn,NULL, SDL_MapRGB(sdlscrn->format, 0, 0, 0) );
199: }
200:
201: /*-----------------------------------------------------------------------*/
202: /*
203: */
204: void Screen_SetDrawModes(void)
205: {
206: /* Clear out */
207: Memory_Clear(&ScreenDraw,sizeof(SCREENDRAW));
208:
209: ScreenDraw.pDrawFunction = screendrawfuncs[sdlscrn->format->BytesPerPixel][ConfigureParams.Screen.ChosenDisplayMode];
210: /* Assign full-screen draw modes from chosen option under dialog */
211: switch (ConfigureParams.Screen.ChosenDisplayMode) {
212:
213: case DISPLAYMODE_HICOL_1X:
214: ScreenDraw.Width = 320;
215: ScreenDraw.Height = 200;
216: ScreenDraw.BitDepth = sdlscrn->format->BitsPerPixel;
217: ScreenDraw.VertPixelsPerLine = 1;
218: ScreenDraw.PCStartHorizLine = 0;
219: ScreenDraw.MouseScale = 1;
220: break;
221: case DISPLAYMODE_HICOL_2X:
222: default:
223: ScreenDraw.Width = 640;
224: ScreenDraw.Height = 480;
225: ScreenDraw.BitDepth = sdlscrn->format->BitsPerPixel;
226: ScreenDraw.VertPixelsPerLine = 2;
227: ScreenDraw.PCStartHorizLine = 0;
228: ScreenDraw.MouseScale = 2;
229: break;
230: }
231: }
232:
233:
234: /*-----------------------------------------------------------------------*/
235: /*
236: Set details for ST screen conversion(Window version)
237: */
238: void Screen_SetWindowConvertDetails(void)
239: {
240: pPCScreenDest = pScreenBitmap; /* Destination PC screen */
241:
242: STScreenStartHorizLine = 0; /* Full height */
243:
244: /* Always draw to WHOLE screen including ALL borders */
245: STScreenLeftSkipBytes = 0; /* Number of bytes to skip on ST screen for left(border) */
246: STScreenWidthBytes = SCREENBYTES_LINE; /* Number of horizontal bytes in our ST screen */
247:
248: STScreenEndHorizLine = SCREEN_HEIGHT_HBL;
249:
250: PCScreenBytesPerLine = sdlscrn->pitch;
251: }
252:
253: /*-----------------------------------------------------------------------*/
254: /*
255: Set details for ST screen conversion (Full-Screen version)
256: */
257: void Screen_SetFullScreenConvertDetails(void)
258: {
259: /* Only draw what can fit into full-screen and centre on Y */
260: STScreenLeftSkipBytes = 0;
261: STScreenWidthBytes = SCREENBYTES_LINE;
262:
263: STScreenStartHorizLine = 0;
264: STScreenEndHorizLine = SCREEN_HEIGHT_HBL;
265:
266: PCScreenBytesPerLine = sdlscrn->pitch;
267: pPCScreenDest = (unsigned char *)sdlscrn->pixels; /* Destination PC screen */
268: /* And offset on X */
269: // pPCScreenDest += ScreenDraw.PCStartXOffset;
270: //pPCScreenDest += ScreenDraw.PCStartHorizLine * PCScreenBytesPerLine;
271:
272: /* Is non-interlaced? May need to double up on Y */
273: bScrDoubleY = TRUE;
274: }
275:
276:
277: /*-----------------------------------------------------------------------*/
278: /*
279: Lock full-screen for drawing
280: */
281: BOOL Screen_Lock(void)
282: {
283: if(SDL_MUSTLOCK(sdlscrn))
284: {
285: if(SDL_LockSurface(sdlscrn))
286: {
287: Screen_ReturnFromFullScreen(); /* All OK? If not need to jump back to a window */
288: return(FALSE);
289: }
290: }
291:
292: return(TRUE);
293: }
294:
295: /*-----------------------------------------------------------------------*/
296: /*
297: UnLock full-screen
298: */
299: void Screen_UnLock(void)
300: {
301: if( SDL_MUSTLOCK(sdlscrn) )
302: SDL_UnlockSurface(sdlscrn);
303: }
304:
305:
306: /*-----------------------------------------------------------------------*/
307: /*
308: Draw ST screen to window/full-screen framebuffer
309: */
310: void Screen_DrawFrame(BOOL bForceFlip)
311: {
312: void *pDrawFunction;
313:
314: if ((!ConfigureParams.Screen.bFullScreen) &&
315: (prevChosenDisplayMode != ConfigureParams.Screen.ChosenDisplayMode))
316: Screen_SetWindowRes ();
317:
318: //if (!bScreenContentsChanged) return;
319: if (bTooSlowSoSkipAFlip) {
320: bTooSlowSoSkipAFlip = FALSE;
321: return;
322: }
323:
324: /* Lock screen ready for drawing */
325: if (Screen_Lock()) {
326: bScreenContentsChanged = FALSE;
327: /* Set details */
328: if (bInFullScreen)
329: Screen_SetFullScreenConvertDetails();
330: else
331: Screen_SetWindowConvertDetails();
332: /* Call drawing for full-screen */
333: pDrawFunction = ScreenDraw.pDrawFunction;
334:
335: /* build RGB palettes */
336: BuildRGBPalette (MainRGBPalette, MainPalette, len_main_palette);
337: BuildRGBPalette (CtrlRGBPalette, CtrlPalette, 16);
338:
339: if (pDrawFunction)
340: CALL_VAR(pDrawFunction)
341:
342: /* Unlock screen */
343: Screen_UnLock();
344:
345: SDL_Flip(sdlscrn);
346: }
347: }
348:
349: /*-----------------------------------------------------------------------*/
350: /*
351: Draw ST screen to window/full-screen
352: This is now called from the 68k program's vblank handler,
353: since we need the vblank to update palettes appropriately
354: before drawing the screen (for frontier)
355: */
356: void Screen_Draw(unsigned long _dummy)
357: {
358: /* Are we holding screen? Ie let user choose options while in full-screen mode using GDI */
359: if (bInFullScreen && bFullScreenHold)
360: {
361: return;
362: }
363:
364: if (!bQuitProgram)
365: {
366: if(VideoBase)
367: {
368: Screen_DrawFrame(FALSE);
369: }
370: }
371:
372: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.