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"
4142
4243// GLOBALS
4344SDL_Surface *screen;
45+ SDL_Surface *hw_screen;
4446SDL_Surface *nes_screen; // 256x224
45- SDL_Surface* rgbscreen;
4647
4748extern 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)
430564void 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}
0 commit comments