From beee456c688330e044b5ec32e5860f9b3ab4ff2e Mon Sep 17 00:00:00 2001 From: Max Lingua Date: Fri, 17 Jan 2014 01:03:34 -0500 Subject: PS2: support for different gfx modes --- backends/platform/ps2/Gs2dScreen.cpp | 205 ++++++++++++++++++++++++++++------- backends/platform/ps2/Gs2dScreen.h | 9 +- backends/platform/ps2/GsDefs.h | 24 ++++ backends/platform/ps2/systemps2.cpp | 10 +- 4 files changed, 202 insertions(+), 46 deletions(-) diff --git a/backends/platform/ps2/Gs2dScreen.cpp b/backends/platform/ps2/Gs2dScreen.cpp index da1cce35e0..c1d6b6e5ac 100644 --- a/backends/platform/ps2/Gs2dScreen.cpp +++ b/backends/platform/ps2/Gs2dScreen.cpp @@ -44,12 +44,49 @@ enum Buffers { PRINTF }; +/* + Supported modes: + + Mode #1 = SDTV progressive (NTSC: 224p / PAL: 256p) + Mode #2 = SDTV interlaced (NTSC: 448i / PAL: 512i) <- default + Mode #3 = EDTV progressive (NTSC: 480p / PAL: 576p) + Mode #4 = HDTV progressive (720p) + Mode #5 = HDTV interlaced (1080i) + Mode #6 = VESA (640x480@60) + Mode #7 = VESA (800x600@60) + Mode #8 = VESA (1024x768@60) +*/ + +static ps2_mode_t ps2_mode[] = { + + // -> w, h, interlaced, pitch, mode, vck, magh, magv, dx, dy + + /* #1 : SDTV - progressive */ + { 640, 224, 0, 640, 0x02, 2560, 4, 0, 160 /*158*/, 25 /*22*/ }, /* NTSC */ + { 640, 256, 0, 640, 0x03, 2560, 4, 0, 170 /*163*/, 35 /*36*/ }, /* PAL */ + + /* #2 : SDTV - interlaced */ + { 640, 448, 1, 640, 0x02, 2560, 4, 0, 156 /*158*/, 50 /*45*/ }, /* NTSC */ + { 640, 512, 1, 640, 0x03, 2560, 4, 0, 170 /*163*/, 70 /*72*/ }, /* PAL */ + + /* #3 : EDTV */ + { 720, 480, 0, 768, 0x50, 1440, 2, 0, 58, 35 }, /* NTSC */ + /* { 720, 576, 0, 768, 0x53, 1440, 2, 0, 62, 45 }, */ /* PAL : full */ + /* { 656, 576, 0, 704, 0x53, 1312, 2, 0, 62, 45 }, */ /* PAL : redux @ (0,0) */ + { 656, 576, 0, 704, 0x53, 1312, 2, 0, 78 /*314*/, 45 }, /* PAL : redux @ center'd */ + + /* #4/#5 : HDTV */ + { 1280, 720, 0, 1280, 0x52, 1280, 1, 0, 76 /*302*/, 24 }, + { 1920, 1080, 1, 1920, 0x51, 1920, 1, 0, 60 /*236*/ /*238*/, 40 }, + + /* #6/#7/#8 : VESA 4:3 @ 60Hz */ + { 640, 480, 0, 640, 0x1A, 1280, 2, 0, 70 /*276*/, 34 }, + { 800, 600, 0, 832, 0x2B, 1600, 2, 0, 105 /*420*/, 26 }, + { 1024, 768, 0, 1024, 0x3B, 2048, 2, 0, 144 /*580*/, 34 } +}; + #define ANIM_STACK_SIZE (1024 * 32) -#define DEFAULT_PAL_X 175 -#define DEFAULT_PAL_Y 72 // 60 -#define DEFAULT_NTSC_X 165 -#define DEFAULT_NTSC_Y 45 #define ORG_X 256 #define ORG_Y 256 #define ORIGIN_X (ORG_X << 4) @@ -103,7 +140,8 @@ int vblankEndHandler(int cause) { void createAnimThread(Gs2dScreen *screen); -Gs2dScreen::Gs2dScreen(uint16 width, uint16 height, TVMode mode) { +Gs2dScreen::Gs2dScreen(uint16 width, uint16 height) { + _systemQuit = false; ee_sema_t newSema; newSema.init_count = 1; @@ -131,7 +169,7 @@ Gs2dScreen::Gs2dScreen(uint16 width, uint16 height, TVMode mode) { _pitch = (width + 127) & ~127; _screenBuf = (uint8 *)memalign(64, _width * _height); - _overlayBuf = (uint16 *)memalign(64, _width * _height * 2); + _overlayBuf = (uint16 *)memalign(64, _pitch * _height * 2); _clut = (uint32 *)memalign(64, 256 * 4); memset(_screenBuf, 0, _width * _height); @@ -139,32 +177,102 @@ Gs2dScreen::Gs2dScreen(uint16 width, uint16 height, TVMode mode) { _clut[1] = GS_RGBA(0xC0, 0xC0, 0xC0, 0); clearOverlay(); - if (mode == TV_DONT_CARE) { -#if 1 char romver[8]; + uint16 biosver; int fd = fioOpen("rom0:ROMVER", O_RDONLY); fioRead(fd, &romver, 8); fioClose(fd); + biosver=atoi(romver); + printf("ROMVER = %s\n", romver); + printf("ver = %d\n", atoi(romver)); + + if (!_tvMode) { // determine TV standard first + if (ConfMan.hasKey("tv_mode", "PlayStation2")) { + const char *tvname = ConfMan.get("tv_mode", "PlayStation2").c_str(); + + if (strcmp("ntsc", tvname) == 0) { + _tvMode = 2; + } + else if (strcmp("pal", tvname) == 0) { + _tvMode = 1; + } + else + _tvMode = 0; + } + + if (!_tvMode) { + if (romver[4] == 'E') + _tvMode = TV_PAL; + else + _tvMode = TV_NTSC; - if (romver[4] == 'E') - _tvMode = TV_PAL; - else - _tvMode = TV_NTSC; -#else - if (PAL_NTSC_FLAG == 'E') - _tvMode = TV_PAL; + printf("Auto-detect TV mode: PSX:%c PS2:%c\n", *(char *)(0x1FC7FF52), romver[4]); + } + } + + uint8 mode; + if (!_gfxMode) { // determine GFX mode next + if (ConfMan.hasKey("gfx_mode", "PlayStation2")) { + _gfxMode = ConfMan.getInt("gfx_mode", "PlayStation2"); + // TODO: free more video mem to support these modes + if (_gfxMode == 4 || _gfxMode == 5) { + printf("Not enough video mem: using EDTV (3)\n"); + _gfxMode = 3; + } + else + if (_gfxMode == 7 || _gfxMode == 8) { + printf("Not enough video mem: using VGA (6)\n"); + _gfxMode = 6; + } + + if (_gfxMode < 1 || _gfxMode > 8) _gfxMode = 2; + else + if (_gfxMode == 4 || _gfxMode == 5) _tvMode = TV_HDTV; + else + if (_gfxMode > 5) _tvMode = TV_VESA; + } else - _tvMode = TV_NTSC; -#endif - } else - _tvMode = mode; + _gfxMode = 2; + } - // _tvMode = TV_NTSC; - printf("Setting up %s mode\n", (_tvMode == TV_PAL) ? "PAL" : "NTSC"); + // Remap Mode Index + mode = _gfxMode; + if (_tvMode == TV_NTSC) { + mode = (mode * 2) - 1; + } + else if (_tvMode == TV_PAL) { + mode = (mode * 2); + } + else if (_tvMode == TV_HDTV) { + mode += 3; + } + else /* VESA */ { + _tvMode = TV_VESA; + mode += 3; + } + mode--; + + switch (_tvMode) { + case TV_NTSC: + printf("Setting up TV mode: NTSC\n"); + break; + case TV_PAL: + printf("Setting up TV mode: PAL\n"); + break; + case TV_HDTV: + printf("Setting up TV mode: HDTV\n"); + break; + case TV_VESA: + printf("Setting up TV mode: VESA\n"); + break; + } + + _tvWidth = ps2_mode[mode].w; + _tvHeight = ps2_mode[mode].h; + _tvPitch = ps2_mode[mode].pitch; + + printf("Setting up GFX mode: %d x %d\n", _tvWidth, _tvHeight); - // set screen size, 640x512 for pal, 640x448 for ntsc - _tvWidth = 640; - _tvHeight = ((_tvMode == TV_PAL) ? 512 /*544*/ : 448); kFullScreen[0].z = kFullScreen[1].z = 0; kFullScreen[0].x = ORIGIN_X; kFullScreen[0].y = ORIGIN_Y; @@ -177,7 +285,7 @@ Gs2dScreen::Gs2dScreen(uint16 width, uint16 height, TVMode mode) { _texCoords[1].u = SCALE(_width); _texCoords[1].v = SCALE(_height); - uint32 tvFrameSize = _tvWidth * _tvHeight * 4; // 32 bits per pixel + uint32 tvFrameSize = _tvPitch * _tvHeight * 4; // 32 bits per pixel // setup frame buffer pointers _frameBufPtr[0] = 0; @@ -216,22 +324,39 @@ Gs2dScreen::Gs2dScreen(uint16 width, uint16 height, TVMode mode) { GS_CSR = 0; GsPutIMR(0x7F00); - uint16 dispPosX, dispPosY; - if (_tvMode == TV_PAL) { - SetGsCrt(GS_INTERLACED, 3, 0); - dispPosX = DEFAULT_PAL_X; - dispPosY = DEFAULT_PAL_Y; - } else { - SetGsCrt(GS_INTERLACED, 2, 0); - dispPosX = DEFAULT_NTSC_X; - dispPosY = DEFAULT_NTSC_Y; + if (biosver < 220 && ps2_mode[mode].mode == 0x53) { // EDTV PAL : mode not in BIOS < 2.20 + // no worries... we work in magic ;-) + /* 720x576p */ + asm ("di"); + asm ("sync.l; sync.p"); + GS_PMODE = 0; + asm ("sync.l; sync.p"); + GS_SMODE1 = 0x1742890504; + asm ("sync.l; sync.p"); + GS_SMODE2 = 0; + GS_SYNCH1 = 0x402E02003C827; + asm ("sync.l; sync.p"); + GS_SYNCH2 = 0x19CA67; + asm ("sync.l; sync.p"); + GS_SYNCV = 0xA9000002700005; + asm ("sync.l; sync.p"); + GS_SRFSH = 4; + asm ("sync.l; sync.p"); + GS_SMODE1 = 0x1742880504; + asm ("sync.l; sync.p"); + asm ("sync.l; sync.p"); + GS_SMODE2 = 0; + asm("ei"); + } + else { // BIOS + SetGsCrt(ps2_mode[mode].interlaced, ps2_mode[mode].mode, 0); // ps2_mode[mode].interlaced); } asm("di"); GS_PMODE = GS_SET_PMODE(1, 0, 1, 1, 0, 255); GS_BGCOLOUR = GS_RGBA(0, 0, 0, 0); - GS_DISPLAY1 = GS_SET_DISPLAY(_tvWidth, _tvHeight, dispPosX, dispPosY); + GS_DISPLAY1 = GS_SET_DISPLAY_MODE(ps2_mode[mode]); asm("ei"); _curDrawBuf = 0; @@ -239,7 +364,7 @@ Gs2dScreen::Gs2dScreen(uint16 width, uint16 height, TVMode mode) { _dmaPipe->setOrigin(ORIGIN_X, ORIGIN_Y); _dmaPipe->setConfig(1, 0, 1); _dmaPipe->setScissorRect(0, 0, _tvWidth - 1, _tvHeight - 1); - _dmaPipe->setDrawBuffer(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24, 0); + _dmaPipe->setDrawBuffer(_frameBufPtr[_curDrawBuf], _tvPitch, GS_PSMCT24, 0); _dmaPipe->flush(); _clutChanged = _screenChanged = _overlayChanged = true; @@ -507,10 +632,10 @@ void Gs2dScreen::updateScreen(void) { WaitSema(g_DmacSema); // wait for dma transfer, if there's one running WaitSema(g_VblankSema); // wait if there's already an image waiting for vblank - g_DmacCmd = GS_SET_DISPFB(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24); // put it here for dmac/vblank handler + g_DmacCmd = GS_SET_DISPFB(_frameBufPtr[_curDrawBuf], _tvPitch, GS_PSMCT24); // put it here for dmac/vblank handler _dmaPipe->flush(); _curDrawBuf ^= 1; - _dmaPipe->setDrawBuffer(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24, 0); + _dmaPipe->setDrawBuffer(_frameBufPtr[_curDrawBuf], _tvPitch, GS_PSMCT24, 0); } else _dmaPipe->flush(); SignalSema(_screenSema); @@ -752,10 +877,10 @@ void Gs2dScreen::playAnim(void) { drawY += LINE_SPACE; } - g_DmacCmd = GS_SET_DISPFB(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24); // put it here for dmac/vblank handler + g_DmacCmd = GS_SET_DISPFB(_frameBufPtr[_curDrawBuf], _tvPitch, GS_PSMCT24); // put it here for dmac/vblank handler _dmaPipe->flush(); _curDrawBuf ^= 1; - _dmaPipe->setDrawBuffer(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24, 0); + _dmaPipe->setDrawBuffer(_frameBufPtr[_curDrawBuf], _tvPitch, GS_PSMCT24, 0); _dmaPipe->setAlphaBlend(DEST_COLOR, ZERO_COLOR, SOURCE_ALPHA, SOURCE_COLOR, 0); SignalSema(_screenSema); diff --git a/backends/platform/ps2/Gs2dScreen.h b/backends/platform/ps2/Gs2dScreen.h index ce6538753d..258ced627e 100644 --- a/backends/platform/ps2/Gs2dScreen.h +++ b/backends/platform/ps2/Gs2dScreen.h @@ -25,6 +25,7 @@ #include "sysdefs.h" #include "backends/base-backend.h" +#include "common/config-manager.h" #include "backends/platform/ps2/DmaPipe.h" #include "graphics/surface.h" @@ -32,7 +33,9 @@ enum TVMode { TV_DONT_CARE = 0, TV_PAL, - TV_NTSC + TV_NTSC, + TV_HDTV, /* internal */ + TV_VESA /* internal */ }; enum GsInterlace { @@ -42,7 +45,7 @@ enum GsInterlace { class Gs2dScreen { public: - Gs2dScreen(uint16 width, uint16 height, TVMode mode); + Gs2dScreen(uint16 width, uint16 height); ~Gs2dScreen(void); void newScreenSize(uint16 width, uint16 height); // uint8 tvMode(void); @@ -85,8 +88,10 @@ private: void createAnimTextures(void); DmaPipe *_dmaPipe; + uint8 _gfxMode; uint8 _tvMode; uint16 _tvWidth, _tvHeight; + uint16 _tvPitch; GsVertex _blitCoords[2]; TexVertex _texCoords[2]; diff --git a/backends/platform/ps2/GsDefs.h b/backends/platform/ps2/GsDefs.h index 4da08ae301..e5174d3ef7 100644 --- a/backends/platform/ps2/GsDefs.h +++ b/backends/platform/ps2/GsDefs.h @@ -35,6 +35,13 @@ #define GS_DISPLAY1 *((volatile uint64 *)0x12000080) #define GS_BGCOLOUR *((volatile uint64 *)0x120000E0) +#define GS_SMODE1 *((volatile uint64 *)0x12000010) +#define GS_SMODE2 *((volatile uint64 *)0x12000020) +#define GS_SYNCH1 *((volatile uint64 *)0x12000040) +#define GS_SYNCH2 *((volatile uint64 *)0x12000050) +#define GS_SYNCV *((volatile uint64 *)0x12000060) +#define GS_SRFSH *((volatile uint64 *)0x12000030) + enum GS_CSR_FIELDS { CSR_SIGNAL = 1 << 0, CSR_FINISH = 1 << 1, @@ -44,6 +51,19 @@ enum GS_CSR_FIELDS { CSR_RESET = 1 << 9 }; +typedef struct { + u16 w; + u16 h; + u16 interlaced; + u16 pitch; + u16 mode; + u16 vclk; + u16 magh; + u16 magv; + u16 dx; + u16 dy; +} ps2_mode_t; + #define GS_SET_PMODE(readC1, readC2, alphaSel, alphaOut, alphaBlend, alphaFixed) \ ((readC1) | ((readC2) << 1) | ((alphaSel) << 5) | ((alphaOut) << 6) | ((alphaBlend) << 7) | ((alphaFixed) << 8)) @@ -52,6 +72,10 @@ enum GS_CSR_FIELDS { ((((2560 + (width - 1)) / width) - 1)<<23) | \ (ypos << 12) | (xpos * (2560 / width))) +#define GS_SET_DISPLAY_MODE(mode) \ + (((uint64)(mode.h - 1) << 44) | ((uint64)(mode.vclk - 1) << 32) | \ + ((mode.magh - 1) << 23) | (mode.dy << 12) | (mode.dx << 2)) + #define GS_SET_DISPFB(frameBufPtr, frameBufWidth, psm) \ (((frameBufPtr) / 8192) | (((frameBufWidth) / 64) << 9) | ((psm) << 15)) diff --git a/backends/platform/ps2/systemps2.cpp b/backends/platform/ps2/systemps2.cpp index c301ec8d39..ed1c437f01 100644 --- a/backends/platform/ps2/systemps2.cpp +++ b/backends/platform/ps2/systemps2.cpp @@ -323,11 +323,11 @@ OSystem_PS2::OSystem_PS2(const char *elfPath) { _screenChangeCount = 0; _mouseVisible = false; - _screen = new Gs2dScreen(320, 200, TV_DONT_CARE); + // _screen = new Gs2dScreen(320, 200, TV_DONT_CARE); // moved to ::initSize sioprintf("Initializing system...\n"); - _screen->wantAnim(true); + // _screen->wantAnim(true); _bootPath = (char *)malloc(128); _bootDevice = detectBootPath(elfPath, _bootPath); @@ -382,8 +382,8 @@ void OSystem_PS2::init(void) { prepMC(); makeConfigPath(); - _screen->wantAnim(false); - fillScreen(0); + // _screen->wantAnim(false); + // fillScreen(0); } void OSystem_PS2::config(void) { @@ -633,6 +633,8 @@ void OSystem_PS2::initSize(uint width, uint height, const Graphics::PixelFormat /* ugly hack: we know we can parse ScummVM.ini now */ if (!_screenChangeCount) { // first round config(); + _screen = new Gs2dScreen(width, height); + fillScreen(0); } _screen->newScreenSize(width, height); -- cgit v1.2.3