--- hatari/src/falcon/videl.c 2019/04/09 08:49:37 1.1.1.6 +++ hatari/src/falcon/videl.c 2019/04/09 08:52:09 1.1.1.8 @@ -33,6 +33,7 @@ $FFFF825E (word) : VDL_STC - ST Palette Register 15 $FFFF8260 (byte) : ST shift mode + $FFFF8264 (byte) : Horizontal scroll register shadow register $FFFF8265 (byte) : Horizontal scroll register $FFFF8266 (word) : Falcon shift mode @@ -74,78 +75,84 @@ const char VIDEL_fileid[] = "Hatari vide #include "hostscreen.h" #include "screen.h" #include "stMemory.h" -#include "video.h" #include "videl.h" -#define handleRead(a) IoMem_ReadByte(a) -#define handleReadW(a) IoMem_ReadWord(a) #define Atari2HostAddr(a) (&STRam[a]) - -#define VIDEL_DEBUG 0 - -#if VIDEL_DEBUG -#define Dprintf(a) printf a -#else -#define Dprintf(a) -#endif - -#define HW 0xff8200 #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 */ -static struct videl_s videl; - -/* TODO: put these to some struct so that it's easier to see - * they're VIDEL global - */ -static int width, height, bpp; -static bool hostColorsSync; + Sint16 leftBorderSize; /* Size of the left border */ + Sint16 rightBorderSize; /* Size of the right border */ + Sint16 upperBorderSize; /* Size of the upper border */ + Sint16 lowerBorderSize; /* Size of the lower border */ + Uint16 XSize; /* X size of the graphical area */ + Uint16 YSize; /* Y size of the graphical area */ + + Uint16 save_scrWidth; /* save screen width to detect a change of X resolution */ + Uint16 save_scrHeight; /* save screen height to detect a change of Y resolution */ + Uint16 save_scrBpp; /* save screen Bpp to detect a change of bitplan mode */ -Uint16 vfc_counter; /* counter for VFC register $ff82a0 (to be internalized when VIDEL emulation is complete) */ + bool hostColorsSync; /* Sync palette with host's */ +}; -/* Autozoom */ -static int zoomwidth, prev_scrwidth; -static int zoomheight, prev_scrheight; -static int *zoomxtable; -static int *zoomytable; +struct videl_zoom_s { + Uint16 zoomwidth; + Uint16 prev_scrwidth; + Uint16 zoomheight; + Uint16 prev_scrheight; + int *zoomxtable; + int *zoomytable; +}; +static struct videl_s videl; +static struct videl_zoom_s videl_zoom; +Uint16 vfc_counter; /* counter for VFC register $ff82a0 (to be internalized when VIDEL emulation is complete) */ -static void VIDEL_renderScreenNoZoom(void); -static void VIDEL_renderScreenZoom(void); +static void VIDEL_memset_uint32(Uint32 *addr, Uint32 color, int count); +static void VIDEL_memset_uint16(Uint16 *addr, Uint16 color, int count); +static void VIDEL_memset_uint8(Uint8 *addr, Uint8 color, int count); - -// Called upon startup and when CPU encounters a RESET instruction. +/** + * Called upon startup and when CPU encounters a RESET instruction. + */ void VIDEL_reset(void) { videl.bUseSTShifter = false; /* Use Falcon color palette by default */ videl.reg_ffff8006_save = IoMem_ReadByte(0xff8006); - videl.monitor_type = videl.reg_ffff8006_save & 0xc0; + videl.monitor_type = videl.reg_ffff8006_save & 0xc0; - hostColorsSync = false; + videl.hostColorsSync = false; vfc_counter = 0; /* Autozoom */ - zoomwidth=prev_scrwidth=0; - zoomheight=prev_scrheight=0; - zoomxtable=NULL; - zoomytable=NULL; + videl_zoom.zoomwidth = 0; + videl_zoom.prev_scrwidth = 0; + videl_zoom.zoomheight = 0; + videl_zoom.prev_scrheight = 0; + videl_zoom.zoomxtable = NULL; + videl_zoom.zoomytable = NULL; /* Default resolution to boot with */ - width = 640; - height = 480; - HostScreen_setWindowSize(width, height, ConfigureParams.Screen.nForceBpp); + videl.save_scrWidth = 640; + videl.save_scrHeight = 480; + videl.save_scrBpp = ConfigureParams.Screen.nForceBpp; + HostScreen_setWindowSize(videl.save_scrWidth, videl.save_scrHeight, videl.save_scrBpp); /* Reset IO register (some are not initialized by TOS) */ IoMem_WriteWord(0xff820e, 0); /* Line offset */ IoMem_WriteWord(0xff8264, 0); /* Horizontal scroll */ + + /* Init synch mode register */ + VIDEL_SyncMode_WriteByte(); } /** @@ -155,6 +162,7 @@ void VIDEL_MemorySnapShot_Capture(bool b { /* Save/Restore details */ MemorySnapShot_Store(&videl, sizeof(videl)); + MemorySnapShot_Store(&videl_zoom, sizeof(videl_zoom)); MemorySnapShot_Store(&vfc_counter, sizeof(vfc_counter)); } @@ -163,21 +171,104 @@ void VIDEL_MemorySnapShot_Capture(bool b */ void VIDEL_ColorRegsWrite(void) { - hostColorsSync = false; + videl.hostColorsSync = false; } /** * VIDEL_Monitor_WriteByte : Contains memory and monitor configuration. - * This register is read only. + * This register is read only. */ void VIDEL_Monitor_WriteByte(void) { - LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8006 Monitor and memory conf write (Read only)\n"); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff8006 Monitor and memory conf write (Read only)\n"); /* Restore hardware value */ + IoMem_WriteByte(0xff8006, videl.reg_ffff8006_save); } /** + * VIDEL_SyncMode_WriteByte : Videl synchronization mode. + * $FFFF820A [R/W] _______0 .................................. SYNC-MODE + || + |+--Synchronisation [ 0:internal / 1:external ] + +---Vertical frequency [ Read-only bit ] + [ Monochrome monitor:0 / Colour monitor:1 ] + */ +void VIDEL_SyncMode_WriteByte(void) +{ + Uint8 syncMode = IoMem_ReadByte(0xff820a); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff820a Sync Mode write: 0x%02x\n", syncMode); + + if (videl.monitor_type == FALCON_MONITOR_MONO) + syncMode &= 0xfd; + else + syncMode |= 0x2; + + IoMem_WriteByte(0xff820a, syncMode); +} + +/** + * Read video address counter and update ff8205/07/09 + */ +void VIDEL_ScreenCounter_ReadByte(void) +{ +// Uint32 addr; // To be used + Uint32 addr = 0; // To be removed + + // addr = Videl_CalculateAddress(); /* TODO: get current video address */ + IoMem[0xff8205] = ( addr >> 16 ) & 0xff; + IoMem[0xff8207] = ( addr >> 8 ) & 0xff; + IoMem[0xff8209] = addr & 0xff; + + LOG_TRACE(TRACE_VIDEL, "Videl : $ff8205/07/09 Sync Mode read: 0x%08x\n", addr); +} + +/** + * Write video address counter + */ +void VIDEL_ScreenCounter_WriteByte(void) +{ + Uint32 addr_new = 0; + Uint8 AddrByte; + + AddrByte = IoMem[ IoAccessCurrentAddress ]; + + /* Compute the new video address with one modified byte */ + if ( IoAccessCurrentAddress == 0xff8205 ) + addr_new = ( addr_new & 0x00ffff ) | ( AddrByte << 16 ); + else if ( IoAccessCurrentAddress == 0xff8207 ) + addr_new = ( addr_new & 0xff00ff ) | ( AddrByte << 8 ); + else if ( IoAccessCurrentAddress == 0xff8209 ) + addr_new = ( addr_new & 0xffff00 ) | ( AddrByte ); + + // TODO: save the value in a table for the final rendering +} + +/** + * VIDEL_LineOffset_WriteWord: $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_WriteWord(void) +{ + Uint16 lineOffset = IoMem_ReadWord(0xff820e); + + LOG_TRACE(TRACE_VIDEL, "Videl : $ff820e Line Offset write: 0x%04x\n", lineOffset); +} + +/** + * VIDEL_Line_Width_WriteWord: $FFFF8210 [R/W] W ______9876543210 Line Width (VWRAP) + * Length of display line in words.Or, how many words should be added to + * vram counter after every display line. + */ +void VIDEL_Line_Width_WriteWord(void) +{ + Uint16 lineWidth = IoMem_ReadWord(0xff8210); + + LOG_TRACE(TRACE_VIDEL, "Videl : $ff8210 Line Width write: 0x%04x\n", lineWidth); +} + +/** * Write to video address base high, med and low register (0xff8201/03/0d). * On Falcon, when a program writes to high or med registers, base low register * is reset to zero. @@ -193,7 +284,7 @@ void VIDEL_ScreenBase_WriteByte(void) screenBase = (IoMem[0xff8201]<<16)+(IoMem[0xff8203]<<8)+IoMem[0xff820d]; - LOG_TRACE(TRACE_VIDEL, "Videl : $%04x Screen base write: 0x%01x\t (screen: 0x%04x)\n", + LOG_TRACE(TRACE_VIDEL, "Videl : $%04x Screen base write: 0x%02x\t (screen: 0x%04x)\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress], screenBase); } @@ -219,7 +310,10 @@ void VIDEL_ST_ShiftModeWriteByte(void) Uint8 st_shiftMode; st_shiftMode = IoMem_ReadByte(0xff8260); - LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8260 ST Shift Mode (STSHIFT) write: 0x%x\n", st_shiftMode); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff8260 ST Shift Mode (STSHIFT) write: 0x%02x\n", st_shiftMode); + + /* Bits 2-7 are set to 0 */ + IoMem_WriteByte(0xff8260, st_shiftMode & 3); /* Activate STE palette */ videl.bUseSTShifter = true; @@ -246,6 +340,7 @@ void VIDEL_ST_ShiftModeWriteByte(void) video_mode = videl.monitor_type == FALCON_MONITOR_VGA ? 0x8 : 0x6; break; case 3: /* ???/320 Pixels */ + default: line_width = 0x50; video_mode = 0x0; break; @@ -259,22 +354,42 @@ void VIDEL_ST_ShiftModeWriteByte(void) } /** - VIDEL_FALCON_ShiftModeWriteWord : + VIDEL_HorScroll64_WriteByte : Horizontal scroll register (0-15) + $FFFF8264 [R/W] ________ ................................ H-SCROLL HI + |||| [ Shadow register for $FFFF8265 ] + ++++--Pixel shift [ 0:normal / 1..15:Left shift ] + [ Change in line-width NOT required ] + */ +void VIDEL_HorScroll64_WriteByte(void) +{ + Uint8 horScroll64 = IoMem_ReadWord(0xff8264); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff8264 Horizontal scroll 64 write: 0x%02x\n", horScroll64); +} + +/** + VIDEL_HorScroll65_WriteByte : Horizontal scroll register (0-15) + $FFFF8265 [R/W] ____3210 .................................H-SCROLL LO + |||| + ++++--Pixel [ 0:normal / 1..15:Left shift ] + [ Change in line-width NOT required ] + */ +void VIDEL_HorScroll65_WriteByte(void) +{ + Uint8 horScroll65 = IoMem_ReadWord(0xff8265); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff8265 Horizontal scroll 65 write: 0x%02x\n", horScroll65); +} + +/** + VIDEL_Falcon_ShiftMode_WriteWord : $FFFF8266 [R/W] W _____A98_6543210 Falcon Shift Mode (SPSHIFT) ||| ||||||| - ||| |||++++- 0..15: Colourbank setting in 8BP - ||| ||+----- 0: 8 Bitplanes (256 Colors) off - ||| ||+----- 1: 8 Bitplanes (256 Colors) on - ||| |+------ 0: internal Vertical Sync - ||| | 1: external Vertical Sync - ||| +------- 0: internal Horizontal Sync - ||| 1: external Horizontal Sync - ||+--------- 0: True-Color-Mode off - || 1: True-Color-Mode on - |+---------- 0: Overlay-Mode off - | 1: Overlay-Mode on - +----------- 0: 2-Color-Mode off - 1: 2-Color-Mode on + ||| |||++++- 0..15: Colourbank choice from 256-colour table in 16 colour multiples + ||| ||+----- 8 Bitplanes mode (256 Colors) [0:off / 1:on] + ||| |+------ Vertical Sync [0: internal / 1: external] + ||| +------- Horizontal Sync [0: internal / 1: external] + ||+--------- True-Color-Mode [0:off / 1:on] + |+---------- Overlay-Mode [0:off / 1:on] + +----------- 0: 2-Color-Mode [0:off / 1:on] Writing to this register does the following things: - activate Falcon palette @@ -284,11 +399,11 @@ void VIDEL_ST_ShiftModeWriteByte(void) Note: 4-Color-Mode isn't realisable with Falcon palette. */ -void VIDEL_FALC_ShiftModeWriteWord(void) +void VIDEL_Falcon_ShiftMode_WriteWord(void) { Uint16 falc_shiftMode = IoMem_ReadWord(0xff8266); - LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8266 Falcon Shift Mode (SPSHIFT) write: 0x%02x\n", falc_shiftMode); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff8266 Falcon Shift Mode (SPSHIFT) write: 0x%04x\n", falc_shiftMode); videl.bUseSTShifter = false; } @@ -300,7 +415,7 @@ void VIDEL_HHC_WriteWord(void) { Uint16 hhc = IoMem_ReadWord(0xff8280); - LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8280 Horizontal Hold Counter (HHC) write: 0x%02x\n", hhc); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff8280 Horizontal Hold Counter (HHC) write: 0x%04x\n", hhc); } /** @@ -310,7 +425,7 @@ void VIDEL_HHT_WriteWord(void) { Uint16 hht = IoMem_ReadWord(0xff8282); - LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8282 Horizontal Hold Timer (HHT) write: 0x%02x\n", hht); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff8282 Horizontal Hold Timer (HHT) write: 0x%04x\n", hht); } /** @@ -320,7 +435,7 @@ void VIDEL_HBB_WriteWord(void) { Uint16 hbb = IoMem_ReadWord(0xff8284); - LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8284 Horizontal Border Begin (HBB) write: 0x%02x\n", hbb); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff8284 Horizontal Border Begin (HBB) write: 0x%04x\n", hbb); } /** @@ -330,17 +445,20 @@ void VIDEL_HBE_WriteWord(void) { Uint16 hbe = IoMem_ReadWord(0xff8286); - LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8286 Horizontal Border End (HBE) write: 0x%02x\n", hbe); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff8286 Horizontal Border End (HBE) write: 0x%04x\n", hbe); } /** * Write Horizontal Display Begin (HDB) + $FFFF8288 [R/W] W ______9876543210 Horizontal Display Begin (HDB) + | + +---------- Display will start in [0: 1st halfline / 1: 2nd halfline] */ void VIDEL_HDB_WriteWord(void) { Uint16 hdb = IoMem_ReadWord(0xff8288); - LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8288 Horizontal Display Begin (HDB) write: 0x%02x\n", hdb); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff8288 Horizontal Display Begin (HDB) write: 0x%04x\n", hdb); } /** @@ -350,7 +468,7 @@ void VIDEL_HDE_WriteWord(void) { Uint16 hde = IoMem_ReadWord(0xff828a); - LOG_TRACE(TRACE_VIDEL, "Videl : $ffff828a Horizontal Display End (HDE) write: 0x%02x\n", hde); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff828a Horizontal Display End (HDE) write: 0x%04x\n", hde); } /** @@ -360,7 +478,7 @@ void VIDEL_HSS_WriteWord(void) { Uint16 hss = IoMem_ReadWord(0xff828c); - LOG_TRACE(TRACE_VIDEL, "Videl : $ffff828c Horizontal SS (HSS) write: 0x%02x\n", hss); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff828c Horizontal SS (HSS) write: 0x%04x\n", hss); } /** @@ -370,7 +488,7 @@ void VIDEL_HFS_WriteWord(void) { Uint16 hfs = IoMem_ReadWord(0xff828e); - LOG_TRACE(TRACE_VIDEL, "Videl : $ffff828e Horizontal FS (HFS) write: 0x%02x\n", hfs); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff828e Horizontal FS (HFS) write: 0x%04x\n", hfs); } /** @@ -380,7 +498,7 @@ void VIDEL_HEE_WriteWord(void) { Uint16 hee = IoMem_ReadWord(0xff8290); - LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8290 Horizontal EE (HEE) write: 0x%02x\n", hee); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff8290 Horizontal EE (HEE) write: 0x%04x\n", hee); } /** @@ -389,7 +507,7 @@ void VIDEL_HEE_WriteWord(void) void VIDEL_VFC_ReadWord(void) { IoMem_WriteWord(0xff82a0, vfc_counter); - LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82a0 Vertical Frequency Counter (VFC) read: 0x%02x\n", vfc_counter); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a0 Vertical Frequency Counter (VFC) read: 0x%04x\n", vfc_counter); } /** @@ -399,7 +517,7 @@ void VIDEL_VFT_WriteWord(void) { Uint16 vft = IoMem_ReadWord(0xff82a2); - LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82a2 Vertical Frequency Timer (VFT) write: 0x%02x\n", vft); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a2 Vertical Frequency Timer (VFT) write: 0x%04x\n", vft); } /** @@ -409,7 +527,7 @@ void VIDEL_VBB_WriteWord(void) { Uint16 vbb = IoMem_ReadWord(0xff82a4); - LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82a4 Vertical Border Begin (VBB) write: 0x%02x\n", vbb); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a4 Vertical Border Begin (VBB) write: 0x%04x\n", vbb); } /** @@ -419,7 +537,7 @@ void VIDEL_VBE_WriteWord(void) { Uint16 vbe = IoMem_ReadWord(0xff82a6); - LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82a6 Vertical Border End (VBE) write: 0x%02x\n", vbe); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a6 Vertical Border End (VBE) write: 0x%04x\n", vbe); } /** @@ -429,7 +547,7 @@ void VIDEL_VDB_WriteWord(void) { Uint16 vdb = IoMem_ReadWord(0xff82a8); - LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82a8 Vertical Display Begin (VDB) write: 0x%02x\n", vdb); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a8 Vertical Display Begin (VDB) write: 0x%04x\n", vdb); } /** @@ -439,7 +557,7 @@ void VIDEL_VDE_WriteWord(void) { Uint16 vde = IoMem_ReadWord(0xff82aa); - LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82aa Vertical Display End (VDE) write: 0x%02x\n", vde); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff82aa Vertical Display End (VDE) write: 0x%04x\n", vde); } /** @@ -449,7 +567,7 @@ void VIDEL_VSS_WriteWord(void) { Uint16 vss = IoMem_ReadWord(0xff82ac); - LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82ac Vertical SS (VSS) write: 0x%02x\n", vss); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff82ac Vertical SS (VSS) write: 0x%04x\n", vss); } /** @@ -459,7 +577,7 @@ void VIDEL_VCO_WriteWord(void) { Uint16 vco = IoMem_ReadWord(0xff82c0); - LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82c0 Video control (VCO) write: 0x%02x\n", vco); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff82c0 Video control (VCO) write: 0x%04x\n", vco); } /** @@ -469,28 +587,39 @@ void VIDEL_VMD_WriteWord(void) { Uint16 vdm = IoMem_ReadWord(0xff82c2); - LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82c2 Video Mode (VDM) write: 0x%02x\n", vdm); + LOG_TRACE(TRACE_VIDEL, "Videl : $ff82c2 Video Mode (VDM) write: 0x%04x\n", vdm); } -static long VIDEL_getVideoramAddress(void) +/** + * VIDEL_getVideoramAddress: returns the video RAM address. + * On Falcon, video address must be a multiple of four in bitplane modes. + */ +static Uint32 VIDEL_getVideoramAddress(void) { - return (handleRead(HW + 1) << 16) | (handleRead(HW + 3) << 8) | handleRead(HW + 0x0d); + Uint32 videoBase; + + videoBase = (Uint32) IoMem_ReadByte(0xff8201) << 16; + videoBase |= (Uint32) IoMem_ReadByte(0xff8203) << 8; + videoBase |= IoMem_ReadByte(0xff820d) & ~3; + + return videoBase; } -static int VIDEL_getScreenBpp(void) +static Uint16 VIDEL_getScreenBpp(void) { - int f_shift = handleReadW(HW + 0x66); - int st_shift = handleRead(HW + 0x60); + Uint16 f_shift = IoMem_ReadWord(0xff8266); + Uint16 bits_per_pixel; + Uint8 st_shift = IoMem_ReadByte(0xff8260); + /* to get bpp, we must examine f_shift and st_shift. - * f_shift is valid if any of bits no. 10, 8 or 4 - * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e. + * f_shift is valid if any of bits no. 10, 8 or 4 is set. + * Priority in f_shift is: 10 ">" 8 ">" 4, i.e. * if bit 10 set then bit 8 and bit 4 don't care... * If all these bits are 0 and ST shifter is written * after Falcon one, get display depth from st_shift * (as for ST and STE) */ - int bits_per_pixel; if (f_shift & 0x400) /* Falcon: 2 colors */ bits_per_pixel = 1; else if (f_shift & 0x100) /* Falcon: hicolor */ @@ -506,34 +635,172 @@ static int VIDEL_getScreenBpp(void) else /* if (st_shift == 0x02) */ bits_per_pixel = 1; - // Dprintf(("Videl works in %d bpp, f_shift=%04x, st_shift=%d", bits_per_pixel, f_shift, st_shift)); +/* LOG_TRACE(TRACE_VIDEL, "Videl works in %d bpp, f_shift=%04x, st_shift=%d", bits_per_pixel, f_shift, st_shift); */ return bits_per_pixel; } +/** + * VIDEL_getScreenWidth : returns the visible X resolution + * left border + graphic area + right border + * left border : hdb - hbe-offset + * right border : hbb - hde-offset + * Graphics display : starts at cycle HDB and ends at cycle HDE. + */ static int VIDEL_getScreenWidth(void) { - return (handleReadW(HW + 0x10) & 0x03ff) * 16 / VIDEL_getScreenBpp(); + Uint16 bpp = VIDEL_getScreenBpp(); + + /* X Size of the Display area */ + videl.XSize = (IoMem_ReadWord(0xff8210) & 0x03ff) * 16 / bpp; + + /* If the user disabled the borders display from the gui, we suppress them */ + if (ConfigureParams.Screen.bAllowOverscan == 0) { + videl.leftBorderSize = 0; + videl.rightBorderSize = 0; + return videl.XSize; + } + + /* According to Aura and Animal Mine doc about Videl, if a monochrome monitor is connected, + * HDB and HDE have no significance and no border is displayed. + */ + if (videl.monitor_type == FALCON_MONITOR_MONO) { + videl.leftBorderSize = 0; + videl.rightBorderSize = 0; + return videl.XSize; + } + + Uint16 hbb = IoMem_ReadWord(0xff8284) & 0x01ff; + Uint16 hbe = IoMem_ReadWord(0xff8286) & 0x01ff; + Uint16 hdb = IoMem_ReadWord(0xff8288) & 0x01ff; + Uint16 hde = IoMem_ReadWord(0xff828a) & 0x01ff; + Uint16 vdm = IoMem_ReadWord(0xff82c2) & 0xc; + Uint16 hht = IoMem_ReadWord(0xff8282) & 0x1ff; + + Uint16 cycPerPixel, divider; + Sint16 hdb_offset, hde_offset; + Sint16 leftBorder, rightBorder; + + /* Compute cycles per pixel */ + if (vdm == 0) + cycPerPixel = 4; + else if (vdm == 4) + cycPerPixel = 2; + else + cycPerPixel = 1; + + /* Compute the divider */ + if (videl.monitor_type == FALCON_MONITOR_VGA) { + if (cycPerPixel == 4) + divider = 4; + else + divider = 2; + } + else if (videl.bUseSTShifter == true) { + divider = 16; + } + else { + divider = cycPerPixel; + } + + /* Compute hdb_offset and hde_offset */ + if (videl.bUseSTShifter == false) { + if (bpp < 16) { + /* falcon mode bpp */ + hdb_offset = ((64+(128/bpp + 16 + 2) * cycPerPixel) / divider ) + 1; + hde_offset = ((128/bpp + 2) * cycPerPixel) / divider; + } + else { + /* falcon mode true color */ + hdb_offset = ((64 + 16 * cycPerPixel) / divider ) + 1; + hde_offset = 0; + } + } + else { + /* ST bitplan mode */ + hdb_offset = ((128+(128/bpp + 2) * cycPerPixel) / divider ) + 1; + hde_offset = ((128/bpp + 2) * cycPerPixel) / divider; + } + + LOG_TRACE(TRACE_VIDEL, "hdb_offset=%04x, hde_offset=%04x\n", hdb_offset, hde_offset); + + /* Compute left border size in cycles */ + if (IoMem_ReadWord(0xff8288) & 0x0200) + leftBorder = hdb - hbe + hdb_offset - hht - 2; + else + leftBorder = hdb - hbe + hdb_offset; + + /* Compute right border size in cycles */ + rightBorder = hbb - hde_offset - hde; + + videl.leftBorderSize = leftBorder / cycPerPixel; + videl.rightBorderSize = rightBorder / cycPerPixel; + LOG_TRACE(TRACE_VIDEL, "left border size=%04x, right border size=%04x\n", videl.leftBorderSize, videl.rightBorderSize); + + if (videl.leftBorderSize < 0) { +// fprintf(stderr, "BORDER LEFT < 0 %d\n", videl.leftBorderSize); + videl.leftBorderSize = 0; + } + if (videl.rightBorderSize < 0) { +// fprintf(stderr, "BORDER RIGHT < 0 %d\n", videl.rightBorderSize); + videl.rightBorderSize = 0; + } + + return videl.leftBorderSize + videl.XSize + videl.rightBorderSize; } +/** + * VIDEL_getScreenHeight : returns the visible Y resolution + * upper border + graphic area + lower border + * upper border : vdb - vbe + * lower border : vbb - vde + * Graphics display : starts at line VDB and ends at line VDE. + * If interlace mode off unit of VC-registers is half lines, else lines. + */ static int VIDEL_getScreenHeight(void) { - int vdb = handleReadW(HW + 0xa8) & 0x07ff; - int vde = handleReadW(HW + 0xaa) & 0x07ff; - int vmode = handleReadW(HW + 0xc2); - - /* visible y resolution: - * Graphics display starts at line VDB and ends at line - * VDE. If interlace mode off unit of VC-registers is - * half lines, else lines. + Uint16 vbb = IoMem_ReadWord(0xff82a4) & 0x07ff; + Uint16 vbe = IoMem_ReadWord(0xff82a6) & 0x07ff; + Uint16 vdb = IoMem_ReadWord(0xff82a8) & 0x07ff; + Uint16 vde = IoMem_ReadWord(0xff82aa) & 0x07ff; + Uint16 vmode = IoMem_ReadWord(0xff82c2); + + /* According to Aura and Animal Mine doc about Videl, if a monochrome monitor is connected, + * VDB and VDE have no significance and no border is displayed. */ - int yres = vde - vdb; - if (!(vmode & 0x02)) // interlace - yres >>= 1; - if (vmode & 0x01) // double - yres >>= 1; + if (videl.monitor_type == FALCON_MONITOR_MONO) { + videl.upperBorderSize = 0; + videl.lowerBorderSize = 0; + } + else { + /* We must take the positive value only, as a program like AceTracker starts the */ + /* graphical area 1 line before the end of the upper border */ + videl.upperBorderSize = vdb - vbe > 0 ? vdb - vbe : 0; + videl.lowerBorderSize = vbb - vde > 0 ? vbb - vde : 0; + } - return yres; + /* Y Size of the Display area */ + videl.YSize = vde - vdb; + + /* If the user disabled the borders display from the gui, we suppress them */ + if (ConfigureParams.Screen.bAllowOverscan == 0) { + videl.upperBorderSize = 0; + videl.lowerBorderSize = 0; + } + + if (!(vmode & 0x02)){ /* interlace */ + videl.YSize >>= 1; + videl.upperBorderSize >>= 1; + videl.lowerBorderSize >>= 1; + } + + if (vmode & 0x01) { /* double */ + videl.YSize >>= 1; + videl.upperBorderSize >>= 1; + videl.lowerBorderSize >>= 1; + } + + return videl.upperBorderSize + videl.YSize + videl.lowerBorderSize; } #if 0 @@ -559,29 +826,29 @@ static void VIDEL_getMonitorScale(int *s * 1 0 0 0 640x480 -> 1 x 1 * 1 0 0 1 640x240 -> 1 x 2 */ - int vmode = handleReadW(HW + 0xc2); + int vmode = IoMem_ReadWord(0xff82c2); /* half pixel seems to have opposite meaning on * VGA and RGB monitor, so they need to handled separately */ if (videl.monitor_type) == FALCON_MONITOR_VGA) { - if (vmode & 0x08) { // quarter pixel + if (vmode & 0x08) { /* quarter pixel */ *sx = 1; } else { *sx = 2; } - if (vmode & 0x01) { // double line + if (vmode & 0x01) { /* double line */ *sy = 2; } else { *sy = 1; } } else { - if (vmode & 0x04) { // half pixel + if (vmode & 0x04) { /* half pixel */ *sx = 1; } else { *sx = 2; } - if (vmode & 0x02) { // interlace used only on RGB? + if (vmode & 0x02) { /* interlace used only on RGB ? */ *sy = 1; } else { *sy = 2; @@ -595,12 +862,10 @@ static void VIDEL_getMonitorScale(int *s */ static void VIDEL_updateColors(void) { - //Dprintf(("ColorUpdate in progress\n")); - - int i, r, g, b, colors = 1 << bpp; + int i, r, g, b, colors = 1 << videl.save_scrBpp; -#define F_COLORS(i) handleRead(VIDEL_COLOR_REGS_BEGIN + (i)) -#define STE_COLORS(i) handleRead(0xff8240 + (i)) +#define F_COLORS(i) IoMem_ReadByte(VIDEL_COLOR_REGS_BEGIN + (i)) +#define STE_COLORS(i) IoMem_ReadByte(0xff8240 + (i)) if (!videl.bUseSTShifter) { for (i = 0; i < colors; i++) { @@ -631,55 +896,86 @@ static void VIDEL_updateColors(void) HostScreen_updatePalette(colors); } - hostColorsSync = true; + videl.hostColorsSync = true; } void VIDEL_ZoomModeChanged(void) { /* User selected another zoom mode, so set a new screen resolution now */ - HostScreen_setWindowSize(width, height, bpp == 16 ? 16 : ConfigureParams.Screen.nForceBpp); + HostScreen_setWindowSize(videl.save_scrWidth, videl.save_scrHeight, videl.save_scrBpp == 16 ? 16 : ConfigureParams.Screen.nForceBpp); } bool VIDEL_renderScreen(void) { + videl.videoBaseAddr = VIDEL_getVideoramAddress(); // Todo: to be removed when all code is in Videl + + /* Atari screen infos */ int vw = VIDEL_getScreenWidth(); int vh = VIDEL_getScreenHeight(); int vbpp = VIDEL_getScreenBpp(); + + int lineoffset = IoMem_ReadWord(0xff820e) & 0x01ff; /* 9 bits */ + int linewidth = IoMem_ReadWord(0xff8210) & 0x03ff; /* 10 bits */ + bool change = false; - if (vw > 0 && vw != width) { - Dprintf(("CH width %d\n", width)); - width = vw; + if (vw > 0 && vw != videl.save_scrWidth) { + LOG_TRACE(TRACE_VIDEL, "Videl : width change from %d to %d\n", videl.save_scrWidth, vw); + videl.save_scrWidth = vw; change = true; } - if (vh > 0 && vh != height) { - Dprintf(("CH height %d\n", width)); - height = vh; + if (vh > 0 && vh != videl.save_scrHeight) { + LOG_TRACE(TRACE_VIDEL, "Videl : height change from %d to %d\n", videl.save_scrHeight, vh); + videl.save_scrHeight = vh; change = true; } - if (vbpp != bpp) { - Dprintf(("CH bpp %d\n", vbpp)); - bpp = vbpp; + if (vbpp != videl.save_scrBpp) { + LOG_TRACE(TRACE_VIDEL, "Videl : bpp change from %d to %d\n", videl.save_scrBpp, vbpp); + videl.save_scrBpp = vbpp; change = true; } if (change) { - LOG_TRACE(TRACE_VIDEL, "Videl : video mode change to %dx%d@%d\n", width, height, bpp); - HostScreen_setWindowSize(width, height, bpp == 16 ? 16 : ConfigureParams.Screen.nForceBpp); + LOG_TRACE(TRACE_VIDEL, "Videl : video mode change to %dx%d@%d\n", videl.save_scrWidth, videl.save_scrHeight, videl.save_scrBpp); + HostScreen_setWindowSize(videl.save_scrWidth, videl.save_scrHeight, videl.save_scrBpp == 16 ? 16 : ConfigureParams.Screen.nForceBpp); } if (!HostScreen_renderBegin()) return false; + /* + I think this implementation is naive: + indeed, I suspect that we should instead skip lineoffset + words each time we have read "more" than linewidth words + (possibly "more" because of the number of bit planes). + Moreover, the 1 bit plane mode is particular; + while doing some experiments on my Falcon, it seems to + behave like the 4 bit planes mode. + At last, we have also to take into account the 4 bits register + located at the word $ffff8264 (bit offset). This register makes + the semantics of the lineoffset register change a little. + int bitoffset = IoMem_ReadWord(0xff8264) & 0x000f; + The meaning of this register in True Color mode is not clear + for me at the moment (and my experiments on the Falcon don't help + me). + */ + int nextline = linewidth + lineoffset; + + if ((vw<32) || (vh<32)) + return false; + + if (videl.save_scrBpp < 16 && videl.hostColorsSync == 0) + VIDEL_updateColors(); + if (nScreenZoomX * nScreenZoomY != 1) { - VIDEL_renderScreenZoom(); + VIDEL_ConvertScreenZoom(vw, vh, videl.save_scrBpp, nextline); } else { - VIDEL_renderScreenNoZoom(); + VIDEL_ConvertScreenNoZoom(vw, vh, videl.save_scrBpp, nextline); } - HostScreen_renderEnd(); + HostScreen_renderEnd(); HostScreen_update1(false); return true; @@ -690,7 +986,7 @@ bool VIDEL_renderScreen(void) * Performs conversion from the TOS's bitplane word order (big endian) data * into the native chunky color index. */ -static void Videl_bitplaneToChunky(Uint16 *atariBitplaneData, Uint16 bpp, +static void VIDEL_bitplaneToChunky(Uint16 *atariBitplaneData, Uint16 bpp, Uint8 colorValues[16]) { Uint32 a, b, c, d, x; @@ -817,51 +1113,33 @@ static void Videl_bitplaneToChunky(Uint1 #endif } - -static void VIDEL_renderScreenNoZoom(void) -{ - int vw = VIDEL_getScreenWidth(); - int vh = VIDEL_getScreenHeight(); - - int lineoffset = handleReadW(HW + 0x0e) & 0x01ff; // 9 bits - int linewidth = handleReadW(HW + 0x10) & 0x03ff; // 10 bits - /* - I think this implementation is naive: - indeed, I suspect that we should instead skip lineoffset - words each time we have read "more" than linewidth words - (possibly "more" because of the number of bit planes). - Moreover, the 1 bit plane mode is particular; - while doing some experiments on my Falcon, it seems to - behave like the 4 bit planes mode. - At last, we have also to take into account the 4 bits register - located at the word $ffff8264 (bit offset). This register makes - the semantics of the lineoffset register change a little. - int bitoffset = handleReadW(HW + 0x64) & 0x000f; - The meaning of this register in True Color mode is not clear - for me at the moment (and my experiments on the Falcon don't help - me). - */ - int nextline = linewidth + lineoffset; - - if (bpp < 16 && !hostColorsSync) { - VIDEL_updateColors(); - } - - VIDEL_ConvertScreenNoZoom(vw, vh, bpp, nextline); -} - - void VIDEL_ConvertScreenNoZoom(int vw, int vh, int vbpp, int nextline) { int scrpitch = HostScreen_getPitch(); + int h, w, j; - long atariVideoRAM = VIDEL_getVideoramAddress(); - - Uint16 *fvram = (Uint16 *) Atari2HostAddr(atariVideoRAM); + Uint16 *fvram = (Uint16 *) Atari2HostAddr(videl.videoBaseAddr); Uint8 *hvram = HostScreen_getVideoramAddress(); SDL_PixelFormat *scrfmt = HostScreen_getFormat(); - int hscrolloffset = (handleRead(HW + 0x65) & 0x0f); + Uint16 lowBorderSize, rightBorderSize; + + int hscrolloffset = IoMem_ReadByte(0xff8265) & 0x0f; + + /* Horizontal scroll register set? */ + if (hscrolloffset) { + /* Yes, so we need to adjust offset to next line: */ + nextline += vbpp; + } + + /* If emulated computer is the TT, we use the same rendering for display, but without the borders */ + if (ConfigureParams.System.nMachineType == MACHINE_TT) { + videl.leftBorderSize = 0; + videl.rightBorderSize = 0; + videl.upperBorderSize = 0; + videl.lowerBorderSize = 0; + fvram = (Uint16 *) Atari2HostAddr(VIDEL_getVideoramAddress()); + } /* Clip to SDL_Surface dimensions */ int scrwidth = HostScreen_getWidth(); @@ -871,247 +1149,350 @@ void VIDEL_ConvertScreenNoZoom(int vw, i if (vw>scrwidth) vw_clip = scrwidth; if (vh>scrheight) vh_clip = scrheight; - /* Horizontal scroll register set? */ - if (hscrolloffset) { - /* Yes, so we need to adjust offset to next line: */ - nextline += vbpp; + /* If emulated computer is the FALCON, we must take : + * vw = X area display size and not all the X screen with the borders into account + * vh = Y area display size and not all the Y screen with the borders into account + */ + if (ConfigureParams.System.nMachineType == MACHINE_FALCON) { + vw = videl.XSize; + vh = videl.YSize; } + /* If there's not enough space to display the left border, just return */ + if (vw_clip < videl.leftBorderSize) + return; + /* If there's not enough space for the left border + the graphic area, we clip */ + if (vw_clip < vw + videl.leftBorderSize) { + vw = vw_clip - videl.leftBorderSize; + rightBorderSize = 0; + } + /* if there's not enough space for the left border + the graphic area + the right border, we clip the border */ + else if (vw_clip < vw + videl.leftBorderSize + videl.rightBorderSize) + rightBorderSize = vw_clip - videl.leftBorderSize - vw; + else + rightBorderSize = videl.rightBorderSize; + + /* If there's not enough space to display the upper border, just return */ + if (vh_clip < videl.upperBorderSize) + return; + + /* If there's not enough space for the upper border + the graphic area, we clip */ + if (vh_clip < vh + videl.upperBorderSize) { + vh = vh_clip - videl.upperBorderSize; + lowBorderSize = 0; + } + /* if there's not enough space for the upper border + the graphic area + the lower border, we clip the border */ + else if (vh_clip < vh + videl.upperBorderSize + videl.lowerBorderSize) + lowBorderSize = vh_clip - videl.upperBorderSize - vh; + else + lowBorderSize = videl.lowerBorderSize; + /* Center screen */ hvram += ((scrheight-vh_clip)>>1)*scrpitch; hvram += ((scrwidth-vw_clip)>>1)*HostScreen_getBpp(); - /* Render */ + Uint16 *fvram_line = fvram; + scrwidth = videl.leftBorderSize + vw + videl.rightBorderSize; + + /* render the graphic area */ if (vbpp < 16) { /* Bitplanes modes */ - // The SDL colors blitting... + /* The SDL colors blitting... */ Uint8 color[16]; - // FIXME: The byte swap could be done here by enrolling the loop into 2 each by 8 pixels + /* FIXME: The byte swap could be done here by enrolling the loop into 2 each by 8 pixels */ switch ( HostScreen_getBpp() ) { case 1: - { - Uint16 *fvram_line = fvram; - Uint8 *hvram_line = hvram; - int h; + { + Uint8 *hvram_line = hvram; - for (h = 0; h < vh_clip; h++) { - Uint16 *fvram_column = fvram_line; - Uint8 *hvram_column = hvram_line; - int w; + /* Render the upper border */ + for (h = 0; h < videl.upperBorderSize; h++) { + VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + hvram_line += scrpitch; + } - /* First 16 pixels: */ - Videl_bitplaneToChunky(fvram_column, vbpp, color); - memcpy(hvram_column, color+hscrolloffset, 16-hscrolloffset); - hvram_column += 16-hscrolloffset; + /* Render the graphical area */ + for (h = 0; h < vh; h++) { + Uint16 *fvram_column = fvram_line; + Uint8 *hvram_column = hvram_line; + + /* Left border first */ + VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize); + hvram_column += videl.leftBorderSize; + + /* First 16 pixels */ + VIDEL_bitplaneToChunky(fvram_column, vbpp, color); + memcpy(hvram_column, color+hscrolloffset, 16-hscrolloffset); + hvram_column += 16-hscrolloffset; + fvram_column += vbpp; + /* Now the main part of the line */ + for (w = 1; w < (vw+15)>>4; w++) { + VIDEL_bitplaneToChunky( fvram_column, vbpp, color ); + memcpy(hvram_column, color, 16); + hvram_column += 16; fvram_column += vbpp; - /* Now the main part of the line: */ - for (w = 1; w < (vw_clip+15)>>4; w++) { - Videl_bitplaneToChunky( fvram_column, vbpp, color ); - memcpy(hvram_column, color, 16); - hvram_column += 16; - fvram_column += vbpp; - } - /* Last pixels of the line for fine scrolling: */ - if (hscrolloffset) { - Videl_bitplaneToChunky(fvram_column, vbpp, color); - memcpy(hvram_column, color, hscrolloffset); - } - - hvram_line += scrpitch; - fvram_line += nextline; } + /* Last pixels of the line for fine scrolling */ + if (hscrolloffset) { + VIDEL_bitplaneToChunky(fvram_column, vbpp, color); + memcpy(hvram_column, color, hscrolloffset); + } + /* Right border */ + VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), rightBorderSize); + + fvram_line += nextline; + hvram_line += scrpitch; } - break; + + /* Render the lower border */ + for (h = 0; h < lowBorderSize; h++) { + VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + hvram_line += scrpitch; + } + } + break; case 2: - { - Uint16 *fvram_line = fvram; - Uint16 *hvram_line = (Uint16 *)hvram; - int h; + { + Uint16 *hvram_line = (Uint16 *)hvram; - for (h = 0; h < vh_clip; h++) { - Uint16 *fvram_column = fvram_line; - Uint16 *hvram_column = hvram_line; - int w, j; + /* Render the upper border */ + for (h = 0; h < videl.upperBorderSize; h++) { + VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + hvram_line += scrpitch>>1; + } - /* First 16 pixels: */ - Videl_bitplaneToChunky(fvram_column, vbpp, color); - for (j = 0; j < 16 - hscrolloffset; j++) { - *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]); + /* Render the graphical area */ + for (h = 0; h < vh; h++) { + Uint16 *fvram_column = fvram_line; + Uint16 *hvram_column = hvram_line; + + /* Left border first */ + VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize); + hvram_column += videl.leftBorderSize; + + /* First 16 pixels */ + VIDEL_bitplaneToChunky(fvram_column, vbpp, color); + for (j = 0; j < 16 - hscrolloffset; j++) { + *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]); + } + fvram_column += vbpp; + /* Now the main part of the line */ + for (w = 1; w < (vw+15)>>4; w++) { + VIDEL_bitplaneToChunky( fvram_column, vbpp, color ); + for (j=0; j<16; j++) { + *hvram_column++ = HostScreen_getPaletteColor( color[j] ); } fvram_column += vbpp; - /* Now the main part of the line: */ - for (w = 1; w < (vw_clip+15)>>4; w++) { - Videl_bitplaneToChunky( fvram_column, vbpp, color ); - for (j=0; j<16; j++) { - *hvram_column++ = HostScreen_getPaletteColor( color[j] ); - } - fvram_column += vbpp; - } - /* Last pixels of the line for fine scrolling: */ - if (hscrolloffset) { - Videl_bitplaneToChunky(fvram_column, vbpp, color); - for (j = 0; j < hscrolloffset; j++) { - *hvram_column++ = HostScreen_getPaletteColor(color[j]); - } + } + /* Last pixels of the line for fine scrolling */ + if (hscrolloffset) { + VIDEL_bitplaneToChunky(fvram_column, vbpp, color); + for (j = 0; j < hscrolloffset; j++) { + *hvram_column++ = HostScreen_getPaletteColor(color[j]); } - - hvram_line += scrpitch>>1; - fvram_line += nextline; } + /* Right border */ + VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), rightBorderSize); + + fvram_line += nextline; + hvram_line += scrpitch>>1; } - break; + + /* Render the lower border */ + for (h = 0; h < lowBorderSize; h++) { + VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + hvram_line += scrpitch>>1; + } + } + break; case 4: - { - Uint16 *fvram_line = fvram; - Uint32 *hvram_line = (Uint32 *)hvram; - int h; + { + Uint32 *hvram_line = (Uint32 *)hvram; - for (h = 0; h < vh_clip; h++) { - Uint16 *fvram_column = fvram_line; - Uint32 *hvram_column = hvram_line; - int w, j; + /* Render the upper border */ + for (h = 0; h < videl.upperBorderSize; h++) { + VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + hvram_line += scrpitch>>2; + } - /* First 16 pixels: */ - Videl_bitplaneToChunky(fvram_column, vbpp, color); - for (j = 0; j < 16 - hscrolloffset; j++) { - *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]); + /* Render the graphical area */ + for (h = 0; h < vh; h++) { + Uint16 *fvram_column = fvram_line; + Uint32 *hvram_column = hvram_line; + + /* Left border first */ + VIDEL_memset_uint32 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize); + hvram_column += videl.leftBorderSize; + + /* First 16 pixels */ + VIDEL_bitplaneToChunky(fvram_column, vbpp, color); + for (j = 0; j < 16 - hscrolloffset; j++) { + *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]); + } + fvram_column += vbpp; + /* Now the main part of the line */ + for (w = 1; w < (vw+15)>>4; w++) { + VIDEL_bitplaneToChunky( fvram_column, vbpp, color ); + for (j=0; j<16; j++) { + *hvram_column++ = HostScreen_getPaletteColor( color[j] ); } fvram_column += vbpp; - /* Now the main part of the line: */ - for (w = 1; w < (vw_clip+15)>>4; w++) { - Videl_bitplaneToChunky( fvram_column, vbpp, color ); - for (j=0; j<16; j++) { - *hvram_column++ = HostScreen_getPaletteColor( color[j] ); - } - fvram_column += vbpp; - } - /* Last pixels of the line for fine scrolling: */ - if (hscrolloffset) { - Videl_bitplaneToChunky(fvram_column, vbpp, color); - for (j = 0; j < hscrolloffset; j++) { - *hvram_column++ = HostScreen_getPaletteColor(color[j]); - } + } + /* Last pixels of the line for fine scrolling */ + if (hscrolloffset) { + VIDEL_bitplaneToChunky(fvram_column, vbpp, color); + for (j = 0; j < hscrolloffset; j++) { + *hvram_column++ = HostScreen_getPaletteColor(color[j]); } - - hvram_line += scrpitch>>2; - fvram_line += nextline; } + /* Right border */ + VIDEL_memset_uint32 (hvram_column, HostScreen_getPaletteColor(0), rightBorderSize); + + fvram_line += nextline; + hvram_line += scrpitch>>2; } - break; + + /* Render the lower border */ + for (h = 0; h < lowBorderSize; h++) { + VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + hvram_line += scrpitch>>2; + } + } + break; } } else { - // Falcon TC (High Color) + /* Falcon TC (High Color) */ switch ( HostScreen_getBpp() ) { case 1: - { - /* FIXME: when Videl switches to 16bpp, set the palette to 3:3:2 */ - Uint16 *fvram_line = fvram; - Uint8 *hvram_line = hvram; - int h; - - for (h = 0; h < vh_clip; h++) { - Uint16 *fvram_column = fvram_line; - Uint8 *hvram_column = hvram_line; - int w, tmp; - - for (w = 0; w < vw_clip; w++) { - - tmp = SDL_SwapBE16(*fvram_column); + { + /* FIXME: when Videl switches to 16bpp, set the palette to 3:3:2 */ + Uint8 *hvram_line = hvram; + + /* Render the upper border */ + for (h = 0; h < videl.upperBorderSize; h++) { + VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + hvram_line += scrpitch; + } - *hvram_column = ((tmp>>13) & 7) << 5; - *hvram_column |= ((tmp>>8) & 7) << 2; - *hvram_column |= ((tmp>>2) & 3); + /* Render the graphical area */ + for (h = 0; h < vh; h++) { + Uint16 *fvram_column = fvram_line; + Uint8 *hvram_column = hvram_line; + int tmp; + + /* Left border first */ + VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize); + hvram_column += videl.leftBorderSize; + + /* Graphical area */ + for (w = 0; w < vw; w++) { + tmp = SDL_SwapBE16(*fvram_column++); + *hvram_column++ = (((tmp>>13) & 7) << 5) + (((tmp>>8) & 7) << 2) + (((tmp>>2) & 3)); + } - hvram_column++; - fvram_column++; - } + /* Right border */ + VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), rightBorderSize); - hvram_line += scrpitch; - fvram_line += nextline; - } + fvram_line += nextline; + hvram_line += scrpitch; } - break; + /* Render the bottom border */ + for (h = 0; h < lowBorderSize; h++) { + VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + hvram_line += scrpitch; + } + } + break; case 2: - { - Uint16 *fvram_line = fvram; - Uint16 *hvram_line = (Uint16 *)hvram; - int h; + { + Uint16 *hvram_line = (Uint16 *)hvram; + + /* Render the upper border */ + for (h = 0; h < videl.upperBorderSize; h++) { + VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + hvram_line += scrpitch>>1; + } + + /* Render the graphical area */ + for (h = 0; h < vh; h++) { + Uint16 *hvram_column = hvram_line; + + /* Left border first */ + VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize); + hvram_column += videl.leftBorderSize; - for (h = 0; h < vh_clip; h++) { #if SDL_BYTEORDER == SDL_BIG_ENDIAN - //FIXME: here might be a runtime little/big video endian switch like: - // if ( /* videocard memory in Motorola endian format */ false) - memcpy(hvram_line, fvram_line, vw_clip<<1); + /* FIXME: here might be a runtime little/big video endian switch like: + if ( " videocard memory in Motorola endian format " false) + */ + memcpy(hvram_column, fvram_line, vw<<1); + hvram_column += vw<<1; #else - int w; - Uint16 *fvram_column = fvram_line; - Uint16 *hvram_column = hvram_line; + Uint16 *fvram_column = fvram_line; + /* Graphical area */ + for (w = 0; w < vw; w++) + *hvram_column ++ = SDL_SwapBE16(*fvram_column++); +#endif /* SDL_BYTEORDER == SDL_BIG_ENDIAN */ - for (w = 0; w < vw_clip; w++) { - // byteswap with SDL asm macros - *hvram_column++ = SDL_SwapBE16(*fvram_column++); - } -#endif // SDL_BYTEORDER == SDL_BIG_ENDIAN + /* Right border */ + VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), rightBorderSize); - hvram_line += scrpitch>>1; - fvram_line += nextline; - } + fvram_line += nextline; + hvram_line += scrpitch>>1; } - break; - case 4: - { - Uint16 *fvram_line = fvram; - Uint32 *hvram_line = (Uint32 *)hvram; - int h; - for (h = 0; h < vh_clip; h++) { - Uint16 *fvram_column = fvram_line; - Uint32 *hvram_column = hvram_line; - int w; - - for (w = 0; w < vw_clip; w++) { - Uint16 srcword = *fvram_column++; - - *hvram_column++ = - SDL_MapRGB(scrfmt, - (srcword & 0xf8), - (((srcword & 0x07) << 5) | - ((srcword >> 11) & 0x3c)), - ((srcword >> 5) & 0xf8)); - } - - hvram_line += scrpitch>>2; - fvram_line += nextline; - } + /* Render the bottom border */ + for (h = 0; h < lowBorderSize; h++) { + VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + hvram_line += scrpitch>>1; } - break; - } - } -} + } + break; + case 4: + { + Uint32 *hvram_line = (Uint32 *)hvram; + /* Render the upper border */ + for (h = 0; h < videl.upperBorderSize; h++) { + VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + hvram_line += scrpitch>>2; + } -static void VIDEL_renderScreenZoom(void) -{ - /* Atari screen infos */ - int vw = VIDEL_getScreenWidth(); - int vh = VIDEL_getScreenHeight(); + /* Render the graphical area */ + for (h = 0; h < vh; h++) { + Uint16 *fvram_column = fvram_line; + Uint32 *hvram_column = hvram_line; + + /* Left border first */ + VIDEL_memset_uint32 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize); + hvram_column += videl.leftBorderSize; + + /* Graphical area */ + for (w = 0; w < vw; w++) { + Uint16 srcword = *fvram_column++; + *hvram_column ++ = SDL_MapRGB(scrfmt, (srcword & 0xf8), (((srcword & 0x07) << 5) | ((srcword >> 11) & 0x3c)), ((srcword >> 5) & 0xf8)); + } - int lineoffset = handleReadW(HW + 0x0e) & 0x01ff; // 9 bits - int linewidth = handleReadW(HW + 0x10) & 0x03ff; // 10 bits - /* same remark as before: too naive */ - int nextline = linewidth + lineoffset; + /* Right border */ + VIDEL_memset_uint32 (hvram_column, HostScreen_getPaletteColor(0), rightBorderSize); + } - if ((vw<32) || (vh<32)) return; + fvram_line += nextline; + hvram_line += scrpitch>>2; - if (bpp<16 && !hostColorsSync) { - VIDEL_updateColors(); + /* Render the bottom border */ + for (h = 0; h < lowBorderSize; h++) { + VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + hvram_line += scrpitch>>2; + } + } + break; + } } - - VIDEL_ConvertScreenZoom(vw, vh, bpp, nextline); } @@ -1119,7 +1500,23 @@ void VIDEL_ConvertScreenZoom(int vw, int { int i, j, w, h, cursrcline; - Uint16 *fvram = (Uint16 *) Atari2HostAddr(VIDEL_getVideoramAddress()); + Uint16 *fvram = (Uint16 *) Atari2HostAddr(videl.videoBaseAddr); + Uint16 *fvram_line; + Uint16 scrIdx = 0; + + int coefx = 1; + int coefy = 1; + + /* If emulated computer is the TT, we use the same rendering for display, but without the borders */ + if (ConfigureParams.System.nMachineType == MACHINE_TT) { + videl.leftBorderSize = 0; + videl.rightBorderSize = 0; + videl.upperBorderSize = 0; + videl.lowerBorderSize = 0; + videl.XSize = vw; + videl.YSize = vh; + fvram = (Uint16 *) Atari2HostAddr(VIDEL_getVideoramAddress()); + } /* Host screen infos */ int scrpitch = HostScreen_getPitch(); @@ -1129,7 +1526,7 @@ void VIDEL_ConvertScreenZoom(int vw, int SDL_PixelFormat *scrfmt = HostScreen_getFormat(); Uint8 *hvram = (Uint8 *) HostScreen_getVideoramAddress(); - int hscrolloffset = (handleRead(HW + 0x65) & 0x0f); + int hscrolloffset = IoMem_ReadByte(0xff8265) & 0x0f; /* Horizontal scroll register set? */ if (hscrolloffset) { @@ -1139,8 +1536,8 @@ void VIDEL_ConvertScreenZoom(int vw, int /* Integer zoom coef ? */ if (/*(bx_options.autozoom.integercoefs) &&*/ (scrwidth>=vw) && (scrheight>=vh)) { - int coefx = scrwidth/vw; - int coefy = scrheight/vh; + coefx = scrwidth/vw; + coefy = scrheight/vh; scrwidth = vw * coefx; scrheight = vh * coefy; @@ -1151,299 +1548,458 @@ void VIDEL_ConvertScreenZoom(int vw, int } /* New zoom ? */ - if ((zoomwidth != vw) || (scrwidth != prev_scrwidth)) { - if (zoomxtable) { - free(zoomxtable); + if ((videl_zoom.zoomwidth != vw) || (scrwidth != videl_zoom.prev_scrwidth)) { + if (videl_zoom.zoomxtable) { + free(videl_zoom.zoomxtable); } - zoomxtable = malloc(sizeof(int)*scrwidth); + videl_zoom.zoomxtable = malloc(sizeof(int)*scrwidth); for (i=0; i>4; w++) { - Videl_bitplaneToChunky( fvram_column, vbpp, color ); - memcpy(hvram_column, color, 16); - hvram_column += 16; - fvram_column += vbpp; - } - /* Last pixels of the line for fine scrolling: */ - if (hscrolloffset) { - Videl_bitplaneToChunky(fvram_column, vbpp, color); - memcpy(hvram_column, color, hscrolloffset); - } + { + /* One complete 16-pixel aligned planar 2 chunky line */ + Uint8 *p2cline = malloc(sizeof(Uint8) * ((vw+15) & ~15)); + Uint8 *hvram_line = hvram; + Uint8 *hvram_column = p2cline; + + /* Render the upper border */ + for (h = 0; h < videl.upperBorderSize * coefy; h++) { + VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + hvram_line += scrpitch; + } - /* Zoom a new line */ - for (w=0; w>4; w++) { + VIDEL_bitplaneToChunky( fvram_column, vbpp, color ); + memcpy(hvram_column, color, 16); + hvram_column += 16; + fvram_column += vbpp; + } + /* Last pixels of the line for fine scrolling */ + if (hscrolloffset) { + VIDEL_bitplaneToChunky(fvram_column, vbpp, color); + memcpy(hvram_column, color, hscrolloffset); } - hvram_line += scrpitch; - cursrcline = zoomytable[h]; + hvram_column = hvram_line; + + /* Display the Left border */ + VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize * coefx); + hvram_column += videl.leftBorderSize * coefx; + + /* Display the Graphical area */ + for (w=0; w<(vw*coefx); w++) + hvram_column[w] = p2cline[videl_zoom.zoomxtable[w - videl.leftBorderSize * coefx]]; + hvram_column += vw * coefx; + + /* Display the Right border */ + VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), videl.rightBorderSize * coefx); + hvram_column += videl.rightBorderSize * coefx; } - free(p2cline); + hvram_line += scrpitch; + cursrcline = videl_zoom.zoomytable[h]; } - break; + + /* Render the lower border */ + for (h = 0; h < videl.lowerBorderSize * coefy; h++) { + VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + hvram_line += scrpitch; + } + + free(p2cline); + } + break; case 2: - { - /* One complete planar 2 chunky line */ - Uint16 *p2cline = malloc(sizeof(Uint16)*vw); - - Uint16 *fvram_line; - Uint16 *hvram_line = (Uint16 *)hvram; - - for (h = 0; h < scrheight; h++) { - fvram_line = fvram + (zoomytable[h] * nextline); - - /* Recopy the same line ? */ - if (zoomytable[h] == cursrcline) { - memcpy(hvram_line, hvram_line-(scrpitch>>1), scrwidth*scrbpp); - } else { - Uint16 *fvram_column = fvram_line; - Uint16 *hvram_column = p2cline; - - /* First 16 pixels of a new line: */ - Videl_bitplaneToChunky(fvram_column, vbpp, color); - for (j = 0; j < 16 - hscrolloffset; j++) { - *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]); + { + /* One complete 16-pixel aligned planar 2 chunky line */ + Uint16 *p2cline = malloc(sizeof(Uint16) * ((vw+15) & ~15)); + Uint16 *hvram_line = (Uint16 *)hvram; + Uint16 *hvram_column = p2cline; + + /* Render the upper border */ + for (h = 0; h < videl.upperBorderSize * coefy; h++) { + VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + hvram_line += scrpitch>>1; + } + + /* Render the graphical area */ + for (h = 0; h < scrheight; h++) { + fvram_line = fvram + (videl_zoom.zoomytable[scrIdx] * nextline); + scrIdx ++; + + /* Recopy the same line ? */ + if (videl_zoom.zoomytable[h] == cursrcline) { + memcpy(hvram_line, hvram_line-(scrpitch>>1), scrwidth*scrbpp); + } else { + Uint16 *fvram_column = fvram_line; + hvram_column = p2cline; + + /* First 16 pixels of a new line */ + VIDEL_bitplaneToChunky(fvram_column, vbpp, color); + for (j = 0; j < 16 - hscrolloffset; j++) { + *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]); + } + fvram_column += vbpp; + /* Convert the main part of the new line */ + for (w = 1; w < (vw+15)>>4; w++) { + VIDEL_bitplaneToChunky( fvram_column, vbpp, color ); + for (j=0; j<16; j++) { + *hvram_column++ = HostScreen_getPaletteColor( color[j] ); } fvram_column += vbpp; - /* Convert the main part of the new line: */ - for (w = 1; w < (vw+15)>>4; w++) { - Videl_bitplaneToChunky( fvram_column, vbpp, color ); - for (j=0; j<16; j++) { - *hvram_column++ = HostScreen_getPaletteColor( color[j] ); - } - fvram_column += vbpp; - } - /* Last pixels of the new line for fine scrolling: */ - if (hscrolloffset) { - Videl_bitplaneToChunky(fvram_column, vbpp, color); - for (j = 0; j < hscrolloffset; j++) { - *hvram_column++ = HostScreen_getPaletteColor(color[j]); - } - } - - /* Zoom a new line */ - for (w=0; w>1; - cursrcline = zoomytable[h]; + hvram_column = hvram_line; + + /* Display the Left border */ + VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize * coefx); + hvram_column += videl.leftBorderSize * coefx; + + /* Display the Graphical area */ + for (w=0; w<(vw*coefx); w++) + hvram_column[w] = p2cline[videl_zoom.zoomxtable[w]]; + hvram_column += vw * coefx; + + /* Display the Right border */ + VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), videl.rightBorderSize * coefx); + hvram_column += videl.rightBorderSize * coefx; } - free(p2cline); + hvram_line += scrpitch>>1; + cursrcline = videl_zoom.zoomytable[h]; } - break; + + /* Render the lower border */ + for (h = 0; h < videl.lowerBorderSize * coefy; h++) { + VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + hvram_line += scrpitch>>1; + } + + free(p2cline); + } + break; case 4: - { - /* One complete planar 2 chunky line */ - Uint32 *p2cline = malloc(sizeof(Uint32)*vw); - - Uint16 *fvram_line; - Uint32 *hvram_line = (Uint32 *)hvram; - - for (h = 0; h < scrheight; h++) { - fvram_line = fvram + (zoomytable[h] * nextline); - - /* Recopy the same line ? */ - if (zoomytable[h] == cursrcline) { - memcpy(hvram_line, hvram_line-(scrpitch>>2), scrwidth*scrbpp); - } else { - Uint16 *fvram_column = fvram_line; - Uint32 *hvram_column = p2cline; - - /* First 16 pixels of a new line: */ - Videl_bitplaneToChunky(fvram_column, vbpp, color); - for (j = 0; j < 16 - hscrolloffset; j++) { - *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]); + { + /* One complete 16-pixel aligned planar 2 chunky line */ + Uint32 *p2cline = malloc(sizeof(Uint32) * ((vw+15) & ~15)); + Uint32 *hvram_line = (Uint32 *)hvram; + Uint32 *hvram_column = p2cline; + + /* Render the upper border */ + for (h = 0; h < videl.upperBorderSize * coefy; h++) { + VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + hvram_line += scrpitch>>2; + } + + /* Render the graphical area */ + for (h = 0; h < scrheight; h++) { + fvram_line = fvram + (videl_zoom.zoomytable[scrIdx] * nextline); + scrIdx ++; + /* Recopy the same line ? */ + if (videl_zoom.zoomytable[h] == cursrcline) { + memcpy(hvram_line, hvram_line-(scrpitch>>2), scrwidth*scrbpp); + } else { + Uint16 *fvram_column = fvram_line; + hvram_column = p2cline; + + /* First 16 pixels of a new line */ + VIDEL_bitplaneToChunky(fvram_column, vbpp, color); + for (j = 0; j < 16 - hscrolloffset; j++) { + *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]); + } + fvram_column += vbpp; + /* Convert the main part of the new line */ + for (w = 1; w < (vw+15)>>4; w++) { + VIDEL_bitplaneToChunky( fvram_column, vbpp, color ); + for (j=0; j<16; j++) { + *hvram_column++ = HostScreen_getPaletteColor( color[j] ); } fvram_column += vbpp; - /* Convert the main part of the new line: */ - for (w = 1; w < (vw+15)>>4; w++) { - Videl_bitplaneToChunky( fvram_column, vbpp, color ); - for (j=0; j<16; j++) { - *hvram_column++ = HostScreen_getPaletteColor( color[j] ); - } - fvram_column += vbpp; - } - /* Last pixels of the new line for fine scrolling: */ - if (hscrolloffset) { - Videl_bitplaneToChunky(fvram_column, vbpp, color); - for (j = 0; j < hscrolloffset; j++) { - *hvram_column++ = HostScreen_getPaletteColor(color[j]); - } + } + /* Last pixels of the new line for fine scrolling */ + if (hscrolloffset) { + VIDEL_bitplaneToChunky(fvram_column, vbpp, color); + for (j = 0; j < hscrolloffset; j++) { + *hvram_column++ = HostScreen_getPaletteColor(color[j]); } + } - /* Zoom a new line */ - for (w=0; w>2; - cursrcline = zoomytable[h]; + /* Display the Right border */ + VIDEL_memset_uint32 (hvram_column, HostScreen_getPaletteColor(0), videl.rightBorderSize * coefx); + hvram_column += videl.rightBorderSize * coefx; } - free(p2cline); + hvram_line += scrpitch>>2; + cursrcline = videl_zoom.zoomytable[h]; } - break; + + /* Render the lower border */ + for (h = 0; h < videl.lowerBorderSize * coefy; h++) { + VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + hvram_line += scrpitch>>2; + } + + free(p2cline); + } + break; } } else { /* Falcon high-color (16-bit) mode */ switch(scrbpp) { case 1: - { - /* FIXME: when Videl switches to 16bpp, set the palette to 3:3:2 */ - Uint16 *fvram_line; - Uint8 *hvram_line = hvram; - - for (h = 0; h < scrheight; h++) { - Uint16 *fvram_column; - Uint8 *hvram_column; + { + /* FIXME: when Videl switches to 16bpp, set the palette to 3:3:2 */ + Uint8 *hvram_line = hvram; + Uint8 *hvram_column = hvram_line; + + /* Render the upper border */ + for (h = 0; h < videl.upperBorderSize * coefy; h++) { + VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + hvram_line += scrpitch; + } - fvram_line = fvram + (zoomytable[h] * nextline); - fvram_column = fvram_line; - hvram_column = hvram_line; + /* Render the graphical area */ + for (h = 0; h < scrheight; h++) { + Uint16 *fvram_column; + + fvram_line = fvram + (videl_zoom.zoomytable[scrIdx] * nextline); + scrIdx ++; + + fvram_column = fvram_line; + + /* Recopy the same line ? */ + if (videl_zoom.zoomytable[h] == cursrcline) { + memcpy(hvram_line, hvram_line-scrpitch, scrwidth*scrbpp); + } else { - /* Recopy the same line ? */ - if (zoomytable[h] == cursrcline) { - memcpy(hvram_line, hvram_line-scrpitch, scrwidth*scrbpp); - } else { - for (w = 0; w < scrwidth; w++) { - Uint16 srcword; - Uint8 dstbyte; + hvram_column = hvram_line; + /* Display the Left border */ + VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize * coefx); + hvram_column += videl.leftBorderSize * coefx; + + /* Display the Graphical area */ + for (w = 0; w<(vw*coefx); w++) { + Uint16 srcword; + Uint8 dstbyte; - srcword = SDL_SwapBE16(fvram_column[zoomxtable[w]]); - - dstbyte = ((srcword>>13) & 7) << 5; - dstbyte |= ((srcword>>8) & 7) << 2; - dstbyte |= ((srcword>>2) & 3); + srcword = SDL_SwapBE16(fvram_column[videl_zoom.zoomxtable[w - videl.leftBorderSize * coefx]]); - *hvram_column++ = dstbyte; - } + dstbyte = ((srcword>>13) & 7) << 5; + dstbyte |= ((srcword>>8) & 7) << 2; + dstbyte |= ((srcword>>2) & 3); + *hvram_column++ = dstbyte; } - hvram_line += scrpitch; - cursrcline = zoomytable[h]; + /* Display the Right border */ + VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), videl.rightBorderSize * coefx); + hvram_column += videl.rightBorderSize * coefx; } + + hvram_line += scrpitch; + cursrcline = videl_zoom.zoomytable[h]; } - break; + + /* Render the lower border */ + for (h = 0; h < videl.lowerBorderSize * coefy; h++) { + VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + hvram_line += scrpitch; + } + } + break; case 2: - { - Uint16 *fvram_line; - Uint16 *hvram_line = (Uint16 *)hvram; - - for (h = 0; h < scrheight; h++) { - Uint16 *fvram_column; - Uint16 *hvram_column; + { + Uint16 *hvram_line = (Uint16 *)hvram; + Uint16 *hvram_column = hvram_line; + + /* Render the upper border */ + for (h = 0; h < videl.upperBorderSize * coefy; h++) { + VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + hvram_line += scrpitch>>1; + } + + /* Render the graphical area */ + for (h = 0; h < scrheight; h++) { + Uint16 *fvram_column; + + fvram_line = fvram + (videl_zoom.zoomytable[scrIdx] * nextline); + scrIdx ++; + + fvram_column = fvram_line; + + /* Recopy the same line ? */ + if (videl_zoom.zoomytable[h] == cursrcline) { + memcpy(hvram_line, hvram_line-(scrpitch>>1), scrwidth*scrbpp); + } else { - fvram_line = fvram + (zoomytable[h] * nextline); - fvram_column = fvram_line; hvram_column = hvram_line; - /* Recopy the same line ? */ - if (zoomytable[h] == cursrcline) { - memcpy(hvram_line, hvram_line-(scrpitch>>1), scrwidth*scrbpp); - } else { - for (w = 0; w < scrwidth; w++) { - Uint16 srcword; - - srcword = SDL_SwapBE16(fvram_column[zoomxtable[w]]); - *hvram_column++ = srcword; - } - } + /* Display the Left border */ + VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize * coefx); + hvram_column += videl.leftBorderSize * coefx; + + /* Display the Graphical area */ + for (w=0; w<(vw*coefx); w++) + *hvram_column++ = SDL_SwapBE16(fvram_column[videl_zoom.zoomxtable[w]]); + - hvram_line += scrpitch>>1; - cursrcline = zoomytable[h]; + /* Display the Right border */ + VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), videl.rightBorderSize * coefx); + hvram_column += videl.rightBorderSize * coefx; } + + hvram_line += scrpitch>>1; + cursrcline = videl_zoom.zoomytable[h]; } - break; + + /* Render the lower border */ + for (h = 0; h < videl.lowerBorderSize * coefy; h++) { + VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + hvram_line += scrpitch>>1; + } + } + break; case 4: - { - Uint16 *fvram_line; - Uint32 *hvram_line = (Uint32 *)hvram; - - for (h = 0; h < scrheight; h++) { - Uint16 *fvram_column; - Uint32 *hvram_column; + { + Uint32 *hvram_line = (Uint32 *)hvram; + Uint32 *hvram_column = hvram_line; + + /* Render the upper border */ + for (h = 0; h < videl.upperBorderSize * coefy; h++) { + VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + } + + /* Render the graphical area */ + for (h = 0; h < scrheight; h++) { + Uint16 *fvram_column; + + fvram_line = fvram + (videl_zoom.zoomytable[scrIdx] * nextline); + scrIdx ++; + fvram_column = fvram_line; + + /* Recopy the same line ? */ + if (videl_zoom.zoomytable[h] == cursrcline) { + memcpy(hvram_line, hvram_line-(scrpitch>>2), scrwidth*scrbpp); + hvram_line += scrpitch>>2; + } else { - fvram_line = fvram + (zoomytable[h] * nextline); - fvram_column = fvram_line; hvram_column = hvram_line; - /* Recopy the same line ? */ - if (zoomytable[h] == cursrcline) { - memcpy(hvram_line, hvram_line-(scrpitch>>2), scrwidth*scrbpp); - } else { - for (w = 0; w < scrwidth; w++) { - Uint16 srcword; - - srcword = fvram_column[zoomxtable[w]]; + /* Display the Left border */ + VIDEL_memset_uint32 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize * coefx); + hvram_column += videl.leftBorderSize * coefx; + + /* Display the Graphical area */ + for (w = 0; w<(vw*coefx); w++) { + Uint16 srcword; - *hvram_column++ = - SDL_MapRGB(scrfmt, - (srcword & 0xf8), - (((srcword & 0x07) << 5) | - ((srcword >> 11) & 0x3c)), - ((srcword >> 5) & 0xf8)); - } + srcword = fvram_column[videl_zoom.zoomxtable[w]]; + *hvram_column++ = SDL_MapRGB(scrfmt, (srcword & 0xf8), (((srcword & 0x07) << 5) | ((srcword >> 11) & 0x3c)), ((srcword >> 5) & 0xf8)); } - hvram_line += scrpitch>>2; - cursrcline = zoomytable[h]; + /* Display the Right border */ + VIDEL_memset_uint32 (hvram_column, HostScreen_getPaletteColor(0), videl.rightBorderSize * coefx); + hvram_column += videl.rightBorderSize * coefx; } + + hvram_line += scrpitch>>2; + cursrcline = videl_zoom.zoomytable[h]; } - break; + + /* Render the lower border */ + for (h = 0; h < videl.lowerBorderSize * coefy; h++) { + VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth); + hvram_line += scrpitch>>2; + } + } + break; } } } + +static void VIDEL_memset_uint32(Uint32 *addr, Uint32 color, int count) +{ + while (count-- > 0) { + *addr++ = color; + } +} + +static void VIDEL_memset_uint16(Uint16 *addr, Uint16 color, int count) +{ + while (count-- > 0) { + *addr++ = color; + } +} + +static void VIDEL_memset_uint8(Uint8 *addr, Uint8 color, int count) +{ + memset(addr, color, count); +}