File: demo_impl.h

package info (click to toggle)
libretro-nestopia 1.52.0%2B20230102.gitcb1e24e-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 12,960 kB
  • sloc: cpp: 107,513; xml: 27,221; python: 1,329; ansic: 772; makefile: 634
file content (190 lines) | stat: -rw-r--r-- 4,667 bytes parent folder | download | duplicates (8)
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
/* Simple shell used by demos. Uses SDL multimedia library. */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "SDL.h"

/* Image loader */
typedef struct image_t
{
	unsigned char const* byte_pixels;/* 8-bit pixels */
	unsigned short const* rgb_16;    /* 16-bit pixels */
	int width;
	int height;
	int row_width; /* number of pixels to get to next row (may be greater than width) */
} image_t;
/* if no palette, loads as 16-bit RGB */
void load_bmp( image_t* out, const char* path, SDL_Color palette [256] );
void save_bmp( const char* path );
void init_window( int width, int height );
int read_input( void );
void lock_pixels( void );
void double_output_height( void );
void display_output( void );
void fatal_error( const char* str );

static unsigned char* output_pixels; /* 16-bit RGB */
static long output_pitch;
static float mouse_x, mouse_y; /* -1.0 to 1.0 */
static int mouse_moved;
static int key_pressed;

/* implementation */

static SDL_Rect rect;
static SDL_Surface* screen;
static SDL_Surface* surface;
static unsigned long next_time;

void fatal_error( const char* str )
{
	fprintf( stderr, "Error: %s\n", str );
	exit( EXIT_FAILURE );
}

static void init_sdl_( void )
{
	static int initialized;
	if ( !initialized )
	{
		if ( SDL_Init( SDL_INIT_VIDEO ) < 0 )
			fatal_error( "SDL initialization failed" );
		atexit( SDL_Quit );
	}
}

void init_window( int width, int height )
{
	rect.w = width;
	rect.h = height;
	
	init_sdl_();
	
	screen = SDL_SetVideoMode( width, height, 0, 0 );
	surface = SDL_CreateRGBSurface( SDL_SWSURFACE, width, height, 16, 0, 0, 0, 0 );
	if ( !screen || !surface )
		fatal_error( "SDL initialization failed" );
	
	SDL_WM_SetCaption( "NTSC Filter Demo", "NTSC Filter Demo" );
}

int read_input( void )
{
	SDL_Event e;
	
	/* limit to 60 calls per second */
	unsigned long start = SDL_GetTicks();
	if ( start < next_time && next_time - start > 10 )
		SDL_Delay( next_time - start );
	while ( SDL_GetTicks() < next_time ) { }
	next_time = start + 1000 / 60;
	
	mouse_moved = 0;
	key_pressed = 0;
	
	while ( SDL_PollEvent( &e ) )
	{
		if ( e.type == SDL_MOUSEBUTTONDOWN || e.type == SDL_QUIT )
			return 0;
		
		if ( e.type == SDL_KEYDOWN )
		{
			if ( e.key.keysym.sym == SDLK_ESCAPE || e.key.keysym.sym == SDLK_q )
				return 0;
			key_pressed = e.key.keysym.sym;
		}
		
		if ( e.type == SDL_MOUSEMOTION )
		{
			int x, y;
			SDL_GetMouseState( &x, &y );
			mouse_moved = 1;
			mouse_x = x / (float) (SDL_GetVideoSurface()->w - 1) * 2 - 1;
			mouse_y = (1 - y / (float) (SDL_GetVideoSurface()->h - 1)) * 2 - 1;
		}
	}
	return 1;
}

void lock_pixels( void )
{
	if ( SDL_LockSurface( surface ) < 0 )
		fatal_error( "Couldn't lock surface" );
	SDL_FillRect( surface, 0, 0 );
	output_pitch = surface->pitch;
	output_pixels = (unsigned char*) surface->pixels;
}

void double_output_height( void )
{
	int y;
	for ( y = surface->h / 2; --y >= 0; )
	{
		unsigned char const* in = output_pixels + y * output_pitch;
		unsigned char* out = output_pixels + y * 2 * output_pitch;
		int n;
		for ( n = surface->w; n; --n )
		{
			unsigned prev = *(unsigned short*) in;
			unsigned next = *(unsigned short*) (in + output_pitch);
			/* mix 16-bit rgb without losing low bits */
			unsigned mixed = prev + next + ((prev ^ next) & 0x0821);
			/* darken by 12% */
			*(unsigned short*) out = prev;
			*(unsigned short*) (out + output_pitch) = (mixed >> 1) - (mixed >> 4 & 0x18E3);
			in += 2;
			out += 2;
		}
	}
}

void display_output( void )
{
	SDL_UnlockSurface( surface );
	if ( SDL_BlitSurface( surface, &rect, screen, &rect ) < 0 || SDL_Flip( screen ) < 0 )
		fatal_error( "SDL blit failed" );
}

void load_bmp( image_t* out, const char* path, SDL_Color palette [256] )
{
	SDL_PixelFormat fmt = { 0 }; /* clear fields */
	SDL_Palette pal = { 0 };
	SDL_Surface* bmp;
	SDL_Surface* conv;
	
	init_sdl_();
	bmp = SDL_LoadBMP( path );
	if ( !bmp )
		fatal_error( "Couldn't load BMP" );
	
	fmt.BitsPerPixel  = 16;
	fmt.BytesPerPixel = 2;
	if ( palette )
	{
		pal.ncolors = 256;
		pal.colors = palette;
		fmt.palette = &pal;
		fmt.BitsPerPixel  = 8;
		fmt.BytesPerPixel = 1;
	}
	conv = SDL_ConvertSurface( bmp, &fmt, SDL_SWSURFACE );
	if ( !conv )
		fatal_error( "Couldn't convert BMP" );
	SDL_FreeSurface( bmp );
	
	if ( SDL_LockSurface( conv ) < 0 )
		fatal_error( "Couldn't lock surface" );
	
	out->byte_pixels = (unsigned char *) conv->pixels;
	out->rgb_16      = (unsigned short*) conv->pixels;
	out->width       = conv->w;
	out->height      = conv->h;
	out->row_width   = conv->pitch / fmt.BytesPerPixel;
}

void save_bmp( const char* path )
{
	if ( SDL_SaveBMP( surface, path ) )
		fatal_error( "Couldn't save BMP" );
}