2015-05-13 18:47:23 +00:00
|
|
|
#include "sysconfig.h"
|
|
|
|
#include "sysdeps.h"
|
|
|
|
#include "config.h"
|
|
|
|
#include "uae.h"
|
|
|
|
#include "options.h"
|
|
|
|
#include "gui.h"
|
2017-01-21 18:38:12 +01:00
|
|
|
#include "memory.h"
|
2016-04-24 09:45:29 +00:00
|
|
|
#include "newcpu.h"
|
2015-05-13 18:47:23 +00:00
|
|
|
#include "custom.h"
|
2016-04-24 09:45:29 +00:00
|
|
|
#include "xwin.h"
|
2015-05-13 18:47:23 +00:00
|
|
|
#include "drawing.h"
|
2016-04-24 09:45:29 +00:00
|
|
|
#include "inputdevice.h"
|
2015-05-13 18:47:23 +00:00
|
|
|
#include "savestate.h"
|
2015-09-09 21:49:41 +02:00
|
|
|
#include "picasso96.h"
|
2016-12-10 11:40:41 +01:00
|
|
|
#include "pandora_gfx.h"
|
2015-05-13 18:47:23 +00:00
|
|
|
|
|
|
|
#include <png.h>
|
2017-01-21 14:54:08 +01:00
|
|
|
#include "SDL.h"
|
2015-09-09 21:49:41 +02:00
|
|
|
|
|
|
|
/* SDL variable for output of emulation */
|
2017-01-29 14:24:34 +01:00
|
|
|
SDL_Surface* screen = nullptr;
|
2015-09-09 21:49:41 +02:00
|
|
|
|
|
|
|
/* Possible screen modes (x and y resolutions) */
|
2017-02-01 13:48:22 +01:00
|
|
|
#define MAX_SCREEN_MODES 13
|
|
|
|
static int x_size_table[MAX_SCREEN_MODES] = {640, 640, 720, 800, 800, 960, 1024, 1280, 1280, 1360, 1366, 1680, 1920};
|
|
|
|
static int y_size_table[MAX_SCREEN_MODES] = {400, 480, 400, 480, 600, 540, 768, 720, 800, 768, 768, 1050, 1080};
|
2015-09-09 21:49:41 +02:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
struct PicassoResolution* DisplayModes;
|
2015-11-16 22:32:10 +01:00
|
|
|
struct MultiDisplay Displays[MAX_DISPLAYS];
|
2015-09-09 21:49:41 +02:00
|
|
|
|
2015-11-16 22:32:10 +01:00
|
|
|
int screen_is_picasso = 0;
|
2015-09-09 21:49:41 +02:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
static SDL_Surface* current_screenshot = nullptr;
|
|
|
|
static char screenshot_filename_default[255] =
|
2016-09-01 13:53:43 +02:00
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
'/', 't', 'm', 'p', '/', 'n', 'u', 'l', 'l', '.', 'p', 'n', 'g', '\0'
|
2015-05-13 18:47:23 +00:00
|
|
|
};
|
2017-01-29 14:24:34 +01:00
|
|
|
char* screenshot_filename = static_cast<char *>(&screenshot_filename_default[0]);
|
|
|
|
FILE* screenshot_file = nullptr;
|
|
|
|
static void CreateScreenshot();
|
|
|
|
static int save_thumb(char* path);
|
2015-05-13 18:47:23 +00:00
|
|
|
int delay_savestate_frame = 0;
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
int graphics_setup(void)
|
2015-05-13 18:47:23 +00:00
|
|
|
{
|
2015-09-09 21:49:41 +02:00
|
|
|
#ifdef PICASSO96
|
2017-01-29 14:24:34 +01:00
|
|
|
picasso_InitResolutions();
|
|
|
|
InitPicasso96();
|
2015-09-09 21:49:41 +02:00
|
|
|
#endif
|
2017-01-29 14:24:34 +01:00
|
|
|
return 1;
|
2015-05-13 18:47:23 +00:00
|
|
|
}
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
void InitAmigaVidMode(struct uae_prefs* p)
|
2015-05-13 18:47:23 +00:00
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
/* Initialize structure for Amiga video modes */
|
|
|
|
gfxvidinfo.pixbytes = 2;
|
|
|
|
gfxvidinfo.bufmem = static_cast<uae_u8 *>(screen->pixels);
|
2017-02-22 15:10:38 +01:00
|
|
|
gfxvidinfo.outwidth = screen->w ? screen->w : 640; //p->gfx_size.width;
|
2017-02-02 22:27:51 +01:00
|
|
|
gfxvidinfo.outheight = screen->h ? screen->h : 256; //p->gfx_size.height;
|
2017-01-21 18:38:12 +01:00
|
|
|
gfxvidinfo.rowbytes = screen->pitch;
|
2015-05-13 18:47:23 +00:00
|
|
|
}
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
void graphics_subshutdown()
|
2015-05-13 18:47:23 +00:00
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
if (screen != nullptr)
|
|
|
|
{
|
|
|
|
SDL_FreeSurface(screen);
|
|
|
|
screen = nullptr;
|
|
|
|
}
|
|
|
|
if (texture != nullptr)
|
2017-01-21 19:28:18 +01:00
|
|
|
{
|
|
|
|
SDL_DestroyTexture(texture);
|
|
|
|
}
|
2016-10-15 20:49:53 +02:00
|
|
|
}
|
|
|
|
|
2017-02-22 15:30:49 +01:00
|
|
|
// Check if the requested Amiga resolution can be displayed with the current Screen mode as a direct multiple
|
|
|
|
// Based on this we make the decision to use Linear (smooth) or Nearest Neighbor (pixelated) scaling
|
|
|
|
bool isModeAspectRatioExact(SDL_DisplayMode* mode)
|
|
|
|
{
|
|
|
|
//TODO: for now, this is hardcoded to false which will cause Linear scaling to be used
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
static void open_screen(struct uae_prefs* p)
|
2015-05-13 18:47:23 +00:00
|
|
|
{
|
2017-01-21 18:59:24 +01:00
|
|
|
int width;
|
|
|
|
int height;
|
2017-01-29 14:24:34 +01:00
|
|
|
|
2017-01-21 17:28:43 +01:00
|
|
|
#ifdef PICASSO96
|
|
|
|
if (screen_is_picasso)
|
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
width = picasso_vidinfo.width;
|
2017-01-21 17:28:43 +01:00
|
|
|
height = picasso_vidinfo.height;
|
2017-01-29 14:24:34 +01:00
|
|
|
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); // make the scaled rendering look smoother.
|
2017-01-21 17:28:43 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
p->gfx_resolution = p->gfx_size.width > 600 ? 1 : 0;
|
2017-01-29 14:24:34 +01:00
|
|
|
width = p->gfx_size.width;
|
2017-01-21 17:28:43 +01:00
|
|
|
height = p->gfx_size.height;
|
2017-02-22 15:30:49 +01:00
|
|
|
if (isModeAspectRatioExact(&sdlMode))
|
|
|
|
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
|
|
|
|
else
|
|
|
|
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
|
2017-01-21 17:28:43 +01:00
|
|
|
}
|
2016-10-15 20:49:53 +02:00
|
|
|
|
2017-01-21 18:59:24 +01:00
|
|
|
graphics_subshutdown();
|
2017-02-22 15:10:38 +01:00
|
|
|
|
2017-01-21 18:59:24 +01:00
|
|
|
screen = SDL_CreateRGBSurface(0, width, height, 16, 0, 0, 0, 0);
|
|
|
|
check_error_sdl(screen == nullptr, "Unable to create a surface");
|
2017-01-29 14:24:34 +01:00
|
|
|
|
2017-02-22 15:10:38 +01:00
|
|
|
SDL_RenderSetLogicalSize(renderer, width, height*2);
|
2017-01-21 19:28:18 +01:00
|
|
|
|
2017-01-21 18:59:24 +01:00
|
|
|
// Initialize SDL Texture for the renderer
|
|
|
|
texture = SDL_CreateTexture(renderer,
|
2017-01-29 14:24:34 +01:00
|
|
|
SDL_PIXELFORMAT_RGB565,
|
|
|
|
SDL_TEXTUREACCESS_STREAMING,
|
|
|
|
width,
|
|
|
|
height);
|
2017-01-21 18:59:24 +01:00
|
|
|
check_error_sdl(texture == nullptr, "Unable to create texture");
|
|
|
|
|
2016-12-10 11:40:41 +01:00
|
|
|
// Update the texture from the surface
|
2017-01-29 14:24:34 +01:00
|
|
|
SDL_UpdateTexture(texture, nullptr, screen->pixels, screen->pitch);
|
2017-01-21 19:28:18 +01:00
|
|
|
SDL_RenderClear(renderer);
|
2016-12-10 11:40:41 +01:00
|
|
|
// Copy the texture on the renderer
|
2017-01-29 14:24:34 +01:00
|
|
|
SDL_RenderCopy(renderer, texture, nullptr, nullptr);
|
2016-12-10 11:40:41 +01:00
|
|
|
// Update the window surface (show the renderer)
|
|
|
|
SDL_RenderPresent(renderer);
|
2017-01-29 14:24:34 +01:00
|
|
|
|
|
|
|
if (screen != nullptr)
|
2017-01-21 18:59:24 +01:00
|
|
|
{
|
|
|
|
InitAmigaVidMode(p);
|
|
|
|
init_row_map();
|
|
|
|
}
|
2015-09-09 21:49:41 +02:00
|
|
|
}
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
void update_display(struct uae_prefs* p)
|
2015-09-09 21:49:41 +02:00
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
open_screen(p);
|
|
|
|
SDL_ShowCursor(SDL_DISABLE);
|
|
|
|
framecnt = 1; // Don't draw frame before reset done
|
2015-05-13 18:47:23 +00:00
|
|
|
}
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
int check_prefs_changed_gfx()
|
2015-05-13 18:47:23 +00:00
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
int changed = 0;
|
2016-09-01 13:53:43 +02:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
if (currprefs.gfx_size.height != changed_prefs.gfx_size.height ||
|
|
|
|
currprefs.gfx_size.width != changed_prefs.gfx_size.width ||
|
|
|
|
currprefs.gfx_size_fs.width != changed_prefs.gfx_size_fs.width ||
|
|
|
|
currprefs.gfx_resolution != changed_prefs.gfx_resolution)
|
|
|
|
{
|
|
|
|
cfgfile_configuration_change(1);
|
|
|
|
currprefs.gfx_size.height = changed_prefs.gfx_size.height;
|
|
|
|
currprefs.gfx_size.width = changed_prefs.gfx_size.width;
|
|
|
|
currprefs.gfx_size_fs.width = changed_prefs.gfx_size_fs.width;
|
|
|
|
currprefs.gfx_resolution = changed_prefs.gfx_resolution;
|
|
|
|
update_display(&currprefs);
|
|
|
|
changed = 1;
|
|
|
|
}
|
|
|
|
if (currprefs.leds_on_screen != changed_prefs.leds_on_screen ||
|
|
|
|
currprefs.pandora_hide_idle_led != changed_prefs.pandora_hide_idle_led ||
|
|
|
|
currprefs.pandora_vertical_offset != changed_prefs.pandora_vertical_offset)
|
|
|
|
{
|
|
|
|
currprefs.leds_on_screen = changed_prefs.leds_on_screen;
|
|
|
|
currprefs.pandora_hide_idle_led = changed_prefs.pandora_hide_idle_led;
|
|
|
|
currprefs.pandora_vertical_offset = changed_prefs.pandora_vertical_offset;
|
|
|
|
changed = 1;
|
|
|
|
}
|
|
|
|
if (currprefs.chipset_refreshrate != changed_prefs.chipset_refreshrate)
|
|
|
|
{
|
|
|
|
currprefs.chipset_refreshrate = changed_prefs.chipset_refreshrate;
|
|
|
|
init_hz_full();
|
|
|
|
changed = 1;
|
|
|
|
}
|
2016-09-01 13:53:43 +02:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
currprefs.filesys_limit = changed_prefs.filesys_limit;
|
2016-09-01 13:53:43 +02:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
return changed;
|
2015-05-13 18:47:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
int lockscr()
|
2015-05-13 18:47:23 +00:00
|
|
|
{
|
2017-01-21 18:38:12 +01:00
|
|
|
SDL_LockSurface(screen);
|
2017-01-29 14:24:34 +01:00
|
|
|
return 1;
|
2015-05-13 18:47:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
void unlockscr()
|
2015-05-13 18:47:23 +00:00
|
|
|
{
|
2017-01-21 18:38:12 +01:00
|
|
|
SDL_UnlockSurface(screen);
|
2015-05-13 18:47:23 +00:00
|
|
|
}
|
|
|
|
|
2016-08-27 20:39:53 +02:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
void wait_for_vsync()
|
2016-08-27 20:39:53 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
void flush_screen()
|
2015-05-13 18:47:23 +00:00
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
if (savestate_state == STATE_DOSAVE)
|
|
|
|
{
|
|
|
|
if (delay_savestate_frame > 0)
|
|
|
|
--delay_savestate_frame;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CreateScreenshot();
|
|
|
|
save_thumb(screenshot_filename);
|
|
|
|
savestate_state = 0;
|
|
|
|
}
|
|
|
|
}
|
2015-05-13 18:47:23 +00:00
|
|
|
|
2016-04-24 09:45:29 +00:00
|
|
|
#ifdef WITH_LOGGING
|
2016-09-01 13:53:43 +02:00
|
|
|
RefreshLiveInfo();
|
2016-04-24 09:45:29 +00:00
|
|
|
#endif
|
2016-08-27 20:39:53 +02:00
|
|
|
|
2016-12-10 11:40:41 +01:00
|
|
|
// Update the texture from the surface
|
2017-01-29 14:24:34 +01:00
|
|
|
SDL_UpdateTexture(texture, nullptr, screen->pixels, screen->pitch);
|
2016-12-10 11:40:41 +01:00
|
|
|
// Copy the texture on the renderer
|
2017-01-29 14:24:34 +01:00
|
|
|
SDL_RenderCopy(renderer, texture, nullptr, nullptr);
|
2016-12-10 11:40:41 +01:00
|
|
|
// Update the window surface (show the renderer)
|
|
|
|
SDL_RenderPresent(renderer);
|
2016-10-15 20:49:53 +02:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
init_row_map();
|
2015-05-13 18:47:23 +00:00
|
|
|
}
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
static void graphics_subinit()
|
2015-05-13 18:47:23 +00:00
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
if (screen == nullptr)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Unable to set video mode: %s\n", SDL_GetError());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SDL_ShowCursor(SDL_DISABLE);
|
|
|
|
InitAmigaVidMode(&currprefs);
|
|
|
|
}
|
2015-05-13 18:47:23 +00:00
|
|
|
}
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
STATIC_INLINE int bitsInMask(unsigned long mask)
|
2015-05-13 18:47:23 +00:00
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
/* count bits in mask */
|
|
|
|
int n = 0;
|
|
|
|
while (mask)
|
|
|
|
{
|
|
|
|
n += mask & 1;
|
|
|
|
mask >>= 1;
|
|
|
|
}
|
|
|
|
return n;
|
2015-05-13 18:47:23 +00:00
|
|
|
}
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
STATIC_INLINE int maskShift(unsigned long mask)
|
2015-05-13 18:47:23 +00:00
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
/* determine how far mask is shifted */
|
|
|
|
int n = 0;
|
|
|
|
while (!(mask & 1))
|
|
|
|
{
|
|
|
|
n++;
|
|
|
|
mask >>= 1;
|
|
|
|
}
|
|
|
|
return n;
|
2015-05-13 18:47:23 +00:00
|
|
|
}
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
static int init_colors()
|
2015-05-13 18:47:23 +00:00
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
int i;
|
|
|
|
int red_bits, green_bits, blue_bits;
|
|
|
|
int red_shift, green_shift, blue_shift;
|
2015-05-13 18:47:23 +00:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
/* Truecolor: */
|
2017-01-21 18:38:12 +01:00
|
|
|
red_bits = bitsInMask(screen->format->Rmask);
|
|
|
|
green_bits = bitsInMask(screen->format->Gmask);
|
|
|
|
blue_bits = bitsInMask(screen->format->Bmask);
|
|
|
|
red_shift = maskShift(screen->format->Rmask);
|
|
|
|
green_shift = maskShift(screen->format->Gmask);
|
|
|
|
blue_shift = maskShift(screen->format->Bmask);
|
2017-01-29 14:24:34 +01:00
|
|
|
alloc_colors64k(red_bits, green_bits, blue_bits, red_shift, green_shift, blue_shift, 0);
|
|
|
|
notice_new_xcolors();
|
|
|
|
for (i = 0; i < 4096; i++)
|
|
|
|
xcolors[i] = xcolors[i] * 0x00010001;
|
2015-05-13 18:47:23 +00:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
return 1;
|
2015-05-13 18:47:23 +00:00
|
|
|
}
|
|
|
|
|
2015-09-09 21:49:41 +02:00
|
|
|
/*
|
|
|
|
* Find the colour depth of the display
|
|
|
|
*/
|
2017-01-29 14:24:34 +01:00
|
|
|
static int get_display_depth()
|
2015-09-09 21:49:41 +02:00
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
// const SDL_VideoInfo *vid_info;
|
|
|
|
|
|
|
|
// int depth = 0;
|
2017-01-21 15:03:47 +01:00
|
|
|
int depth = 16;
|
2016-10-15 20:49:53 +02:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
// if ((vid_info = SDL_GetVideoInfo()))
|
|
|
|
// {
|
|
|
|
// depth = vid_info->vfmt->BitsPerPixel;
|
|
|
|
|
|
|
|
/* Don't trust the answer if it's 16 bits; the display
|
|
|
|
* could actually be 15 bits deep. We'll count the bits
|
|
|
|
* ourselves */
|
|
|
|
// if (depth == 16)
|
|
|
|
// depth = bitsInMask (vid_info->vfmt->Rmask) + bitsInMask (vid_info->vfmt->Gmask) + bitsInMask (vid_info->vfmt->Bmask);
|
|
|
|
// }
|
2016-10-15 20:49:53 +02:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
return depth;
|
2015-09-09 21:49:41 +02:00
|
|
|
}
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
int GetSurfacePixelFormat()
|
2015-11-16 22:32:10 +01:00
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
int depth = get_display_depth();
|
|
|
|
int unit = depth + 1 & 0xF8;
|
2015-11-16 22:32:10 +01:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
return (unit == 8 ? RGBFB_CHUNKY
|
|
|
|
: depth == 15 && unit == 16 ? RGBFB_R5G5B5
|
|
|
|
: depth == 16 && unit == 16 ? RGBFB_R5G6B5
|
|
|
|
: unit == 24 ? RGBFB_B8G8R8
|
|
|
|
: unit == 32 ? RGBFB_R8G8B8A8
|
|
|
|
: RGBFB_NONE);
|
2015-11-16 22:32:10 +01:00
|
|
|
}
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
int graphics_init(bool mousecapture)
|
2015-05-13 18:47:23 +00:00
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
graphics_subinit();
|
2015-05-13 18:47:23 +00:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
if (!init_colors())
|
|
|
|
return 0;
|
2016-09-01 13:53:43 +02:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
return 1;
|
2015-05-13 18:47:23 +00:00
|
|
|
}
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
void graphics_leave()
|
2015-05-13 18:47:23 +00:00
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
graphics_subshutdown();
|
|
|
|
|
2016-12-10 11:40:41 +01:00
|
|
|
SDL_DestroyRenderer(renderer);
|
|
|
|
SDL_DestroyWindow(sdlWindow);
|
2017-01-29 14:24:34 +01:00
|
|
|
|
|
|
|
SDL_VideoQuit();
|
2015-05-13 18:47:23 +00:00
|
|
|
}
|
|
|
|
|
2017-01-21 18:38:12 +01:00
|
|
|
#define systemRedShift (screen->format->Rshift)
|
|
|
|
#define systemGreenShift (screen->format->Gshift)
|
|
|
|
#define systemBlueShift (screen->format->Bshift)
|
|
|
|
#define systemRedMask (screen->format->Rmask)
|
|
|
|
#define systemGreenMask (screen->format->Gmask)
|
|
|
|
#define systemBlueMask (screen->format->Bmask)
|
2015-05-13 18:47:23 +00:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
static int save_png(SDL_Surface* surface, char* path)
|
|
|
|
{
|
|
|
|
int w = surface->w;
|
|
|
|
int h = surface->h;
|
|
|
|
unsigned char* pix = static_cast<unsigned char *>(surface->pixels);
|
|
|
|
unsigned char writeBuffer[1024 * 3];
|
|
|
|
FILE* f = fopen(path, "wb");
|
|
|
|
if (!f) return 0;
|
|
|
|
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
|
|
|
|
nullptr,
|
|
|
|
nullptr,
|
|
|
|
nullptr);
|
|
|
|
if (!png_ptr)
|
|
|
|
{
|
|
|
|
fclose(f);
|
|
|
|
return 0;
|
|
|
|
}
|
2015-05-13 18:47:23 +00:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
png_infop info_ptr = png_create_info_struct(png_ptr);
|
2015-05-13 18:47:23 +00:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
if (!info_ptr)
|
|
|
|
{
|
|
|
|
png_destroy_write_struct(&png_ptr,NULL);
|
|
|
|
fclose(f);
|
|
|
|
return 0;
|
|
|
|
}
|
2015-05-13 18:47:23 +00:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
png_init_io(png_ptr, f);
|
2015-05-13 18:47:23 +00:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
png_set_IHDR(png_ptr,
|
|
|
|
info_ptr,
|
|
|
|
w,
|
|
|
|
h,
|
|
|
|
8,
|
|
|
|
PNG_COLOR_TYPE_RGB,
|
|
|
|
PNG_INTERLACE_NONE,
|
|
|
|
PNG_COMPRESSION_TYPE_DEFAULT,
|
|
|
|
PNG_FILTER_TYPE_DEFAULT);
|
2015-05-13 18:47:23 +00:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
png_write_info(png_ptr, info_ptr);
|
2015-05-13 18:47:23 +00:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
unsigned char* b = writeBuffer;
|
2015-05-13 18:47:23 +00:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
int sizeX = w;
|
|
|
|
int sizeY = h;
|
|
|
|
int y;
|
|
|
|
int x;
|
2016-09-01 13:53:43 +02:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
unsigned short* p = reinterpret_cast<unsigned short *>(pix);
|
|
|
|
for (y = 0; y < sizeY; y++)
|
|
|
|
{
|
|
|
|
for (x = 0; x < sizeX; x++)
|
|
|
|
{
|
|
|
|
unsigned short v = p[x];
|
|
|
|
|
|
|
|
*b++ = ((v & systemRedMask) >> systemRedShift) << 3; // R
|
|
|
|
*b++ = ((v & systemGreenMask) >> systemGreenShift) << 2; // G
|
|
|
|
*b++ = ((v & systemBlueMask) >> systemBlueShift) << 3; // B
|
|
|
|
}
|
|
|
|
p += surface->pitch / 2;
|
|
|
|
png_write_row(png_ptr, writeBuffer);
|
|
|
|
b = writeBuffer;
|
|
|
|
}
|
2015-05-13 18:47:23 +00:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
png_write_end(png_ptr, info_ptr);
|
2015-05-13 18:47:23 +00:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
2015-05-13 18:47:23 +00:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
fclose(f);
|
|
|
|
return 1;
|
2015-05-13 18:47:23 +00:00
|
|
|
}
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
static void CreateScreenshot()
|
2015-05-13 18:47:23 +00:00
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
int w, h;
|
2015-05-13 18:47:23 +00:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
if (current_screenshot != nullptr)
|
|
|
|
{
|
|
|
|
SDL_FreeSurface(current_screenshot);
|
|
|
|
current_screenshot = nullptr;
|
|
|
|
}
|
2015-05-13 18:47:23 +00:00
|
|
|
|
2017-01-21 18:38:12 +01:00
|
|
|
w = screen->w;
|
|
|
|
h = screen->h;
|
|
|
|
current_screenshot = SDL_CreateRGBSurfaceFrom(screen->pixels,
|
2017-01-29 14:24:34 +01:00
|
|
|
w,
|
|
|
|
h,
|
|
|
|
screen->format->BitsPerPixel,
|
|
|
|
screen->pitch,
|
|
|
|
screen->format->Rmask,
|
|
|
|
screen->format->Gmask,
|
|
|
|
screen->format->Bmask,
|
|
|
|
screen->format->Amask);
|
2015-05-13 18:47:23 +00:00
|
|
|
}
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
static int save_thumb(char* path)
|
2015-05-13 18:47:23 +00:00
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
int ret = 0;
|
|
|
|
if (current_screenshot != nullptr)
|
|
|
|
{
|
|
|
|
ret = save_png(current_screenshot, path);
|
|
|
|
SDL_FreeSurface(current_screenshot);
|
|
|
|
current_screenshot = nullptr;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool vsync_switchmode(int hz)
|
|
|
|
{
|
|
|
|
// int changed_height = changed_prefs.gfx_size.height;
|
|
|
|
//
|
|
|
|
// if (hz >= 55)
|
|
|
|
// hz = 60;
|
|
|
|
// else
|
|
|
|
// hz = 50;
|
|
|
|
//
|
|
|
|
// if(hz == 50 && currVSyncRate == 60)
|
|
|
|
// {
|
|
|
|
// // Switch from NTSC -> PAL
|
|
|
|
// switch(changed_height) {
|
|
|
|
// case 200: changed_height = 240; break;
|
|
|
|
// case 216: changed_height = 262; break;
|
|
|
|
// case 240: changed_height = 270; break;
|
|
|
|
// case 256: changed_height = 270; break;
|
|
|
|
// case 262: changed_height = 270; break;
|
|
|
|
// case 270: changed_height = 270; break;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// else if(hz == 60 && currVSyncRate == 50)
|
|
|
|
// {
|
|
|
|
// // Switch from PAL -> NTSC
|
|
|
|
// switch(changed_height) {
|
|
|
|
// case 200: changed_height = 200; break;
|
|
|
|
// case 216: changed_height = 200; break;
|
|
|
|
// case 240: changed_height = 200; break;
|
|
|
|
// case 256: changed_height = 216; break;
|
|
|
|
// case 262: changed_height = 216; break;
|
|
|
|
// case 270: changed_height = 240; break;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if(changed_height == currprefs.gfx_size.height && hz == currprefs.chipset_refreshrate)
|
|
|
|
// return true;
|
|
|
|
//
|
|
|
|
// changed_prefs.gfx_size.height = changed_height;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool target_graphics_buffer_update()
|
|
|
|
{
|
|
|
|
bool rate_changed = false;
|
2017-01-21 18:38:12 +01:00
|
|
|
|
2017-01-21 17:28:43 +01:00
|
|
|
if (currprefs.gfx_size.height != changed_prefs.gfx_size.height)
|
|
|
|
{
|
|
|
|
update_display(&changed_prefs);
|
|
|
|
rate_changed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rate_changed)
|
|
|
|
{
|
|
|
|
fpscounter_reset();
|
|
|
|
time_per_frame = 1000 * 1000 / (currprefs.chipset_refreshrate);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2016-11-30 22:25:43 +01:00
|
|
|
}
|
2015-09-09 21:49:41 +02:00
|
|
|
|
|
|
|
#ifdef PICASSO96
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
int picasso_palette()
|
2016-04-24 09:45:29 +00:00
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
int i, changed;
|
2016-04-24 09:45:29 +00:00
|
|
|
|
2017-01-21 18:59:24 +01:00
|
|
|
changed = 0;
|
2017-01-29 14:24:34 +01:00
|
|
|
for (i = 0; i < 256; i++)
|
|
|
|
{
|
2017-01-21 18:59:24 +01:00
|
|
|
int r = picasso96_state.CLUT[i].Red;
|
|
|
|
int g = picasso96_state.CLUT[i].Green;
|
|
|
|
int b = picasso96_state.CLUT[i].Blue;
|
|
|
|
int value = (r << 16 | g << 8 | b);
|
|
|
|
uae_u32 v = CONVERT_RGB(value);
|
2017-01-29 14:24:34 +01:00
|
|
|
if (v != picasso_vidinfo.clut[i])
|
|
|
|
{
|
2017-01-21 18:59:24 +01:00
|
|
|
picasso_vidinfo.clut[i] = v;
|
|
|
|
changed = 1;
|
2017-01-29 14:24:34 +01:00
|
|
|
}
|
2017-01-21 18:59:24 +01:00
|
|
|
}
|
|
|
|
return changed;
|
2016-04-24 09:45:29 +00:00
|
|
|
}
|
2015-09-09 21:49:41 +02:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
static int resolution_compare(const void* a, const void* b)
|
2015-09-09 21:49:41 +02:00
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
struct PicassoResolution* ma = (struct PicassoResolution *)a;
|
|
|
|
struct PicassoResolution* mb = (struct PicassoResolution *)b;
|
|
|
|
if (ma->res.width < mb->res.width)
|
|
|
|
return -1;
|
|
|
|
if (ma->res.width > mb->res.width)
|
|
|
|
return 1;
|
|
|
|
if (ma->res.height < mb->res.height)
|
|
|
|
return -1;
|
|
|
|
if (ma->res.height > mb->res.height)
|
|
|
|
return 1;
|
|
|
|
return ma->depth - mb->depth;
|
2015-09-09 21:49:41 +02:00
|
|
|
}
|
2017-01-29 10:36:18 +01:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
static void sortmodes()
|
2015-09-09 21:49:41 +02:00
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
int i = 0, idx = -1;
|
|
|
|
int pw = -1, ph = -1;
|
|
|
|
while (DisplayModes[i].depth >= 0)
|
|
|
|
i++;
|
|
|
|
qsort(DisplayModes, i, sizeof (struct PicassoResolution), resolution_compare);
|
|
|
|
for (i = 0; DisplayModes[i].depth >= 0; i++)
|
|
|
|
{
|
|
|
|
if (DisplayModes[i].res.height != ph || DisplayModes[i].res.width != pw)
|
|
|
|
{
|
|
|
|
ph = DisplayModes[i].res.height;
|
|
|
|
pw = DisplayModes[i].res.width;
|
|
|
|
idx++;
|
|
|
|
}
|
|
|
|
DisplayModes[i].residx = idx;
|
|
|
|
}
|
2015-09-09 21:49:41 +02:00
|
|
|
}
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
static void modesList()
|
2015-09-09 21:49:41 +02:00
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
int i, j;
|
2015-11-16 22:32:10 +01:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
i = 0;
|
|
|
|
while (DisplayModes[i].depth >= 0)
|
|
|
|
{
|
|
|
|
write_log ("%d: %s (", i, DisplayModes[i].name);
|
|
|
|
j = 0;
|
|
|
|
while (DisplayModes[i].refresh[j] > 0)
|
|
|
|
{
|
|
|
|
if (j > 0)
|
|
|
|
write_log (",");
|
|
|
|
write_log ("%d", DisplayModes[i].refresh[j]);
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
write_log (")\n");
|
|
|
|
i++;
|
|
|
|
}
|
2015-09-09 21:49:41 +02:00
|
|
|
}
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
void picasso_InitResolutions()
|
2015-09-09 21:49:41 +02:00
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
struct MultiDisplay* md1;
|
|
|
|
int i, count = 0;
|
|
|
|
char tmp[200];
|
|
|
|
int bit_idx;
|
|
|
|
int bits[] = {8, 16, 32};
|
2016-09-01 13:53:43 +02:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
Displays[0].primary = 1;
|
|
|
|
Displays[0].disabled = 0;
|
|
|
|
Displays[0].rect.left = 0;
|
|
|
|
Displays[0].rect.top = 0;
|
|
|
|
Displays[0].rect.right = 800;
|
|
|
|
Displays[0].rect.bottom = 480;
|
|
|
|
sprintf(tmp, "%s (%d*%d)", "Display", Displays[0].rect.right, Displays[0].rect.bottom);
|
|
|
|
Displays[0].name = my_strdup(tmp);
|
|
|
|
Displays[0].name2 = my_strdup("Display");
|
2016-09-01 13:53:43 +02:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
md1 = Displays;
|
|
|
|
DisplayModes = md1->DisplayModes = xmalloc (struct PicassoResolution, MAX_PICASSO_MODES);
|
|
|
|
for (i = 0; i < MAX_SCREEN_MODES && count < MAX_PICASSO_MODES; i++)
|
|
|
|
{
|
|
|
|
for (bit_idx = 0; bit_idx < 3; ++bit_idx)
|
|
|
|
{
|
|
|
|
int bitdepth = bits[bit_idx];
|
|
|
|
int bit_unit = (bitdepth + 1) & 0xF8;
|
|
|
|
int rgbFormat = (bitdepth == 8 ? RGBFB_CLUT : (bitdepth == 16 ? RGBFB_R5G6B5 : RGBFB_R8G8B8A8));
|
|
|
|
int pixelFormat = 1 << rgbFormat;
|
|
|
|
pixelFormat |= RGBFF_CHUNKY;
|
|
|
|
//
|
|
|
|
// if (SDL_VideoModeOK (x_size_table[i], y_size_table[i], 16, SDL_SWSURFACE))
|
|
|
|
// {
|
|
|
|
DisplayModes[count].res.width = x_size_table[i];
|
|
|
|
DisplayModes[count].res.height = y_size_table[i];
|
|
|
|
DisplayModes[count].depth = bit_unit >> 3;
|
|
|
|
DisplayModes[count].refresh[0] = 50;
|
|
|
|
DisplayModes[count].refresh[1] = 60;
|
|
|
|
DisplayModes[count].refresh[2] = 0;
|
|
|
|
DisplayModes[count].colormodes = pixelFormat;
|
|
|
|
sprintf(DisplayModes[count].name, "%dx%d, %d-bit",
|
|
|
|
DisplayModes[count].res.width, DisplayModes[count].res.height, DisplayModes[count].depth * 8);
|
|
|
|
|
|
|
|
count++;
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DisplayModes[count].depth = -1;
|
|
|
|
sortmodes();
|
|
|
|
modesList();
|
|
|
|
DisplayModes = Displays[0].DisplayModes;
|
2015-09-09 21:49:41 +02:00
|
|
|
}
|
2016-11-30 22:25:43 +01:00
|
|
|
#endif
|
2016-09-01 00:02:17 +02:00
|
|
|
|
2016-11-30 22:25:43 +01:00
|
|
|
#ifdef PICASSO96
|
2017-01-29 14:24:34 +01:00
|
|
|
void gfx_set_picasso_state(int on)
|
2016-04-24 09:45:29 +00:00
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
if (on == screen_is_picasso)
|
|
|
|
return;
|
2016-04-24 09:45:29 +00:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
screen_is_picasso = on;
|
|
|
|
open_screen(&currprefs);
|
2017-01-21 18:38:12 +01:00
|
|
|
picasso_vidinfo.rowbytes = screen->pitch;
|
2016-04-24 09:45:29 +00:00
|
|
|
}
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
void gfx_set_picasso_modeinfo(uae_u32 w, uae_u32 h, uae_u32 depth, RGBFTYPE rgbfmt)
|
2015-09-09 21:49:41 +02:00
|
|
|
{
|
2017-01-29 14:24:34 +01:00
|
|
|
depth >>= 3;
|
|
|
|
if ((unsigned(picasso_vidinfo.width) == w) &&
|
|
|
|
(unsigned(picasso_vidinfo.height) == h) &&
|
|
|
|
(unsigned(picasso_vidinfo.depth) == depth) &&
|
|
|
|
(picasso_vidinfo.selected_rgbformat == rgbfmt))
|
|
|
|
return;
|
2016-09-01 13:53:43 +02:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
picasso_vidinfo.selected_rgbformat = rgbfmt;
|
|
|
|
picasso_vidinfo.width = w;
|
|
|
|
picasso_vidinfo.height = h;
|
|
|
|
picasso_vidinfo.depth = 2; // Native depth
|
|
|
|
picasso_vidinfo.extra_mem = 1;
|
2016-09-01 13:53:43 +02:00
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
picasso_vidinfo.pixbytes = 2; // Native bytes
|
|
|
|
if (screen_is_picasso)
|
|
|
|
{
|
|
|
|
open_screen(&currprefs);
|
|
|
|
picasso_vidinfo.rowbytes = screen->pitch;
|
|
|
|
picasso_vidinfo.rgbformat = RGBFB_R5G6B5;
|
|
|
|
}
|
2015-09-09 21:49:41 +02:00
|
|
|
}
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
uae_u8* gfx_lock_picasso()
|
2015-09-09 21:49:41 +02:00
|
|
|
{
|
2017-01-21 18:38:12 +01:00
|
|
|
SDL_LockSurface(screen);
|
|
|
|
picasso_vidinfo.rowbytes = screen->pitch;
|
2017-01-29 14:24:34 +01:00
|
|
|
return static_cast<uae_u8 *>(screen->pixels);
|
2015-09-09 21:49:41 +02:00
|
|
|
}
|
|
|
|
|
2017-01-29 14:24:34 +01:00
|
|
|
void gfx_unlock_picasso()
|
2015-09-09 21:49:41 +02:00
|
|
|
{
|
2017-01-21 18:38:12 +01:00
|
|
|
SDL_UnlockSurface(screen);
|
2015-09-09 21:49:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif // PICASSO96
|