-
Notifications
You must be signed in to change notification settings - Fork 0
/
render.c
204 lines (176 loc) · 5.92 KB
/
render.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
//
// Routines d'affichage : 1x / 2x
//
#include "includes.h"
#if defined (__LINUX__) || defined (__APPLE__)
#define BPP32_2X 1 // Useless with Windows - Vital with Linux.
#endif
struct SRender gRender;
#ifdef BPP32_2X
// Scaling 2x. 8 > 32 BPP.
void Render_Scale2x(SDL_Surface *pSDL_Src, SDL_Surface *pSDL_Dst)
{
// Conversion de la palette courante.
u32 pPal[256];
u32 i;
for (i = 0; i < 256; i++)
pPal[i] = SDL_MapRGB(pSDL_Dst->format, gVar.pCurPal[i].r, gVar.pCurPal[i].g, gVar.pCurPal[i].b);
// 2x.
SDL_LockSurface(pSDL_Src);
SDL_LockSurface(pSDL_Dst);
u32 y, x;
u8 *pSrc = pSDL_Src->pixels;
u8 *pDst = pSDL_Dst->pixels;
u32 nClr;
u8 *pSrc2;
u32 *pDst2a, *pDst2b;
for (y = 0; y < SCR_Height; y++)
{
pSrc2 = pSrc;
pDst2a = (u32 *)pDst;
pDst2b = (u32 *)(pDst + pSDL_Dst->pitch);
for (x = 0; x < SCR_Width; x++)
{
nClr = pPal[*pSrc2++];
*pDst2a++ = nClr;
*pDst2a++ = nClr;
*pDst2b++ = nClr;
*pDst2b++ = nClr;
}
pSrc += pSDL_Src->pitch;
pDst += pSDL_Dst->pitch * 2;
}
SDL_UnlockSurface(pSDL_Src);
SDL_UnlockSurface(pSDL_Dst);
}
#else
// Scaling 2x.
void Render_Scale2x(SDL_Surface *pSDL_Src, SDL_Surface *pSDL_Dst)
{
SDL_LockSurface(pSDL_Src);
SDL_LockSurface(pSDL_Dst);
u32 y, x;
u8 *pSrc = pSDL_Src->pixels;
u8 *pDst = pSDL_Dst->pixels;
u16 nClr;
u8 *pSrc2;
u16 *pDst2a, *pDst2b;
for (y = 0; y < SCR_Height; y++)
{
pSrc2 = (u8 *)pSrc;
pDst2a = (u16 *)pDst;
pDst2b = (u16 *)(pDst + pSDL_Dst->pitch);
for (x = 0; x < SCR_Width; x++)
{
nClr = *pSrc2++;
nClr = nClr | (nClr << 8);
*pDst2a++ = nClr;
*pDst2b++ = nClr;
}
pSrc += pSDL_Src->pitch;
pDst += pSDL_Dst->pitch * 2;
}
SDL_UnlockSurface(pSDL_Src);
SDL_UnlockSurface(pSDL_Dst);
}
#endif
typedef void (*pRenderFct)(SDL_Surface *pSDL_Src, SDL_Surface *pSDL_Dst);
// Rendu + Flip.
void RenderFlip(u32 nSync)
{
static pRenderFct pFctTb[e_RenderMode_MAX] = { NULL, Render_Scale2x };
if (pFctTb[gRender.nRenderMode] != NULL) pFctTb[gRender.nRenderMode](gVar.pScreen, gRender.pScreen2x);
if (nSync) FrameWait();
SDL_Flip(gRender.nRenderMode == e_RenderMode_Normal ? gVar.pScreen : gRender.pScreen2x);
}
// Set video mode.
#ifdef BPP32_2X
SDL_Surface * VideoModeSet(u32 nScrWidth, u32 nScrHeight, u32 nBPP, u32 nSDL_Flags)
#else
SDL_Surface * VideoModeSet(u32 nScrWidth, u32 nScrHeight, u32 nSDL_Flags)
#endif
{
SDL_Surface *pSurf;
#ifdef BPP32_2X
pSurf = SDL_SetVideoMode(nScrWidth, nScrHeight, nBPP, SDL_SWSURFACE | nSDL_Flags);
#else
pSurf = SDL_SetVideoMode(nScrWidth, nScrHeight, 8, SDL_SWSURFACE | nSDL_Flags);
#endif
if (pSurf == NULL)
{
fprintf(stderr, "VideoModeSet(): Couldn't set video mode: %sn",SDL_GetError());
//exit(1);
}
else
SDL_FillRect(pSurf, NULL, 7); // Sous Windows, SDL_SetVideoMode g�n�re un event SDL_VIDEOEXPOSE. Comme on g�re F9 dans les events, �a �vite le flash rose (0 = rose / 7 = noir).
return (pSurf);
}
// Met le mode video qui va bien.
void Render_SetVideoMode(void)
{
switch (gRender.nRenderMode)
{
case e_RenderMode_Scale2x:
#ifdef BPP32_2X
gRender.pScreen2x = VideoModeSet(SCR_Width * 2, SCR_Height * 2, 32, (gRender.nFullscreenMode ? SDL_FULLSCREEN : 0));
#else
gRender.pScreen2x = VideoModeSet(SCR_Width * 2, SCR_Height * 2, (gRender.nFullscreenMode ? SDL_FULLSCREEN : 0));
#endif
gVar.pScreen = gRender.pScreenBuf2;
// if (gRender.pScreen2x != NULL) return; // Ok.
if (gRender.pScreen2x != NULL) // Ok.
{
SDL_SetPalette(gRender.pScreen2x, SDL_PHYSPAL | SDL_LOGPAL, gVar.pColors, 0, 256);
SDL_SetPalette(gRender.pScreenBuf2, SDL_LOGPAL, gVar.pColors, 0, 256);
return;
}
// Erreur => On repasse en mode Normal et Windowed.
gRender.nRenderMode = e_RenderMode_Normal;
gRender.nFullscreenMode = 0;
// ... et pas de break.
case e_RenderMode_Normal:
default:
#ifdef BPP32_2X
gVar.pScreen = VideoModeSet(SCR_Width, SCR_Height, 8, (gRender.nFullscreenMode ? SDL_FULLSCREEN : 0));
#else
gVar.pScreen = VideoModeSet(SCR_Width, SCR_Height, (gRender.nFullscreenMode ? SDL_FULLSCREEN : 0));
#endif
gRender.pScreen2x = NULL;
if (gVar.pScreen == NULL) exit(1); // Message d'erreur dans VideoModeSet.
SDL_SetPalette(gVar.pScreen, SDL_PHYSPAL | SDL_LOGPAL, gVar.pColors, 0, 256);
break;
}
}
// Renvoie un ptr sur la surface �cran r�elle (pour les palettes).
SDL_Surface * Render_GetRealVideoSurfPtr(void)
{
return (gRender.nRenderMode == e_RenderMode_Normal ? gVar.pScreen : gRender.pScreen2x);
}
// Init de la vid�o.
void Render_InitVideo(void)
{
gRender.nRenderMode = e_RenderMode_Normal;
gRender.nFullscreenMode = 0;
gRender.pScreen2x = NULL; // En mode 2x, ptr sur la surface �cran.
gRender.pScreenBuf2 = NULL; // Buffer de rendu pour le jeu en mode 2x (� la place de la surface �cran r�elle).
// On initialise d'abord un �cran en mode e_RenderMode_Normal. Important, car on fait un CreateRGBSurface � partir de cette surface.
#ifdef BPP32_2X
gVar.pScreen = VideoModeSet(SCR_Width, SCR_Height, 8, gRender.nFullscreenMode ? SDL_FULLSCREEN : 0);
#else
gVar.pScreen = VideoModeSet(SCR_Width, SCR_Height, gRender.nFullscreenMode ? SDL_FULLSCREEN : 0);
#endif
if (gVar.pScreen == NULL) exit(1);
// On cr�� un buffer de la taille de l'�cran.
// => En mode 2x, on switche le ptr pScreen sur cette surface, les rendus du jeu se font donc dedans. Puis on fait le scale/filtre du buffer vers la vraie surface �cran.
gRender.pScreenBuf2 = SDL_CreateRGBSurface(SDL_SWSURFACE, SCR_Width, SCR_Height, 8, gVar.pScreen->format->Rmask, gVar.pScreen->format->Gmask, gVar.pScreen->format->Bmask, 0);
if (gRender.pScreenBuf2 == NULL)
{
fprintf(stderr, "Render_InitVideo(): Unable to allocate SDL surface: %s\n", SDL_GetError());
exit(1);
}
}
// Libère les ressources du rendu. (1 fois !).
void RenderRelease(void)
{
SDL_FreeSurface(gRender.pScreenBuf2);
}