Rev 2 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2 | Rev 7 | ||
---|---|---|---|
Line 11... | Line 11... | ||
11 | * You must not remove this notice, or any other, from this software. |
11 | * You must not remove this notice, or any other, from this software. |
12 | */ |
12 | */ |
13 | 13 | ||
14 | #include <stdlib.h> // malloc |
14 | #include <stdlib.h> // malloc |
15 | #include <string.h> // memset |
15 | #include <string.h> // memset |
- | 16 | #include <stdbool.h> // bool |
|
16 | 17 | ||
17 | #include <SDL.h> |
18 | #include <SDL.h> |
18 | 19 | ||
19 | #include "system.h" |
20 | #include "system.h" |
20 | #include "game.h" |
21 | #include "game.h" |
21 | #include "img.h" |
22 | #include "img.h" |
22 | 23 | ||
23 | #define |
24 | #define SCALE_FACTOR 4 |
24 | #define SYSVID_HEIGHT 480 |
- | |
25 | #define SYSVID_BPP 32 |
- | |
26 | 25 | ||
27 | #ifdef __APPLE__ |
- | |
28 | #define INDEX_A 0 |
- | |
29 | #define INDEX_R 1 |
- | |
30 | #define INDEX_G 2 |
- | |
31 | #define INDEX_B 3 |
- | |
32 | #else // !__APPLE__ |
- | |
33 | #define INDEX_B 0 |
- | |
34 | #define INDEX_G 1 |
- | |
35 | #define INDEX_R 2 |
- | |
36 | #define INDEX_A 3 |
- | |
37 | #endif // __APPLE__ |
- | |
38 | - | ||
39 | U8 * |
26 | U8 sysvid_fb[320 * 200]; // the framebuffer for this game is really 320x200 |
40 | U8 want_fullscreen = FALSE;// TRUE; |
27 | U8 want_fullscreen = FALSE;// TRUE; |
41 | U8 want_filter = TRUE; |
28 | U8 want_filter = TRUE; |
42 | U8 |
29 | U8 recreate_screen = FALSE; |
43 | 30 | ||
- | 31 | static SDL_Window *window; |
|
- | 32 | static SDL_Renderer *renderer; |
|
44 | static |
33 | static SDL_Texture *screen_texture; |
- | 34 | ||
- | 35 | ||
- | 36 | // XBRZ scaler |
|
- | 37 | void xbrz_scale (size_t factor, const uint32_t *src, uint32_t *trg, int srcWidth, int srcHeight, bool has_alpha_channel); |
|
- | 38 | void nearest_neighbor_scale (const uint32_t *src, int srcWidth, int srcHeight, uint32_t *trg, int trgWidth, int trgHeight); |
|
45 | 39 | ||
46 | 40 | ||
47 | // Initialise video |
41 | // Initialise video |
48 | void sysvid_init (void) |
42 | void sysvid_init (void) |
49 | { |
43 | { |
50 | // create frame buffer |
- | |
51 | sysvid_fb = malloc (320 * 200); |
- | |
52 | if (sysvid_fb == NULL) |
- | |
53 | sys_panic ("Fatal error: frame buffer allocation failed.\n"); |
- | |
54 | - | ||
55 | // SDL init |
44 | // SDL init |
56 | if (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) |
45 | if (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) |
57 | sys_panic ("Fatal error: could not initialize SDL.\n"); |
46 | sys_panic ("Fatal error: could not initialize SDL.\n"); |
58 | 47 | ||
- | 48 | // create game window |
|
59 |
|
49 | window = SDL_CreateWindow ("Rick Dangerous", |
- | 50 | SDL_WINDOWPOS_UNDEFINED, // x |
|
- | 51 | SDL_WINDOWPOS_UNDEFINED, // y |
|
- | 52 | (want_fullscreen ? 0 : 1024), // let system assign width in fullscreen mode |
|
- | 53 | (want_fullscreen ? 0 : 768), // let system assign height in fullscreen mode |
|
- | 54 | (want_fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)); |
|
60 |
|
55 | if (window == NULL) |
- | 56 | sys_panic ("Fatal error: SDL can not create game window.\n"); |
|
61 | 57 | ||
62 | // |
58 | // create renderer |
63 |
|
59 | renderer = SDL_CreateRenderer (window, -1, 0); |
- | 60 | if (renderer == NULL) |
|
64 | sys_panic ("Fatal error: SDL can not |
61 | sys_panic ("Fatal error: SDL can not create renderer\n"); |
65 | 62 | ||
66 | // |
63 | // amke the scaled rendering look smoother |
- | 64 | SDL_RenderSetLogicalSize (renderer, 320 * SCALE_FACTOR, 200 * SCALE_FACTOR); |
|
- | 65 | ||
- | 66 | // create a texture that will cover the whole window |
|
67 |
|
67 | screen_texture = SDL_CreateTexture (renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 320 * SCALE_FACTOR, 200 * SCALE_FACTOR); |
- | 68 | if (screen_texture == NULL) |
|
- | 69 | sys_panic ("Fatal error: SDL can not create rendering surface\n"); |
|
- | 70 | ||
- | 71 | // clear the screen to black |
|
- | 72 | sysvid_clear (); |
|
68 | } |
73 | } |
69 | 74 | ||
70 | 75 | ||
71 | // Shutdown video |
76 | // Shutdown video |
72 | void sysvid_shutdown (void) |
77 | void sysvid_shutdown (void) |
73 | { |
78 | { |
74 | // destroy frame buffer |
- | |
75 | if (sysvid_fb) |
- | |
76 | free (sysvid_fb); |
- | |
77 | sysvid_fb = NULL; |
- | |
78 | - | ||
79 | // SDL quit |
79 | // SDL quit |
80 | SDL_Quit (); |
80 | SDL_Quit (); |
81 | } |
81 | } |
82 | 82 | ||
83 | 83 | ||
84 | // Clear screen |
84 | // Clear screen |
85 | void sysvid_clear (void) |
85 | void sysvid_clear (void) |
86 | { |
86 | { |
- | 87 | SDL_SetRenderDrawColor (renderer, 0, 0, 0, 255); |
|
- | 88 | SDL_RenderClear (renderer); |
|
- | 89 | SDL_RenderPresent (renderer); |
|
- | 90 | ||
87 | memset (sysvid_fb, 0, |
91 | memset (sysvid_fb, 0, sizeof (sysvid_fb)); |
88 | } |
92 | } |
89 | 93 | ||
90 | 94 | ||
91 | // Update screen |
95 | // Update screen |
92 | void sysvid_paint (rect_t *rects) |
96 | void sysvid_paint (rect_t *rects) |
93 | { |
97 | { |
94 | static SDL_Rect area; |
- | |
95 | static |
98 | static uint8_t screen_pixels[320 * 200 * 4]; |
96 | static |
99 | static uint8_t upscaled_pixels[320 * SCALE_FACTOR * 200 * SCALE_FACTOR * 4]; |
97 | static |
100 | static rect_t rect_whole = {0, 0, 320, 200, NULL}; // framebuffer coordinates. The framebuffer is 320x200. |
98 | static U8 palette[16][3] = |
101 | static U8 palette[16][3] = |
99 | { |
102 | { |
100 | {0x00, 0x00, 0x00}, |
103 | {0x00, 0x00, 0x00}, |
101 | {0xd8, 0x00, 0x00}, |
104 | {0xd8, 0x00, 0x00}, |
102 | {0xb0, 0x6c, 0x68}, |
105 | {0xb0, 0x6c, 0x68}, |
Line 112... | Line 115... | ||
112 | {0x48, 0x48, 0x48}, |
115 | {0x48, 0x48, 0x48}, |
113 | {0x68, 0x6c, 0x68}, |
116 | {0x68, 0x6c, 0x68}, |
114 | {0x90, 0x90, 0x90}, |
117 | {0x90, 0x90, 0x90}, |
115 | {0xb0, 0xb4, 0xb0} |
118 | {0xb0, 0xb4, 0xb0} |
116 | }; |
119 | }; |
117 | U16 x, y |
120 | U16 x, y; |
118 | U8 *p, *q, *p0, *q0; |
121 | U8 *p, *q, *p0, *q0; |
119 | 122 | ||
120 | if (rects == NULL) |
123 | if (rects == NULL) |
121 | return; |
124 | return; |
122 | 125 | ||
123 | if ( |
126 | if (recreate_screen) |
124 | { |
127 | { |
125 |
|
128 | recreate_screen = FALSE; |
126 |
|
129 | SDL_SetWindowFullscreen (window, (want_fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)); |
127 | sysvid_paint (& |
130 | sysvid_paint (&rect_whole); |
128 | } |
131 | } |
129 | 132 | ||
- | 133 | // expand what's in the 320x200x1 frame buffer to the 320x200x4 SDL texture buffer |
|
130 | while (rects) |
134 | while (rects) |
131 | { |
135 | { |
132 | p0 = sysvid_fb; |
- | |
133 | p0 |
136 | p0 = &sysvid_fb[rects->y * 320 + rects->x]; |
134 | q0 = (U8 *)screen->pixels; |
- | |
135 | q0 |
137 | q0 = &screen_pixels[(rects->y * 320 + rects->x) * 4]; |
136 | 138 | ||
137 | for (y = |
139 | for (y = rects->y; y < rects->y + rects->height; y++) |
138 | { |
140 | { |
- | 141 | p = p0; |
|
- | 142 | q = q0; |
|
- | 143 | ||
139 | for ( |
144 | for (x = rects->x; x < rects->x + rects->width; x++) |
140 | { |
145 | { |
- | 146 | *(q + 0) = palette[*p][2]; // blue |
|
- | 147 | *(q + 1) = palette[*p][1]; // green |
|
141 |
|
148 | *(q + 2) = palette[*p][0]; // red |
142 | q = |
149 | *(q + 3) = 0; // alpha |
143 | 150 | ||
144 | for (x = rects->x; x < rects->x + rects->width; x++) |
- | |
145 | { |
- | |
146 | for (xz = 0; xz < zoom; xz++) |
- | |
147 | { |
- | |
148 | if (want_filter && (y + yz < 220)) |
- | |
149 |
|
151 | q += 4; |
150 | *(q + INDEX_B) = (U8) (( (U32) ((zoom - xz) * (U32) palette[*( p )][2] |
- | |
151 | + xz * (U32) palette[*( p + 1 )][2]) |
- | |
152 | + (U32) ((zoom - yz) * (U32) palette[*( p )][2] |
- | |
153 | + yz * (U32) palette[*(p + 320)][2])) |
- | |
154 | / (zoom * zoom)); |
- | |
155 | - | ||
156 | *(q + INDEX_G) = (U8) (( (U32) ((zoom - xz) * (U32) palette[*( p )][1] |
- | |
157 | + xz * (U32) palette[*( p + 1 )][1]) |
- | |
158 | + (U32) ((zoom - yz) * (U32) palette[*( p )][1] |
- | |
159 | + yz * (U32) palette[*(p + 320)][1])) |
- | |
160 | / (zoom * zoom)); |
- | |
161 | - | ||
162 | *(q + INDEX_R) = (U8) (( (U32) ((zoom - xz) * (U32) palette[*( p )][0] |
- | |
163 | + xz * (U32) palette[*( p + 1 )][0]) |
- | |
164 | + (U32) ((zoom - yz) * (U32) palette[*( p )][0] |
- | |
165 | + yz * (U32) palette[*(p + 320)][0])) |
- | |
166 | / (zoom * zoom)); |
- | |
167 | *(q + INDEX_A) = 0; |
- | |
168 | } |
- | |
169 | else |
- | |
170 | { |
- | |
171 | *(q + INDEX_B) = palette[*p][2]; // pc: blue. mac: alpha |
- | |
172 | *(q + INDEX_G) = palette[*p][1]; // pc: green. mac: red |
- | |
173 | *(q + INDEX_R) = palette[*p][0]; // pc: red. mac: green |
- | |
174 | *(q + INDEX_A) = 0; // pc: alpha. mac: blue |
- | |
175 | } |
- | |
176 | - | ||
177 | q += pixel_size; |
- | |
178 | } |
- | |
179 | - | ||
180 |
|
152 | p++; |
181 | } |
- | |
182 | - | ||
183 | q0 += 320 * pixel_size * zoom; |
- | |
184 | } |
153 | } |
185 | 154 | ||
- | 155 | q0 += 320 * 4; |
|
186 | p0 += 320; |
156 | p0 += 320; |
187 | } |
157 | } |
188 | 158 | ||
189 | area.x = rects->x * zoom; |
- | |
190 | area.y = (rects->y + 20) * zoom; |
- | |
191 | area.h = rects->height * zoom; |
- | |
192 | area.w = rects->width * zoom; |
- | |
193 | SDL_UpdateRects (screen, 1, &area); |
- | |
194 | - | ||
195 | rects = rects->next; |
159 | rects = rects->next; |
196 | } |
160 | } |
- | 161 | ||
- | 162 | // now upscale with a little bit of magic |
|
- | 163 | if (want_filter) |
|
- | 164 | xbrz_scale (SCALE_FACTOR, (uint32_t *) screen_pixels, (uint32_t *) upscaled_pixels, 320, 200, false); |
|
- | 165 | else |
|
- | 166 | nearest_neighbor_scale ((uint32_t *) screen_pixels, 320, 200, (uint32_t *) upscaled_pixels, 320 * SCALE_FACTOR, 200 * SCALE_FACTOR); |
|
- | 167 | ||
- | 168 | SDL_UpdateTexture (screen_texture, NULL, upscaled_pixels, 320 * SCALE_FACTOR * 4); |
|
- | 169 | SDL_RenderClear (renderer); |
|
- | 170 | SDL_RenderCopy (renderer, screen_texture, NULL, NULL); |
|
- | 171 | SDL_RenderPresent (renderer); |
|
197 | } |
172 | } |