Skip to content

Commit cc1f5d1

Browse files
committed
use hardware screen
Signed-off-by: Vincent-FK <[email protected]>
1 parent b38e474 commit cc1f5d1

File tree

3 files changed

+234
-97
lines changed

3 files changed

+234
-97
lines changed

src/drivers/dingux-sdl/dingoo-video.cpp

Lines changed: 222 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <stdlib.h>
2727
#include <stdbool.h>
2828
#include <SDL/SDL.h>
29+
#include <SDL/SDL_image.h>
2930

3031
#include "dingoo.h"
3132
#include "dingoo-video.h"
@@ -41,8 +42,8 @@
4142

4243
// GLOBALS
4344
SDL_Surface *screen;
45+
SDL_Surface *hw_screen;
4446
SDL_Surface *nes_screen; // 256x224
45-
SDL_Surface* rgbscreen;
4647

4748
extern Config *g_config;
4849

@@ -159,17 +160,9 @@ int InitVideo(FCEUGI *gi) {
159160
// initialize dingoo video mode
160161
if (!s_VideoModeSet) {
161162
uint32 vm = 0; // 0 - 320x240, 1 - 400x240, 2 - 480x272
162-
#define NUMOFVIDEOMODES 3
163-
struct {
164-
uint32 x;
165-
uint32 y;
166-
} VModes[NUMOFVIDEOMODES] = {
167-
{320, 240},
168-
{400, 240},
169-
{480, 272}
170-
};
171-
172-
screen = SDL_SetVideoMode(320, 480, 16, SDL_HWSURFACE);
163+
164+
hw_screen = SDL_SetVideoMode(RES_HW_SCREEN_HORIZONTAL, RES_HW_SCREEN_VERTICAL, 16, SDL_HWSURFACE | DINGOO_MULTIBUF);
165+
screen = SDL_CreateRGBSurface(SDL_SWSURFACE, 320, 240, 16, 0, 0, 0, 0);
173166
s_VideoModeSet = true;
174167
}
175168

@@ -180,8 +173,6 @@ int InitVideo(FCEUGI *gi) {
180173
if(!nes_screen)
181174
printf("Error in SDL_CreateRGBSurfaceFrom\n");
182175
SDL_SetPalette(nes_screen, SDL_LOGPAL, (SDL_Color *)s_cpsdl, 0, 256);
183-
184-
rgbscreen = SDL_CreateRGBSurface(SDL_HWSURFACE, 320, 240, 16, 0,0,0,0);
185176

186177
SDL_ShowCursor(0);
187178

@@ -286,14 +277,196 @@ void UnlockConsole() {
286277

287278
#define READU16(x) (uint16) ((uint16)(x)[0] | (uint16)(x)[1] << 8)
288279

280+
/// Nearest neighboor optimized with possible out of screen coordinates (for cropping)
281+
void flip_NNOptimized_AllowOutOfScreen(SDL_Surface *src_surface, SDL_Surface *dst_surface, int new_w, int new_h) {
282+
int w1 = src_surface->w;
283+
//int h1 = src_surface->h;
284+
int w2 = new_w;
285+
int h2 = new_h;
286+
int x_ratio = (int) ((src_surface->w << 16) / w2);
287+
int y_ratio = (int) ((src_surface->h << 16) / h2);
288+
int x2, y2;
289+
290+
/// --- Compute padding for centering when out of bounds ---
291+
int y_padding = (RES_HW_SCREEN_VERTICAL - new_h) / 2;
292+
int x_padding = 0;
293+
if (w2 > RES_HW_SCREEN_HORIZONTAL) {
294+
x_padding = (w2 - RES_HW_SCREEN_HORIZONTAL) / 2 + 1;
295+
}
296+
int x_padding_ratio = x_padding * w1 / w2;
297+
//printf("src_surface->h=%d, h2=%d\n", src_surface->h, h2);
298+
299+
for (int i = 0; i < h2; i++) {
300+
if (i >= RES_HW_SCREEN_VERTICAL) {
301+
continue;
302+
}
303+
304+
uint16_t *t = (uint16_t *) (dst_surface->pixels + ((i + y_padding) * ((w2 > RES_HW_SCREEN_HORIZONTAL) ? RES_HW_SCREEN_HORIZONTAL : w2)) * sizeof (uint16_t));
305+
y2 = (i * y_ratio) >> 16;
306+
uint16_t *p = (uint16_t *) (src_surface->pixels + (y2 * w1 + x_padding_ratio) * sizeof (uint16_t));
307+
int rat = 0;
308+
for (int j = 0; j < w2; j++) {
309+
if (j >= RES_HW_SCREEN_HORIZONTAL) {
310+
continue;
311+
}
312+
x2 = rat >> 16;
313+
*t++ = p[x2];
314+
rat += x_ratio;
315+
//printf("y=%d, x=%d, y2=%d, x2=%d, (y2*src_surface->w)+x2=%d\n", i, j, y2, x2, (y2 * src_surface->w) + x2);
316+
}
317+
}
318+
}
319+
320+
/// Nearest neighboor optimized with possible out of screen coordinates (for cropping)
321+
void flip_NNOptimized_AllowOutOfScreen_NES(uint8_t *nes_px, SDL_Surface *dst_surface, int new_w, int new_h) {
322+
int w1 = 256; //NWIDTH;
323+
int h1 = s_tlines;
324+
int w2 = new_w;
325+
int h2 = new_h;
326+
int x_ratio = (int) ((w1 << 16) / w2);
327+
int y_ratio = (int) ((h1 << 16) / h2);
328+
int x2, y2;
329+
330+
/// --- Compute padding for centering when out of bounds ---
331+
int y_padding = (RES_HW_SCREEN_VERTICAL - new_h) / 2;
332+
int x_padding = 0;
333+
if (w2 > RES_HW_SCREEN_HORIZONTAL) {
334+
x_padding = (w2 - RES_HW_SCREEN_HORIZONTAL) / 2 + 1;
335+
}
336+
int x_padding_ratio = x_padding * w1 / w2;
337+
//printf("src_surface->h=%d, h2=%d\n", src_surface->h, h2);
338+
339+
for (int i = 0; i < h2; i++) {
340+
if (i >= RES_HW_SCREEN_VERTICAL) {
341+
continue;
342+
}
343+
344+
uint16_t *t = (uint16_t *) (dst_surface->pixels + ((i + y_padding) * ((w2 > RES_HW_SCREEN_HORIZONTAL) ? RES_HW_SCREEN_HORIZONTAL : w2)) * sizeof (uint16_t));
345+
y2 = (i * y_ratio) >> 16;
346+
uint8_t *p = (uint8_t *) (nes_px + (y2 * w1 + x_padding_ratio) * sizeof (uint8_t));
347+
int rat = 0;
348+
for (int j = 0; j < w2; j++) {
349+
if (j >= RES_HW_SCREEN_HORIZONTAL) {
350+
continue;
351+
}
352+
x2 = rat>>16;
353+
*t++ = s_psdl[p[x2]];
354+
rat += x_ratio;
355+
//printf("y=%d, x=%d, y2=%d, x2=%d, (y2*src_surface->w)+x2=%d\n", i, j, y2, x2, (y2 * src_surface->w) + x2);
356+
}
357+
}
358+
}
359+
360+
/// Nearest neighboor optimized with possible out of screen coordinates (for cropping)
361+
void flip_Downscale_LeftRightGaussianFilter_NES(uint8_t *nes_px, SDL_Surface *dst_surface, int new_w, int new_h) {
362+
int w1 = 256; //NWIDTH;
363+
int h1 = s_tlines;
364+
int w2 = new_w;
365+
int h2 = new_h;
366+
int x_ratio = (int) ((w1 << 16) / w2);
367+
int y_ratio = (int) ((h1 << 16) / h2);
368+
int x1, y1;
369+
370+
/// --- Compute padding for centering when out of bounds ---
371+
int y_padding = (RES_HW_SCREEN_VERTICAL - new_h) / 2;
372+
int x_padding = 0;
373+
if (w2 > RES_HW_SCREEN_HORIZONTAL) {
374+
x_padding = (w2 - RES_HW_SCREEN_HORIZONTAL) / 2 + 1;
375+
}
376+
int x_padding_ratio = x_padding * w1 / w2;
377+
//printf("src_surface->h=%d, h2=%d\n", src_surface->h, h2);
378+
379+
/// --- Interp params ---
380+
int px_diff_prev_x = 0;
381+
int px_diff_next_x = 0;
382+
uint32_t ponderation_factor;
383+
uint8_t left_px_missing, right_px_missing;
384+
385+
uint16_t *cur_p;
386+
uint16_t *cur_p_left;
387+
uint16_t *cur_p_right;
388+
uint32_t red_comp, green_comp, blue_comp;
389+
390+
for (int i = 0; i < h2; i++) {
391+
if (i >= RES_HW_SCREEN_VERTICAL) {
392+
continue;
393+
}
394+
395+
uint16_t *t = (uint16_t *) (dst_surface->pixels + ((i + y_padding) * ((w2 > RES_HW_SCREEN_HORIZONTAL) ? RES_HW_SCREEN_HORIZONTAL : w2)) * sizeof (uint16_t));
396+
y1 = (i * y_ratio) >> 16;
397+
uint8_t *p = (uint8_t *) (nes_px + (y1 * w1 + x_padding_ratio) * sizeof (uint8_t));
398+
int rat = 0;
399+
for (int j = 0; j < w2; j++) {
400+
if (j >= RES_HW_SCREEN_HORIZONTAL) {
401+
continue;
402+
}
403+
404+
// ------ current x value ------
405+
x1 = rat >> 16;
406+
px_diff_next_x = ((rat + x_ratio) >> 16) - x1;
407+
408+
// ------ adapted bilinear with 3x3 gaussian blur -------
409+
cur_p = &s_psdl[*(p + x1)];
410+
if (px_diff_prev_x > 1 || px_diff_next_x > 1 ) {
411+
red_comp= ((*cur_p) & 0xF800) << 1;
412+
green_comp = ((*cur_p) & 0x07E0) << 1;
413+
blue_comp = ((*cur_p) & 0x001F) << 1;
414+
415+
left_px_missing = (px_diff_prev_x > 1 && x1 > 0);
416+
right_px_missing = (px_diff_next_x > 1 && x1 + 1 < w1);
417+
ponderation_factor = 2 + left_px_missing + right_px_missing;
418+
419+
// ---- Interpolate current and left ----
420+
if (left_px_missing) {
421+
cur_p_left = &s_psdl[*(p + x1 - 1)];
422+
red_comp += ((*cur_p_left) & 0xF800);
423+
green_comp += ((*cur_p_left) & 0x07E0);
424+
blue_comp += ((*cur_p_left) & 0x001F);
425+
}
426+
427+
// ---- Interpolate current and right ----
428+
if (right_px_missing) {
429+
cur_p_right = &s_psdl[*(p + x1 + 1)];
430+
red_comp += ((*cur_p_right) & 0xF800);
431+
green_comp += ((*cur_p_right) & 0x07E0);
432+
blue_comp += ((*cur_p_right) & 0x001F);
433+
}
434+
435+
/// --- Compute new px value ---
436+
if (ponderation_factor == 4) {
437+
red_comp = (red_comp >> 2) & 0xF800;
438+
green_comp = (green_comp >> 2) & 0x07C0;
439+
blue_comp = (blue_comp >> 2) & 0x001F;
440+
} else if (ponderation_factor == 2) {
441+
red_comp = (red_comp >> 1) & 0xF800;
442+
green_comp = (green_comp >> 1) & 0x07C0;
443+
blue_comp = (blue_comp >> 1) & 0x001F;
444+
} else {
445+
red_comp = (red_comp / ponderation_factor) & 0xF800;
446+
green_comp = (green_comp / ponderation_factor) & 0x07C0;
447+
blue_comp = (blue_comp / ponderation_factor) & 0x001F;
448+
}
449+
450+
/// --- write pixel ---
451+
*t++ = red_comp + green_comp + blue_comp;
452+
} else {
453+
*t++ = s_psdl[p[x1]];
454+
}
455+
456+
/// save number of pixels to interpolate
457+
px_diff_prev_x = px_diff_next_x;
458+
459+
// ------ next pixel ------
460+
rat += x_ratio;
461+
//printf("y=%d, x=%d, y2=%d, x2=%d, (y2*src_surface->w)+x2=%d\n", i, j, y2, x2, (y2 * src_surface->w) + x2);
462+
}
463+
}
464+
}
465+
289466
/**
290467
* Pushes the given buffer of bits to the screen.
291468
*/
292-
293-
extern void upscale_320x448(uint32 *dst, uint8 *src);
294-
295-
void BlitScreen(uint8 *XBuf)
296-
{
469+
void BlitScreen(uint8 *XBuf) {
297470
int x, x2, y, y2;
298471
// Taken from fceugc
299472
// FDS switch disk requested - need to eject, select, and insert
@@ -324,80 +497,41 @@ void BlitScreen(uint8 *XBuf)
324497
}
325498

326499
// TODO - Move these to its own file?
327-
if (SDL_MUSTLOCK(screen)) SDL_LockSurface(screen);
500+
if (SDL_MUSTLOCK(hw_screen)) SDL_LockSurface(hw_screen);
328501

329502
register uint8 *pBuf = XBuf;
330503

331-
/*if(s_fullscreen == 3) { // fullscreen smooth
332-
if (s_clipSides) {
333-
upscale_320x240_bilinearish_clip((uint32 *)rgbscreen->pixels, (uint8 *)XBuf + 256 * 8, 256);
334-
} else {
335-
upscale_320x240_bilinearish_noclip((uint32 *)rgbscreen->pixels, (uint8 *)XBuf + 256 * 8, 256);
336-
}
337-
} else if(s_fullscreen == 2) { // fullscreen
338-
switch(screen->w) {
339-
case 320: upscale_320x240((uint32 *)rgbscreen->pixels, (uint8 *)XBuf + 256 * 8); break;
340-
}
341-
} else if(s_fullscreen == 1) { // aspect fullscreen
342-
switch(screen->w) {
343-
case 320:
344-
pBuf += (s_srendline * 256) + 8;
345-
register uint16 *dest = (uint16 *) rgbscreen->pixels;
346-
dest += (screen->w * s_srendline) + (rgbscreen->w - 280) / 2 + ((rgbscreen->h - 240) / 2) * rgbscreen->w;
347-
//dest += (screen->w * s_srendline) + (screen->w - 280) / 2 + ((screen->h - 240) / 2) * screen->w;
348-
// semi fullscreen no blur
349-
for (y = s_tlines; y; y--) {
350-
for (x = 240; x; x -= 6) {
351-
__builtin_prefetch(dest + 2, 1);
352-
*dest++ = s_psdl[*pBuf];
353-
*dest++ = s_psdl[*(pBuf + 1)];
354-
*dest++ = s_psdl[*(pBuf + 2)];
355-
*dest++ = s_psdl[*(pBuf + 3)];
356-
*dest++ = s_psdl[*(pBuf + 3)];
357-
*dest++ = s_psdl[*(pBuf + 4)];
358-
*dest++ = s_psdl[*(pBuf + 5)];
359-
pBuf += 6;
360-
}
361-
pBuf += 16;
362-
dest += 40;
363-
}
364-
}
365-
} else
366-
{ // native res
367-
int32 pinc = (rgbscreen->w - NWIDTH) >> 1;
368-
register uint32 *dest = (uint32 *) rgbscreen->pixels;
504+
static int prev_aspect_ratio = aspect_ratio;
369505

370-
// XXX soules - not entirely sure why this is being done yet
371-
pBuf += (s_srendline * 256) + NOFFSET;
372-
dest += (rgbscreen->w/2 * s_srendline) + pinc / 2 + ((rgbscreen->h - 240) / 4) * rgbscreen->w;
373-
374-
for (y = s_tlines; y; y--, pBuf += 256 - NWIDTH)
375-
{
376-
for (x = NWIDTH >> 3; x; x--) {
377-
__builtin_prefetch(dest + 4, 1);
378-
*(dest + 160) = palettetranslate[*(uint16 *) pBuf];
379-
*dest++ = palettetranslate[*(uint16 *) pBuf];
380-
*(dest + 160) = palettetranslate[*(uint16 *) (pBuf + 2)];
381-
*dest++ = palettetranslate[*(uint16 *) (pBuf + 2)];
382-
*(dest + 160) = palettetranslate[*(uint16 *) (pBuf + 4)];
383-
*dest++ = palettetranslate[*(uint16 *) (pBuf + 4)];
384-
*(dest + 160) = palettetranslate[*(uint16 *) (pBuf + 6)];
385-
*dest++ = palettetranslate[*(uint16 *) (pBuf + 6)];
386-
pBuf += 8;
387-
}
388-
dest += pinc;
389-
//TonyJih@CTC for RS97 screen
390-
//dest += 160;
391-
}
392-
}*/
393-
upscale_320x448((uint32 *)screen->pixels + 3840, (uint8 *)XBuf + 256 * 8);
506+
/* Clear screen if AR changed */
507+
if (prev_aspect_ratio != aspect_ratio) {
508+
prev_aspect_ratio = aspect_ratio;
509+
dingoo_clear_video();
510+
}
511+
512+
//printf("s_tlines = %d, s_srendline=%d, NOFFSET = %d, NWIDTH=%d\n", s_tlines, s_srendline, NOFFSET, NWIDTH);
394513

395-
/*for (uint8_t y = 0; y < 239; y++, s += 160, d += 320) // double-line fix by pingflood, 2018
396-
memmove((uint32_t*)d, (uint32_t*)s, 1280);*/
397-
//SDL_BlitSurface(rgbscreen, NULL, screen, NULL);
514+
switch (aspect_ratio) {
515+
case ASPECT_RATIOS_TYPE_STRECHED:
516+
/* Streched NN*/
517+
flip_NNOptimized_AllowOutOfScreen_NES(pBuf, hw_screen, hw_screen->w, hw_screen->h);
518+
break;
519+
520+
case ASPECT_RATIOS_TYPE_CROPPED:
521+
/* Cropped but not centered yes for some games */
522+
pBuf += (s_srendline * 256) + NOFFSET;
523+
flip_NNOptimized_AllowOutOfScreen_NES(pBuf, hw_screen, NWIDTH, s_tlines);
524+
break;
525+
526+
default:
527+
aspect_ratio = ASPECT_RATIOS_TYPE_CROPPED;
528+
/* Streched NN*/
529+
flip_NNOptimized_AllowOutOfScreen_NES(pBuf, hw_screen, NWIDTH, s_tlines);
530+
break;
531+
}
398532

399-
if (SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen);
400-
SDL_Flip(screen);
533+
if (SDL_MUSTLOCK(hw_screen)) SDL_UnlockSurface(hw_screen);
534+
SDL_Flip(hw_screen);
401535
}
402536

403537
/**
@@ -428,13 +562,5 @@ void FCEUI_SetAviDisableMovieMessages(bool disable) {
428562

429563
//clear all screens (for multiple-buffering)
430564
void dingoo_clear_video(void) {
431-
SDL_FillRect(screen,NULL,SDL_MapRGBA(screen->format, 0, 0, 0, 255));
432-
SDL_Flip(screen);
433-
434-
SDL_FillRect(screen,NULL,SDL_MapRGBA(screen->format, 0, 0, 0, 255));
435-
SDL_Flip(screen);
436-
#ifdef SDL_TRIPLEBUF
437-
SDL_FillRect(screen,NULL,SDL_MapRGBA(screen->format, 0, 0, 0, 255));
438-
SDL_Flip(screen);
439-
#endif
565+
memset(hw_screen->pixels, 0, hw_screen->w*hw_screen->h*hw_screen->format->BytesPerPixel);
440566
}

src/drivers/dingux-sdl/dingoo-video.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
#ifndef __DINGOO_VIDEO__
2+
#define __DINGOO_VIDEO__
3+
4+
5+
#define RES_HW_SCREEN_VERTICAL 240
6+
#define RES_HW_SCREEN_HORIZONTAL 240
17

28
uint32 PtoV(uint16 x, uint16 y);
39
bool FCEUD_ShouldDrawInputAids();
@@ -6,3 +12,5 @@ unsigned short *FCEUD_GetScreen();
612
#define dingoo_video_color15(R,G,B) ((((R)&0xF8)<<8)|(((G)&0xFC)<<3)|(((B)&0xF8)>>3))
713

814
extern void dingoo_clear_video(void);
15+
16+
#endif // __DINGOO_VIDEO__

0 commit comments

Comments
 (0)