--- hatari/src/falcon/videl.c 2019/04/09 08:57:00 1.1.1.12 +++ hatari/src/falcon/videl.c 2019/04/09 08:59:31 1.1.1.14 @@ -65,8 +65,6 @@ const char VIDEL_fileid[] = "Hatari videl.c : " __DATE__ " " __TIME__; -#include -#include #include "main.h" #include "configuration.h" #include "memorySnapShot.h" @@ -74,20 +72,23 @@ const char VIDEL_fileid[] = "Hatari vide #include "log.h" #include "screen.h" #include "screenConvert.h" +#include "avi_record.h" #include "statusbar.h" #include "stMemory.h" +#include "tos.h" #include "videl.h" -#include "video.h" /* for bUseHighRes variable, maybe unuseful (Laurent) */ -#include "vdi.h" /* for bUseVDIRes variable, maybe unuseful (Laurent) */ +#include "video.h" /* for bUseHighRes variable */ +#include "vdi.h" /* for bUseVDIRes variable */ #define VIDEL_COLOR_REGS_BEGIN 0xff9800 struct videl_s { - bool bUseSTShifter; /* whether to use ST or Falcon palette */ Uint8 reg_ffff8006_save; /* save reg_ffff8006 as it's a read only register */ Uint8 monitor_type; /* 00 Monochrome (SM124) / 01 Color (SC1224) / 10 VGA Color / 11 Television ($FFFF8006) */ - Uint32 videoBaseAddr; /* Video base address, refreshed after each VBL */ + + Uint16 vertFreqCounter; /* Counter for VFC register $ff82a0, restarted on each VBL */ + Uint32 videoRaster; /* Video raster offset, restarted on each VBL */ Sint16 leftBorderSize; /* Size of the left border */ Sint16 rightBorderSize; /* Size of the right border */ @@ -101,11 +102,11 @@ struct videl_s { Uint16 save_scrBpp; /* save screen Bpp to detect a change of bitplan mode */ bool hostColorsSync; /* Sync palette with host's */ + bool bUseSTShifter; /* whether to use ST or Falcon palette */ }; static struct videl_s videl; -Uint16 vfc_counter; /* counter for VFC register $ff82a0 (to be internalized when VIDEL emulation is complete) */ /** * Called upon startup (and via VIDEL_reset()) @@ -133,7 +134,7 @@ void VIDEL_reset(void) videl.reg_ffff8006_save = IoMem_ReadByte(0xff8006); videl.monitor_type = videl.reg_ffff8006_save & 0xc0; - vfc_counter = 0; + VIDEL_RestartVideoCounter(); /* Reset IO register (some are not initialized by TOS) */ IoMem_WriteWord(0xff820e, 0); /* Line offset */ @@ -150,7 +151,6 @@ void VIDEL_MemorySnapShot_Capture(bool b { /* Save/Restore details */ MemorySnapShot_Store(&videl, sizeof(videl)); - MemorySnapShot_Store(&vfc_counter, sizeof(vfc_counter)); } /** @@ -202,10 +202,7 @@ void VIDEL_SyncMode_WriteByte(void) */ void VIDEL_ScreenCounter_ReadByte(void) { -// Uint32 addr; // To be used - Uint32 addr = 0; // To be removed - - // addr = Videl_CalculateAddress(); /* TODO: get current video address */ + Uint32 addr = videl.videoRaster; IoMem[0xff8205] = ( addr >> 16 ) & 0xff; IoMem[0xff8207] = ( addr >> 8 ) & 0xff; IoMem[0xff8209] = addr & 0xff; @@ -218,10 +215,8 @@ void VIDEL_ScreenCounter_ReadByte(void) */ void VIDEL_ScreenCounter_WriteByte(void) { - Uint32 addr_new = 0; - Uint8 AddrByte; - - AddrByte = IoMem[ IoAccessCurrentAddress ]; + Uint32 addr_new = videl.videoRaster; + Uint8 AddrByte = IoMem[ IoAccessCurrentAddress ]; /* Compute the new video address with one modified byte */ if ( IoAccessCurrentAddress == 0xff8205 ) @@ -231,7 +226,19 @@ void VIDEL_ScreenCounter_WriteByte(void) else if ( IoAccessCurrentAddress == 0xff8209 ) addr_new = ( addr_new & 0xffff00 ) | ( AddrByte ); - // TODO: save the value in a table for the final rendering + videl.videoRaster = addr_new; + LOG_TRACE(TRACE_VIDEL, "Videl : $ff8205/07/09 Sync Mode write: 0x%08x\n", addr_new); +} + +/** + * VIDEL_LineOffset_ReadWord: $FFFF820E [R/W] W _______876543210 Line Offset + * How many words are added to the end of display line, i.e. how many words are + * 'behind' the display. + */ +void VIDEL_LineOffset_ReadWord(void) +{ + /* Unused bits in the first byte are read as zero, so mask them */ + IoMem[0xff820e] &= 0x01; } /** @@ -336,6 +343,32 @@ void VIDEL_ST_ShiftModeWriteByte(void) /* Set video mode ($FFFF82C2) */ IoMem_WriteWord(0xff82c2, video_mode); + + /* Hack for Sparrow-TOS (which does not know about Videl registers): */ + if (TosVersion == 0x207) + { + if (st_shiftMode == 2) /* Mono? */ + { + IoMem_WriteWord(0xff82a4, 0); + IoMem_WriteWord(0xff82a6, 0); + IoMem_WriteWord(0xff82a8, 0x43); + IoMem_WriteWord(0xff82aa, 0x363); + } + else if (ConfigureParams.Screen.nMonitorType == MONITOR_TYPE_VGA) + { + IoMem_WriteWord(0xff82a4, 0x3af); + IoMem_WriteWord(0xff82a6, 0x8f); + IoMem_WriteWord(0xff82a8, 0x8f); + IoMem_WriteWord(0xff82aa, 0x3af); + } + else + { + IoMem_WriteWord(0xff82a4, 0x20e); + IoMem_WriteWord(0xff82a6, 0x7e); + IoMem_WriteWord(0xff82a8, 0x7e); + IoMem_WriteWord(0xff82aa, 0x20e); + } + } } /** @@ -481,8 +514,9 @@ void VIDEL_HEE_WriteWord(void) */ void VIDEL_VFC_ReadWord(void) { - IoMem_WriteWord(0xff82a0, vfc_counter); - LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a0 Vertical Frequency Counter (VFC) read: 0x%04x\n", vfc_counter); + IoMem_WriteWord(0xff82a0, videl.vertFreqCounter); + videl.vertFreqCounter++; + LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a0 Vertical Frequency Counter (VFC) read: 0x%04x\n", videl.vertFreqCounter); } /** @@ -573,6 +607,31 @@ static Uint32 VIDEL_getVideoramAddress(v return videoBase; } +/** + * Reset appropriate registers on VBL etc + */ +void VIDEL_RestartVideoCounter(void) +{ + videl.videoRaster = VIDEL_getVideoramAddress(); + /* counter for VFC register $ff82a0 */ + videl.vertFreqCounter = 0; +} + +/** + * Increment appropriate registers on HBL + */ +void VIDEL_VideoRasterHBL(void) +{ + int lineoffset = IoMem_ReadWord(0xff820e) & 0x01ff; /* 9 bits */ + int linewidth = IoMem_ReadWord(0xff8210) & 0x03ff; /* 10 bits */ + + videl.videoRaster += linewidth + lineoffset; + + /* TODO: VFC is incremented every half line, here, we increment it every line */ + videl.vertFreqCounter++; +} + + static Uint16 VIDEL_getScreenBpp(void) { Uint16 f_shift = IoMem_ReadWord(0xff8266); @@ -625,6 +684,13 @@ static int VIDEL_getScreenWidth(void) /* X Size of the Display area */ videl.XSize = (IoMem_ReadWord(0xff8210) & 0x03ff) * 16 / bpp; + /* Sanity check - don't use unsupported texture sizes for SDL2: + * http://answers.unity3d.com/questions/563094/mobile-max-texture-size.html + * (largest currently known real Videl width is ~1600) + */ + while (videl.XSize > 2048) + videl.XSize /= 2; + /* If the user disabled the borders display from the gui, we suppress them */ if (ConfigureParams.Screen.bAllowOverscan == 0) { videl.leftBorderSize = 0; @@ -834,10 +900,27 @@ void VIDEL_UpdateColors(void) } -/* User selected another zoom mode, so set a new screen resolution now */ -void VIDEL_ZoomModeChanged(bool bForceChange) +void Videl_ScreenModeChanged(bool bForceChange) { - int bpp = videl.save_scrBpp == 16 ? 16 : ConfigureParams.Screen.nForceBpp; + int bpp; + + if (ConfigureParams.Screen.nForceBpp) + { + bpp = ConfigureParams.Screen.nForceBpp; + } + else if (Avi_AreWeRecording()) + { + /* Avoid changing the bpp if we are recording */ + bpp = sdlscrn->format->BitsPerPixel; + } + else + { + /* Using SDL's 16 bpp conversion function is a bit faster */ + bpp = (videl.save_scrBpp == 16) ? 16 : 0; + } + + LOG_TRACE(TRACE_VIDEL, "Videl : video mode change to %dx%d@%d\n", + videl.save_scrWidth, videl.save_scrHeight, videl.save_scrBpp); Screen_SetGenConvSize(videl.save_scrWidth, videl.save_scrHeight, bpp, bForceChange); @@ -858,7 +941,7 @@ bool VIDEL_renderScreen(void) bool change = false; - videl.videoBaseAddr = VIDEL_getVideoramAddress(); // Todo: to be removed when all code is in Videl + Uint32 videoBase = VIDEL_getVideoramAddress(); if (vw > 0 && vw != videl.save_scrWidth) { LOG_TRACE(TRACE_VIDEL, "Videl : width change from %d to %d\n", videl.save_scrWidth, vw); @@ -876,8 +959,7 @@ bool VIDEL_renderScreen(void) change = true; } if (change) { - LOG_TRACE(TRACE_VIDEL, "Videl : video mode change to %dx%d@%d\n", videl.save_scrWidth, videl.save_scrHeight, videl.save_scrBpp); - Screen_SetGenConvSize(videl.save_scrWidth, videl.save_scrHeight, videl.save_scrBpp == 16 ? 16 : ConfigureParams.Screen.nForceBpp, false); + Videl_ScreenModeChanged(false); } if (vw < 32 || vh < 32) { @@ -908,7 +990,7 @@ bool VIDEL_renderScreen(void) VIDEL_UpdateColors(); - Screen_GenConvert(&STRam[videl.videoBaseAddr], videl.XSize, videl.YSize, + Screen_GenConvert(&STRam[videoBase], videl.XSize, videl.YSize, videl.save_scrBpp, nextline, hscrolloffset, videl.leftBorderSize, videl.rightBorderSize, videl.upperBorderSize, videl.lowerBorderSize);