Annotation of hatari/src/falcon/videl.c, revision 1.1.1.11

1.1       root        1: /*
                      2:   Hatari - videl.c
                      3: 
1.1.1.9   root        4:   This file is distributed under the GNU General Public License, version 2
                      5:   or at your option any later version. Read the file gpl.txt for details.
1.1       root        6: 
                      7:   Falcon Videl emulation. The Videl is the graphics shifter chip of the Falcon.
                      8:   It supports free programmable resolutions with 1, 2, 4, 8 or 16 bits per
                      9:   pixel.
                     10: 
                     11:   This file originally came from the Aranym project and has been heavily
                     12:   modified to work for Hatari (but the kudos for the great Videl emulation
                     13:   code goes to the people from the Aranym project of course).
1.1.1.6   root       14: 
                     15:   Videl can run at 2 frequencies : 25.175 Mhz or 32 MHz
                     16:   
                     17:   Hardware I/O registers:
                     18: 
                     19:        $FFFF8006 (byte) : monitor type
                     20: 
                     21:        $FFFF8201 (byte) : VDL_VBH - Video Base Hi
                     22:        $FFFF8203 (byte) : VDL_VBM - Video Base Mi
                     23:        $FFFF8205 (byte) : VDL_VCH - Video Count Hi
                     24:        $FFFF8207 (byte) : VDL_VCM - Video Count Mi
                     25:        $FFFF8209 (byte) : VDL_VCL - Video Count Lo
                     26:        $FFFF820A (byte) : VDL_SYM - Sync mode
                     27:        $FFFF820D (byte) : VDL_VBL - Video Base Lo
                     28:        $FFFF820E (word) : VDL_LOF - Offset to next line
                     29:        $FFFF8210 (word) : VDL_LWD - Line Wide in Words
                     30:        
                     31:        $FFFF8240 (word) : VDL_STC - ST Palette Register 00
                     32:        .........
                     33:        $FFFF825E (word) : VDL_STC - ST Palette Register 15
                     34: 
                     35:        $FFFF8260 (byte) : ST shift mode
1.1.1.8   root       36:        $FFFF8264 (byte) : Horizontal scroll register shadow register
1.1.1.6   root       37:        $FFFF8265 (byte) : Horizontal scroll register
                     38:        $FFFF8266 (word) : Falcon shift mode
                     39:        
                     40:        $FFFF8280 (word) : HHC - Horizontal Hold Counter
                     41:        $FFFF8282 (word) : HHT - Horizontal Hold Timer
                     42:        $FFFF8284 (word) : HBB - Horizontal Border Begin
                     43:        $FFFF8286 (word) : HBE - Horizontal Border End
                     44:        $FFFF8288 (word) : HDB - Horizontal Display Begin
                     45:        $FFFF828A (word) : HDE - Horizontal Display End
                     46:        $FFFF828C (word) : HSS - Horizontal SS
                     47:        $FFFF828E (word) : HFS - Horizontal FS
                     48:        $FFFF8290 (word) : HEE - Horizontal EE
                     49:        
                     50:        $FFFF82A0 (word) : VFC - Vertical Frequency Counter
                     51:        $FFFF82A2 (word) : VFT - Vertical Frequency Timer
                     52:        $FFFF82A4 (word) : VBB - Vertical Border Begin
                     53:        $FFFF82A6 (word) : VBE - Vertical Border End
                     54:        $FFFF82A8 (word) : VDB - Vertical Display Begin
                     55:        $FFFF82AA (word) : VDE - Vertical Display End
                     56:        $FFFF82AC (word) : VSS - Vertical SS
                     57:        
                     58:        $FFFF82C0 (word) : VCO - Video control
                     59:        $FFFF82C2 (word) : VMD - Video mode
                     60: 
                     61:        $FFFF9800 (long) : VDL_PAL - Videl palette Register 000
                     62:        ...........
                     63:        $FFFF98FC (long) : VDL_PAL - Videl palette Register 255
1.1       root       64: */
1.1.1.6   root       65: 
1.1.1.4   root       66: const char VIDEL_fileid[] = "Hatari videl.c : " __DATE__ " " __TIME__;
1.1       root       67: 
1.1.1.6   root       68: #include <SDL_endian.h>
                     69: #include <SDL.h>
1.1       root       70: #include "main.h"
                     71: #include "configuration.h"
1.1.1.6   root       72: #include "memorySnapShot.h"
1.1       root       73: #include "ioMem.h"
1.1.1.6   root       74: #include "log.h"
1.1       root       75: #include "hostscreen.h"
                     76: #include "screen.h"
                     77: #include "stMemory.h"
                     78: #include "videl.h"
1.1.1.10  root       79: #include "video.h"                             /* for bUseHighRes variable, maybe unuseful (Laurent) */
                     80: #include "vdi.h"                               /* for bUseVDIRes variable,  maybe unuseful (Laurent) */
1.1       root       81: 
                     82: #define Atari2HostAddr(a) (&STRam[a])
                     83: #define VIDEL_COLOR_REGS_BEGIN 0xff9800
                     84: 
1.1.1.8   root       85: 
1.1.1.6   root       86: struct videl_s {
                     87:        bool   bUseSTShifter;                   /* whether to use ST or Falcon palette */
                     88:        Uint8  reg_ffff8006_save;               /* save reg_ffff8006 as it's a read only register */
                     89:        Uint8  monitor_type;                    /* 00 Monochrome (SM124) / 01 Color (SC1224) / 10 VGA Color / 11 Television ($FFFF8006) */
1.1.1.8   root       90:        Uint32 videoBaseAddr;                   /* Video base address, refreshed after each VBL */
1.1.1.6   root       91: 
1.1.1.8   root       92:        Sint16 leftBorderSize;                  /* Size of the left border */
                     93:        Sint16 rightBorderSize;                 /* Size of the right border */
                     94:        Sint16 upperBorderSize;                 /* Size of the upper border */
                     95:        Sint16 lowerBorderSize;                 /* Size of the lower border */
                     96:        Uint16 XSize;                           /* X size of the graphical area */
                     97:        Uint16 YSize;                           /* Y size of the graphical area */
                     98: 
                     99:        Uint16 save_scrWidth;                   /* save screen width to detect a change of X resolution */
                    100:        Uint16 save_scrHeight;                  /* save screen height to detect a change of Y resolution */
                    101:        Uint16 save_scrBpp;                     /* save screen Bpp to detect a change of bitplan mode */
1.1       root      102: 
1.1.1.8   root      103:        bool hostColorsSync;                    /* Sync palette with host's */
                    104: };
1.1.1.6   root      105: 
1.1.1.8   root      106: struct videl_zoom_s {
                    107:        Uint16 zoomwidth;
                    108:        Uint16 prev_scrwidth;
                    109:        Uint16 zoomheight;
                    110:        Uint16 prev_scrheight;
                    111:        int *zoomxtable;
                    112:        int *zoomytable;
                    113: };
1.1       root      114: 
1.1.1.8   root      115: static struct videl_s videl;
                    116: static struct videl_zoom_s videl_zoom;
1.1.1.6   root      117: 
1.1.1.8   root      118: Uint16 vfc_counter;                    /* counter for VFC register $ff82a0 (to be internalized when VIDEL emulation is complete) */
1.1.1.6   root      119: 
1.1.1.8   root      120: static void VIDEL_memset_uint32(Uint32 *addr, Uint32 color, int count);
                    121: static void VIDEL_memset_uint16(Uint16 *addr, Uint16 color, int count);
                    122: static void VIDEL_memset_uint8(Uint8 *addr, Uint8 color, int count);
1.1.1.10  root      123: 
1.1       root      124: 
1.1.1.8   root      125: /**
                    126:  *  Called upon startup and when CPU encounters a RESET instruction.
                    127:  */
1.1       root      128: void VIDEL_reset(void)
                    129: {
1.1.1.6   root      130:        videl.bUseSTShifter = false;                            /* Use Falcon color palette by default */
                    131:        videl.reg_ffff8006_save = IoMem_ReadByte(0xff8006);
1.1.1.8   root      132:        videl.monitor_type = videl.reg_ffff8006_save & 0xc0;
1.1.1.6   root      133:        
1.1.1.8   root      134:        videl.hostColorsSync = false; 
1.1       root      135: 
1.1.1.6   root      136:        vfc_counter = 0;
                    137:        
1.1       root      138:        /* Autozoom */
1.1.1.8   root      139:        videl_zoom.zoomwidth = 0;
                    140:        videl_zoom.prev_scrwidth = 0;
                    141:        videl_zoom.zoomheight = 0;
                    142:        videl_zoom.prev_scrheight = 0;
                    143:        videl_zoom.zoomxtable = NULL;
                    144:        videl_zoom.zoomytable = NULL;
1.1       root      145: 
1.1.1.4   root      146:        /* Default resolution to boot with */
1.1.1.8   root      147:        videl.save_scrWidth = 640;
                    148:        videl.save_scrHeight = 480;
                    149:        videl.save_scrBpp = ConfigureParams.Screen.nForceBpp;
1.1.1.11! root      150:        HostScreen_setWindowSize(videl.save_scrWidth, videl.save_scrHeight, videl.save_scrBpp, false);
1.1.1.4   root      151: 
                    152:        /* Reset IO register (some are not initialized by TOS) */
                    153:        IoMem_WriteWord(0xff820e, 0);    /* Line offset */
                    154:        IoMem_WriteWord(0xff8264, 0);    /* Horizontal scroll */
1.1.1.8   root      155: 
                    156:        /* Init synch mode register */
                    157:         VIDEL_SyncMode_WriteByte();
1.1       root      158: }
                    159: 
1.1.1.6   root      160: /**
                    161:  * Save/Restore snapshot of local variables ('MemorySnapShot_Store' handles type)
                    162:  */
                    163: void VIDEL_MemorySnapShot_Capture(bool bSave)
                    164: {
                    165:        /* Save/Restore details */
                    166:        MemorySnapShot_Store(&videl, sizeof(videl));
                    167:        MemorySnapShot_Store(&vfc_counter, sizeof(vfc_counter));
                    168: }
                    169: 
                    170: /**
1.1.1.10  root      171:  * Monitor write access to Falcon color palette registers
1.1.1.6   root      172:  */
1.1.1.10  root      173: void VIDEL_FalconColorRegsWrite(void)
1.1       root      174: {
1.1.1.10  root      175:        uint32_t color = IoMem_ReadLong(IoAccessBaseAddress & ~3);
                    176:        color &= 0xfcfc00fc;    /* Unused bits have to be set to 0 */
                    177:        IoMem_WriteLong(IoAccessBaseAddress & ~3, color);
1.1.1.8   root      178:        videl.hostColorsSync = false;
1.1       root      179: }
                    180: 
1.1.1.6   root      181: /**
                    182:  * VIDEL_Monitor_WriteByte : Contains memory and monitor configuration. 
1.1.1.8   root      183:  *                           This register is read only.
1.1.1.6   root      184:  */
                    185: void VIDEL_Monitor_WriteByte(void)
                    186: {
1.1.1.8   root      187:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8006 Monitor and memory conf write (Read only)\n");
1.1.1.6   root      188:        /* Restore hardware value */
1.1.1.8   root      189: 
1.1.1.6   root      190:        IoMem_WriteByte(0xff8006, videl.reg_ffff8006_save);
                    191: }
                    192: 
                    193: /**
1.1.1.8   root      194:  * VIDEL_SyncMode_WriteByte : Videl synchronization mode. 
                    195:  *             $FFFF820A [R/W] _______0  .................................. SYNC-MODE
                    196:                                      ||
                    197:                                      |+--Synchronisation [ 0:internal / 1:external ]
                    198:                                      +---Vertical frequency [ Read-only bit ]
                    199:                                          [ Monochrome monitor:0 / Colour monitor:1 ]
                    200:  */
                    201: void VIDEL_SyncMode_WriteByte(void)
                    202: {
                    203:        Uint8 syncMode = IoMem_ReadByte(0xff820a);
                    204:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff820a Sync Mode write: 0x%02x\n", syncMode);
                    205: 
                    206:        if (videl.monitor_type == FALCON_MONITOR_MONO)
                    207:                syncMode &= 0xfd;
                    208:        else
                    209:                syncMode |= 0x2;
                    210:        
                    211:        IoMem_WriteByte(0xff820a, syncMode);
                    212: }
                    213: 
                    214: /**
                    215:  * Read video address counter and update ff8205/07/09
                    216:  */
                    217: void VIDEL_ScreenCounter_ReadByte(void)
                    218: {
                    219: //     Uint32 addr;    // To be used
                    220:        Uint32 addr = 0; // To be removed
                    221: 
                    222:        // addr = Videl_CalculateAddress();             /* TODO: get current video address */
                    223:        IoMem[0xff8205] = ( addr >> 16 ) & 0xff;
                    224:        IoMem[0xff8207] = ( addr >> 8 ) & 0xff;
                    225:        IoMem[0xff8209] = addr & 0xff;
                    226: 
                    227:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8205/07/09 Sync Mode read: 0x%08x\n", addr);
                    228: }
                    229: 
                    230: /**
                    231:  * Write video address counter
                    232:  */
                    233: void VIDEL_ScreenCounter_WriteByte(void)
                    234: {
                    235:        Uint32 addr_new = 0;
                    236:        Uint8 AddrByte;
                    237: 
                    238:        AddrByte = IoMem[ IoAccessCurrentAddress ];
                    239: 
                    240:        /* Compute the new video address with one modified byte */
                    241:        if ( IoAccessCurrentAddress == 0xff8205 )
                    242:                addr_new = ( addr_new & 0x00ffff ) | ( AddrByte << 16 );
                    243:        else if ( IoAccessCurrentAddress == 0xff8207 )
                    244:                addr_new = ( addr_new & 0xff00ff ) | ( AddrByte << 8 );
                    245:        else if ( IoAccessCurrentAddress == 0xff8209 )
                    246:                addr_new = ( addr_new & 0xffff00 ) | ( AddrByte );
                    247: 
                    248:        // TODO: save the value in a table for the final rendering 
                    249: }
                    250: 
                    251: /**
                    252:  * VIDEL_LineOffset_WriteWord: $FFFF820E [R/W] W _______876543210  Line Offset
                    253:  * How many words are added to the end of display line, i.e. how many words are
                    254:  * 'behind' the display.
                    255:  */
                    256: void VIDEL_LineOffset_WriteWord(void)
                    257: {
1.1.1.9   root      258:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff820e Line Offset write: 0x%04x\n",
                    259:                  IoMem_ReadWord(0xff820e));
1.1.1.8   root      260: }
                    261: 
                    262: /**
                    263:  * VIDEL_Line_Width_WriteWord: $FFFF8210 [R/W] W ______9876543210 Line Width (VWRAP)
                    264:  * Length of display line in words.Or, how many words should be added to
                    265:  * vram counter after every display line.
                    266:  */
                    267: void VIDEL_Line_Width_WriteWord(void)
                    268: {
1.1.1.9   root      269:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8210 Line Width write: 0x%04x\n",
                    270:                  IoMem_ReadWord(0xff8210));
1.1.1.8   root      271: }
                    272: 
                    273: /**
1.1.1.6   root      274:  * Write to video address base high, med and low register (0xff8201/03/0d).
                    275:  * On Falcon, when a program writes to high or med registers, base low register
                    276:  * is reset to zero.
                    277:  */
                    278: void VIDEL_ScreenBase_WriteByte(void)
                    279: {
                    280:        if ((IoAccessCurrentAddress == 0xff8201) || (IoAccessCurrentAddress == 0xff8203)) {
                    281:                /* Reset screen base low register */
                    282:                IoMem[0xff820d] = 0;
                    283:        }
                    284: 
1.1.1.9   root      285:        LOG_TRACE(TRACE_VIDEL, "Videl : $%04x Screen base write: 0x%02x\t (screen: 0x%04x)\n",
                    286:                  IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress],
                    287:                  (IoMem[0xff8201]<<16) + (IoMem[0xff8203]<<8) + IoMem[0xff820d]);
1.1.1.6   root      288: }
                    289: 
                    290: /**
                    291:     VIDEL_ST_ShiftModeWriteByte : 
                    292:        $FFFF8260 [R/W] B  ______10  ST Shift Mode
                    293:                                 ||
                    294:                                 ||                           others   vga
                    295:                                 ||                  $FF8210 $FF82C2 $FF82C2
                    296:                                 00--4BP/320 Pixels=> $0050   $0000   $0005
                    297:                                 01--2BP/640 Pixels=> $0050   $0004   $0009
                    298:                                 10--1BP/640 Pixels=> $0028   $0006   $0008
                    299:                                 11--???/320 Pixels=> $0050   $0000   $0000
                    300: 
                    301:        Writing to this register does the following things:
                    302:                - activate STE palette
                    303:                - sets line width ($ffff8210)
                    304:                - sets video mode in $ffff82c2 (double lines/interlace & cycles/pixel)
                    305:  */
                    306: void VIDEL_ST_ShiftModeWriteByte(void)
                    307: {
                    308:        Uint16 line_width, video_mode;
                    309:        Uint8 st_shiftMode;
                    310: 
                    311:        st_shiftMode = IoMem_ReadByte(0xff8260);
1.1.1.8   root      312:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8260 ST Shift Mode (STSHIFT) write: 0x%02x\n", st_shiftMode);
                    313: 
                    314:        /* Bits 2-7 are set to 0 */
                    315:        IoMem_WriteByte(0xff8260, st_shiftMode & 3); 
1.1.1.6   root      316: 
                    317:        /* Activate STE palette */
                    318:        videl.bUseSTShifter = true;
                    319: 
                    320:        /*  Compute line width and video mode */
                    321:        switch (st_shiftMode & 0x3) {
                    322:                case 0: /* 4BP/320 Pixels */
                    323:                        line_width = 0x50;
                    324:                        /* half pixels + double lines vs. no scaling */
                    325:                        video_mode = videl.monitor_type == FALCON_MONITOR_VGA ? 0x5 : 0x0;
                    326:                        break;
                    327:                case 1: /* 2BP/640 Pixels */
                    328:                        line_width = 0x50;
                    329:                        /* quarter pixels + double lines vs. half pixels */
                    330:                        video_mode = videl.monitor_type == FALCON_MONITOR_VGA ? 0x9 : 0x4;
                    331:                        break;
                    332:                case 2: /* 1BP/640 Pixels */
                    333:                        line_width = 0x28;
                    334:                        if (videl.monitor_type == FALCON_MONITOR_MONO) {
                    335:                                video_mode = 0x0;
                    336:                                break;
                    337:                        }
                    338:                        /* quarter pixels vs. half pixels + interlace */
                    339:                        video_mode = videl.monitor_type == FALCON_MONITOR_VGA ? 0x8 : 0x6;
                    340:                        break;
                    341:                case 3: /* ???/320 Pixels */
1.1.1.8   root      342:                default:
1.1.1.6   root      343:                        line_width = 0x50;
                    344:                        video_mode = 0x0;
                    345:                        break;
                    346:        }
                    347: 
                    348:        /* Set line width ($FFFF8210) */
                    349:        IoMem_WriteWord(0xff8210, line_width); 
                    350:        
                    351:        /* Set video mode ($FFFF82C2) */
                    352:        IoMem_WriteWord(0xff82c2, video_mode); 
                    353: }
                    354: 
                    355: /**
1.1.1.8   root      356:     VIDEL_HorScroll64_WriteByte : Horizontal scroll register (0-15)
                    357:                $FFFF8264 [R/W] ________  ................................ H-SCROLL HI
                    358:                                    ||||  [ Shadow register for $FFFF8265 ]
                    359:                                    ++++--Pixel shift [ 0:normal / 1..15:Left shift ]
                    360:                                        [ Change in line-width NOT required ]
                    361:  */
                    362: void VIDEL_HorScroll64_WriteByte(void)
                    363: {
1.1.1.9   root      364:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8264 Horizontal scroll 64 write: 0x%02x\n",
                    365:                  IoMem_ReadByte(0xff8264));
1.1.1.8   root      366: }
                    367: 
                    368: /**
                    369:     VIDEL_HorScroll65_WriteByte : Horizontal scroll register (0-15)
                    370:                $FFFF8265 [R/W] ____3210  .................................H-SCROLL LO
                    371:                                    ||||
                    372:                                    ++++--Pixel [ 0:normal / 1..15:Left shift ]
                    373:                                        [ Change in line-width NOT required ]
                    374:  */
                    375: void VIDEL_HorScroll65_WriteByte(void)
                    376: {
1.1.1.9   root      377:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8265 Horizontal scroll 65 write: 0x%02x\n",
                    378:                  IoMem_ReadByte(0xff8265));
1.1.1.8   root      379: }
                    380: 
                    381: /**
                    382:     VIDEL_Falcon_ShiftMode_WriteWord :
1.1.1.6   root      383:        $FFFF8266 [R/W] W  _____A98_6543210  Falcon Shift Mode (SPSHIFT)
                    384:                                ||| |||||||
1.1.1.8   root      385:                                ||| |||++++- 0..15: Colourbank choice from 256-colour table in 16 colour multiples
                    386:                                ||| ||+----- 8 Bitplanes mode (256 Colors) [0:off / 1:on]
                    387:                                ||| |+------ Vertical Sync [0: internal / 1: external]
                    388:                                ||| +------- Horizontal Sync [0: internal / 1: external]
                    389:                                ||+--------- True-Color-Mode [0:off / 1:on]
                    390:                                |+---------- Overlay-Mode [0:off / 1:on]
                    391:                                +----------- 0: 2-Color-Mode [0:off / 1:on]
1.1.1.6   root      392: 
                    393:        Writing to this register does the following things:
                    394:                - activate Falcon palette
                    395:                - if you set Bits A/8/4 == 0, it selects 16-Color-Falcon-Mode (NOT the
                    396:                  same as ST LOW since Falcon palette is used!)
                    397:                - $8260 register is ignored, you don't need to write here anything
                    398: 
                    399:        Note: 4-Color-Mode isn't realisable with Falcon palette.
                    400:  */
1.1.1.8   root      401: void VIDEL_Falcon_ShiftMode_WriteWord(void)
1.1.1.6   root      402: {
1.1.1.9   root      403:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8266 Falcon Shift Mode (SPSHIFT) write: 0x%04x\n",
                    404:                  IoMem_ReadWord(0xff8266));
1.1.1.6   root      405: 
                    406:        videl.bUseSTShifter = false;
                    407: }
                    408: 
                    409: /**
                    410:  *  Write Horizontal Hold Counter (HHC)
                    411:  */
                    412: void VIDEL_HHC_WriteWord(void)
                    413: {
1.1.1.9   root      414:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8280 Horizontal Hold Counter (HHC) write: 0x%04x\n",
                    415:                  IoMem_ReadWord(0xff8280));
1.1.1.6   root      416: }
                    417: 
                    418: /**
                    419:  *  Write Horizontal Hold Timer (HHT)
                    420:  */
                    421: void VIDEL_HHT_WriteWord(void)
                    422: {
1.1.1.9   root      423:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8282 Horizontal Hold Timer (HHT) write: 0x%04x\n",
                    424:                  IoMem_ReadWord(0xff8282));
1.1.1.6   root      425: }
                    426: 
                    427: /**
                    428:  *  Write Horizontal Border Begin (HBB)
                    429:  */
                    430: void VIDEL_HBB_WriteWord(void)
                    431: {
1.1.1.9   root      432:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8284 Horizontal Border Begin (HBB) write: 0x%04x\n",
                    433:                  IoMem_ReadWord(0xff8284));
1.1.1.6   root      434: }
                    435: 
                    436: /**
                    437:  *  Write Horizontal Border End (HBE)
                    438:  */
                    439: void VIDEL_HBE_WriteWord(void)
                    440: {
1.1.1.9   root      441:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8286 Horizontal Border End (HBE) write: 0x%04x\n",
                    442:                  IoMem_ReadWord(0xff8286));
1.1.1.6   root      443: }
                    444: 
                    445: /**
                    446:  *  Write Horizontal Display Begin (HDB)
1.1.1.8   root      447:        $FFFF8288 [R/W] W ______9876543210  Horizontal Display Begin (HDB)
                    448:                                |
                    449:                                +---------- Display will start in [0: 1st halfline / 1: 2nd halfline]
1.1.1.6   root      450:  */
                    451: void VIDEL_HDB_WriteWord(void)
                    452: {
1.1.1.9   root      453:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8288 Horizontal Display Begin (HDB) write: 0x%04x\n",
                    454:                  IoMem_ReadWord(0xff8288));
1.1.1.6   root      455: }
                    456: 
                    457: /**
                    458:  *  Write Horizontal Display End (HDE)
                    459:  */
                    460: void VIDEL_HDE_WriteWord(void)
                    461: {
1.1.1.9   root      462:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff828a Horizontal Display End (HDE) write: 0x%04x\n",
                    463:                  IoMem_ReadWord(0xff828a));
1.1.1.6   root      464: }
                    465: 
                    466: /**
                    467:  *  Write Horizontal SS (HSS)
                    468:  */
                    469: void VIDEL_HSS_WriteWord(void)
                    470: {
1.1.1.9   root      471:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff828c Horizontal SS (HSS) write: 0x%04x\n",
                    472:                  IoMem_ReadWord(0xff828c));
1.1.1.6   root      473: }
                    474: 
                    475: /**
                    476:  *  Write Horizontal FS (HFS)
                    477:  */
                    478: void VIDEL_HFS_WriteWord(void)
                    479: {
1.1.1.9   root      480:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff828e Horizontal FS (HFS) write: 0x%04x\n",
                    481:                  IoMem_ReadWord(0xff828e));
1.1.1.6   root      482: }
                    483: 
                    484: /**
                    485:  *  Write Horizontal EE (HEE)
                    486:  */
                    487: void VIDEL_HEE_WriteWord(void)
                    488: {
1.1.1.9   root      489:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8290 Horizontal EE (HEE) write: 0x%04x\n",
                    490:                  IoMem_ReadWord(0xff8290));
1.1.1.6   root      491: }
                    492: 
                    493: /**
                    494:  *  Write Vertical Frequency Counter (VFC)
                    495:  */
                    496: void VIDEL_VFC_ReadWord(void)
                    497: {
                    498:        IoMem_WriteWord(0xff82a0, vfc_counter);
1.1.1.8   root      499:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a0 Vertical Frequency Counter (VFC) read: 0x%04x\n", vfc_counter);
1.1.1.6   root      500: }
                    501: 
                    502: /**
                    503:  *  Write Vertical Frequency Timer (VFT)
                    504:  */
                    505: void VIDEL_VFT_WriteWord(void)
                    506: {
1.1.1.9   root      507:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a2 Vertical Frequency Timer (VFT) write: 0x%04x\n",
                    508:                  IoMem_ReadWord(0xff82a2));
1.1.1.6   root      509: }
                    510: 
                    511: /**
                    512:  *  Write Vertical Border Begin (VBB)
                    513:  */
                    514: void VIDEL_VBB_WriteWord(void)
                    515: {
1.1.1.9   root      516:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a4 Vertical Border Begin (VBB) write: 0x%04x\n",
                    517:                  IoMem_ReadWord(0xff82a4));
1.1.1.6   root      518: }
                    519: 
                    520: /**
                    521:  *  Write Vertical Border End (VBE)
                    522:  */
                    523: void VIDEL_VBE_WriteWord(void)
                    524: {
1.1.1.9   root      525:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a6 Vertical Border End (VBE) write: 0x%04x\n",
                    526:                  IoMem_ReadWord(0xff82a6));
1.1.1.6   root      527: }
                    528: 
                    529: /**
                    530:  *  Write Vertical Display Begin (VDB)
                    531:  */
                    532: void VIDEL_VDB_WriteWord(void)
1.1       root      533: {
1.1.1.9   root      534:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a8 Vertical Display Begin (VDB) write: 0x%04x\n",
                    535:                  IoMem_ReadWord(0xff82a8));
1.1       root      536: }
                    537: 
1.1.1.6   root      538: /**
                    539:  *  Write Vertical Display End (VDE)
                    540:  */
                    541: void VIDEL_VDE_WriteWord(void)
                    542: {
1.1.1.9   root      543:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff82aa Vertical Display End (VDE) write: 0x%04x\n",
                    544:                  IoMem_ReadWord(0xff82aa));
1.1.1.6   root      545: }
                    546: 
                    547: /**
                    548:  *  Write Vertical SS (VSS)
                    549:  */
                    550: void VIDEL_VSS_WriteWord(void)
                    551: {
1.1.1.9   root      552:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff82ac Vertical SS (VSS) write: 0x%04x\n",
                    553:                  IoMem_ReadWord(0xff82ac));
1.1.1.6   root      554: }
                    555: 
                    556: /**
                    557:  *  Write Video Control (VCO)
                    558:  */
                    559: void VIDEL_VCO_WriteWord(void)
                    560: {
1.1.1.9   root      561:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff82c0 Video control (VCO) write: 0x%04x\n",
                    562:                  IoMem_ReadWord(0xff82c0));
1.1.1.6   root      563: }
                    564: 
                    565: /**
                    566:  *  Write Video Mode (VDM)
                    567:  */
                    568: void VIDEL_VMD_WriteWord(void)
                    569: {
1.1.1.9   root      570:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff82c2 Video Mode (VDM) write: 0x%04x\n",
                    571:                  IoMem_ReadWord(0xff82c2));
1.1.1.6   root      572: }
                    573: 
                    574: 
1.1.1.8   root      575: /**
                    576:  *  VIDEL_getVideoramAddress: returns the video RAM address.
                    577:  *  On Falcon, video address must be a multiple of four in bitplane modes.
                    578:  */
                    579: static Uint32 VIDEL_getVideoramAddress(void)
1.1       root      580: {
1.1.1.8   root      581:        Uint32 videoBase;
                    582:        
                    583:        videoBase  = (Uint32) IoMem_ReadByte(0xff8201) << 16;
                    584:        videoBase |= (Uint32) IoMem_ReadByte(0xff8203) << 8;
                    585:        videoBase |= IoMem_ReadByte(0xff820d) & ~3;
                    586:        
                    587:        return videoBase;
1.1       root      588: }
                    589: 
1.1.1.8   root      590: static Uint16 VIDEL_getScreenBpp(void)
1.1       root      591: {
1.1.1.8   root      592:        Uint16 f_shift = IoMem_ReadWord(0xff8266);
                    593:        Uint16 bits_per_pixel;
                    594:        Uint8  st_shift = IoMem_ReadByte(0xff8260);
                    595: 
1.1       root      596:        /* to get bpp, we must examine f_shift and st_shift.
1.1.1.8   root      597:         * f_shift is valid if any of bits no. 10, 8 or 4 is set. 
                    598:         * Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
1.1       root      599:         * if bit 10 set then bit 8 and bit 4 don't care...
                    600:         * If all these bits are 0 and ST shifter is written
                    601:         * after Falcon one, get display depth from st_shift
                    602:         * (as for ST and STE)
                    603:         */
                    604:        if (f_shift & 0x400)            /* Falcon: 2 colors */
                    605:                bits_per_pixel = 1;
                    606:        else if (f_shift & 0x100)       /* Falcon: hicolor */
                    607:                bits_per_pixel = 16;
                    608:        else if (f_shift & 0x010)       /* Falcon: 8 bitplanes */
                    609:                bits_per_pixel = 8;
1.1.1.6   root      610:        else if (!videl.bUseSTShifter)  /* Falcon: 4 bitplanes */
1.1       root      611:                bits_per_pixel = 4;
                    612:        else if (st_shift == 0)
                    613:                bits_per_pixel = 4;
                    614:        else if (st_shift == 0x01)
                    615:                bits_per_pixel = 2;
                    616:        else /* if (st_shift == 0x02) */
                    617:                bits_per_pixel = 1;
                    618: 
1.1.1.8   root      619: /*     LOG_TRACE(TRACE_VIDEL, "Videl works in %d bpp, f_shift=%04x, st_shift=%d", bits_per_pixel, f_shift, st_shift); */
1.1       root      620: 
                    621:        return bits_per_pixel;
                    622: }
                    623: 
1.1.1.8   root      624: /**
                    625:  *  VIDEL_getScreenWidth : returns the visible X resolution
                    626:  *     left border + graphic area + right border
                    627:  *     left border  : hdb - hbe-offset
                    628:  *     right border : hbb - hde-offset
                    629:  *     Graphics display : starts at cycle HDB and ends at cycle HDE. 
                    630:  */
1.1       root      631: static int VIDEL_getScreenWidth(void)
                    632: {
1.1.1.9   root      633:        Uint16 hbb, hbe, hdb, hde, vdm, hht;
                    634:        Uint16 cycPerPixel, divider;
                    635:        Sint16 hdb_offset, hde_offset;
                    636:        Sint16 leftBorder, rightBorder;
1.1.1.8   root      637:        Uint16 bpp = VIDEL_getScreenBpp();
                    638: 
                    639:        /* X Size of the Display area */
                    640:        videl.XSize = (IoMem_ReadWord(0xff8210) & 0x03ff) * 16 / bpp;
                    641: 
                    642:        /* If the user disabled the borders display from the gui, we suppress them */
                    643:        if (ConfigureParams.Screen.bAllowOverscan == 0) {
                    644:                videl.leftBorderSize = 0;
                    645:                videl.rightBorderSize = 0;
                    646:                return videl.XSize;
                    647:        }
                    648: 
                    649:        /* According to Aura and Animal Mine doc about Videl, if a monochrome monitor is connected,
                    650:         * HDB and HDE have no significance and no border is displayed.
                    651:         */
                    652:        if (videl.monitor_type == FALCON_MONITOR_MONO) {
                    653:                videl.leftBorderSize = 0;
                    654:                videl.rightBorderSize = 0;
                    655:                return videl.XSize;
                    656:        }
                    657: 
1.1.1.9   root      658:        hbb = IoMem_ReadWord(0xff8284) & 0x01ff;
                    659:        hbe = IoMem_ReadWord(0xff8286) & 0x01ff;
                    660:        hdb = IoMem_ReadWord(0xff8288) & 0x01ff;
                    661:        hde = IoMem_ReadWord(0xff828a) & 0x01ff;
                    662:        vdm = IoMem_ReadWord(0xff82c2) & 0xc;
                    663:        hht = IoMem_ReadWord(0xff8282) & 0x1ff;
1.1.1.8   root      664: 
                    665:        /* Compute cycles per pixel */
                    666:        if (vdm == 0)
                    667:                cycPerPixel = 4;
                    668:        else if (vdm == 4)
                    669:                cycPerPixel = 2;
                    670:        else
                    671:                cycPerPixel = 1;
                    672: 
                    673:        /* Compute the divider */
                    674:        if (videl.monitor_type == FALCON_MONITOR_VGA) {
                    675:                if (cycPerPixel == 4)
                    676:                        divider = 4;
                    677:                else
                    678:                        divider = 2;
                    679:        }
                    680:        else if (videl.bUseSTShifter == true) {
                    681:                divider = 16;
                    682:        }
                    683:        else {
                    684:                divider = cycPerPixel;
                    685:        }
                    686: 
                    687:        /* Compute hdb_offset and hde_offset */
                    688:        if (videl.bUseSTShifter == false) {
                    689:                if (bpp < 16) {
                    690:                        /* falcon mode bpp */
                    691:                        hdb_offset = ((64+(128/bpp + 16 + 2) * cycPerPixel) / divider ) + 1;
                    692:                        hde_offset = ((128/bpp + 2) * cycPerPixel) / divider;
                    693:                }
                    694:                else {
                    695:                        /* falcon mode true color */
                    696:                        hdb_offset = ((64 + 16 * cycPerPixel) / divider ) + 1;
                    697:                        hde_offset = 0;
                    698:                }
                    699:        }
                    700:        else {
                    701:                /* ST bitplan mode */
                    702:                hdb_offset = ((128+(128/bpp + 2) * cycPerPixel) / divider ) + 1;
                    703:                hde_offset = ((128/bpp + 2) * cycPerPixel) / divider;
                    704:        }
                    705: 
                    706:        LOG_TRACE(TRACE_VIDEL, "hdb_offset=%04x,    hde_offset=%04x\n", hdb_offset, hde_offset);
                    707: 
                    708:        /* Compute left border size in cycles */
                    709:        if (IoMem_ReadWord(0xff8288) & 0x0200)
                    710:                leftBorder = hdb - hbe + hdb_offset - hht - 2;
                    711:        else
                    712:                leftBorder = hdb - hbe + hdb_offset;
                    713: 
                    714:        /* Compute right border size in cycles */
                    715:        rightBorder = hbb - hde_offset - hde;
                    716: 
                    717:        videl.leftBorderSize = leftBorder / cycPerPixel;
                    718:        videl.rightBorderSize = rightBorder / cycPerPixel;
                    719:        LOG_TRACE(TRACE_VIDEL, "left border size=%04x,    right border size=%04x\n", videl.leftBorderSize, videl.rightBorderSize);
                    720: 
                    721:        if (videl.leftBorderSize < 0) {
                    722: //             fprintf(stderr, "BORDER LEFT < 0   %d\n", videl.leftBorderSize);
                    723:                videl.leftBorderSize = 0;
                    724:        }
                    725:        if (videl.rightBorderSize < 0) {
                    726: //             fprintf(stderr, "BORDER RIGHT < 0   %d\n", videl.rightBorderSize);
                    727:                videl.rightBorderSize = 0;
                    728:        }
                    729: 
                    730:        return videl.leftBorderSize + videl.XSize + videl.rightBorderSize;
1.1       root      731: }
                    732: 
1.1.1.8   root      733: /**
                    734:  *  VIDEL_getScreenHeight : returns the visible Y resolution
                    735:  *     upper border + graphic area + lower border
                    736:  *     upper border : vdb - vbe
                    737:  *     lower border : vbb - vde
                    738:  *     Graphics display : starts at line VDB and ends at line VDE. 
                    739:  *     If interlace mode off unit of VC-registers is half lines, else lines.
                    740:  */
1.1       root      741: static int VIDEL_getScreenHeight(void)
                    742: {
1.1.1.8   root      743:        Uint16 vbb = IoMem_ReadWord(0xff82a4) & 0x07ff;
                    744:        Uint16 vbe = IoMem_ReadWord(0xff82a6) & 0x07ff;  
                    745:        Uint16 vdb = IoMem_ReadWord(0xff82a8) & 0x07ff;
                    746:        Uint16 vde = IoMem_ReadWord(0xff82aa) & 0x07ff;
                    747:        Uint16 vmode = IoMem_ReadWord(0xff82c2);
                    748: 
                    749:        /* According to Aura and Animal Mine doc about Videl, if a monochrome monitor is connected,
                    750:         * VDB and VDE have no significance and no border is displayed.
1.1       root      751:         */
1.1.1.8   root      752:        if (videl.monitor_type == FALCON_MONITOR_MONO) {
                    753:                videl.upperBorderSize = 0;
                    754:                videl.lowerBorderSize = 0;
                    755:        }
                    756:        else {
                    757:                /* We must take the positive value only, as a program like AceTracker starts the */
                    758:                /* graphical area 1 line before the end of the upper border */
                    759:                videl.upperBorderSize = vdb - vbe > 0 ? vdb - vbe : 0;
                    760:                videl.lowerBorderSize = vbb - vde > 0 ? vbb - vde : 0;
                    761:        }
1.1       root      762: 
1.1.1.8   root      763:        /* Y Size of the Display area */
1.1.1.9   root      764:        if (vde >= vdb) {
                    765:                videl.YSize = vde - vdb;
                    766:        }
                    767:        else {
                    768:                LOG_TRACE(TRACE_VIDEL, "WARNING: vde=0x%x is less than vdb=0x%x\n",
                    769:                          vde, vdb);
                    770:        }
1.1.1.8   root      771: 
                    772:        /* If the user disabled the borders display from the gui, we suppress them */
                    773:        if (ConfigureParams.Screen.bAllowOverscan == 0) {
                    774:                videl.upperBorderSize = 0;
                    775:                videl.lowerBorderSize = 0;
                    776:        }
                    777: 
                    778:        if (!(vmode & 0x02)){           /* interlace */
                    779:                videl.YSize >>= 1;
                    780:                videl.upperBorderSize >>= 1;
                    781:                videl.lowerBorderSize >>= 1;
                    782:        }
                    783:        
                    784:        if (vmode & 0x01) {             /* double */
                    785:                videl.YSize >>= 1;
                    786:                videl.upperBorderSize >>= 1;
                    787:                videl.lowerBorderSize >>= 1;
                    788:        }
1.1.1.9   root      789: 
1.1.1.8   root      790:        return videl.upperBorderSize + videl.YSize + videl.lowerBorderSize;
1.1       root      791: }
                    792: 
1.1.1.5   root      793: #if 0
                    794: /* this is easier & more robustly done in hostscreen.c just by
                    795:  * comparing requested screen width & height to each other.
                    796:  */
                    797: static void VIDEL_getMonitorScale(int *sx, int *sy)
                    798: {
                    799:        /* Videl video mode register bits and resulting desktop resolution:
                    800:         * 
                    801:         * quarter, half, interlace, double:   pixels: -> zoom:
                    802:         * rgb:
                    803:         *    0       0       0         0      320x200 -> 2 x 2
                    804:         *    0       0       1         0      320x400 -> 2 x 1
                    805:         *    0       1       0         0      640x200 -> 1 x 2 !
                    806:         *    0       1       1         0      640x400 -> 1 x 1
                    807:         * vga:
                    808:         *    0       0       0         1      (just double ?)
                    809:         *    0       0       1         1      (double & interlace ???)
                    810:         *    0       1       0         0      320x480 -> 2 x 1 !
                    811:         *    0       1       0         1      320x240 -> 2 x 2
                    812:         *    0       1       1         1      (double + interlace ???)
                    813:         *    1       0       0         0      640x480 -> 1 x 1
                    814:         *    1       0       0         1      640x240 -> 1 x 2
                    815:         */
1.1.1.8   root      816:        int vmode = IoMem_ReadWord(0xff82c2);
1.1.1.5   root      817: 
                    818:        /* half pixel seems to have opposite meaning on
                    819:         * VGA and RGB monitor, so they need to handled separately
                    820:         */
1.1.1.6   root      821:        if (videl.monitor_type) == FALCON_MONITOR_VGA) {
1.1.1.8   root      822:                if (vmode & 0x08) {  /* quarter pixel */
1.1.1.5   root      823:                        *sx = 1;
                    824:                } else {
                    825:                        *sx = 2;
                    826:                }
1.1.1.8   root      827:                if (vmode & 0x01) {  /* double line */
1.1.1.5   root      828:                        *sy = 2;
                    829:                } else {
                    830:                        *sy = 1;
                    831:                }
                    832:        } else {
1.1.1.8   root      833:                if (vmode & 0x04) {  /* half pixel */
1.1.1.5   root      834:                        *sx = 1;
                    835:                } else {
                    836:                        *sx = 2;
                    837:                }
1.1.1.8   root      838:                if (vmode & 0x02) {  /* interlace used only on RGB ? */
1.1.1.5   root      839:                        *sy = 1;
                    840:                } else {
                    841:                        *sy = 2;
                    842:                }
                    843:        }
                    844: }
                    845: #endif
                    846: 
1.1       root      847: 
                    848: /** map the correct colortable into the correct pixel format
                    849:  */
                    850: static void VIDEL_updateColors(void)
                    851: {
1.1.1.8   root      852:        int i, r, g, b, colors = 1 << videl.save_scrBpp;
1.1       root      853: 
1.1.1.8   root      854: #define F_COLORS(i) IoMem_ReadByte(VIDEL_COLOR_REGS_BEGIN + (i))
                    855: #define STE_COLORS(i)  IoMem_ReadByte(0xff8240 + (i))
1.1       root      856: 
1.1.1.6   root      857:        if (!videl.bUseSTShifter) {
1.1       root      858:                for (i = 0; i < colors; i++) {
                    859:                        int offset = i << 2;
                    860:                        r = F_COLORS(offset) & 0xfc;
                    861:                        r |= r>>6;
                    862:                        g = F_COLORS(offset + 1) & 0xfc;
                    863:                        g |= g>>6;
                    864:                        b = F_COLORS(offset + 3) & 0xfc;
                    865:                        b |= b>>6;
                    866:                        HostScreen_setPaletteColor(i, r,g,b);
                    867:                }
                    868:                HostScreen_updatePalette(colors);
                    869:        } else {
                    870:                for (i = 0; i < colors; i++) {
                    871:                        int offset = i << 1;
                    872:                        r = STE_COLORS(offset) & 0x0f;
                    873:                        r = ((r & 7)<<1)|(r>>3);
                    874:                        r |= r<<4;
                    875:                        g = (STE_COLORS(offset + 1)>>4) & 0x0f;
                    876:                        g = ((g & 7)<<1)|(g>>3);
                    877:                        g |= g<<4;
                    878:                        b = STE_COLORS(offset + 1) & 0x0f;
                    879:                        b = ((b & 7)<<1)|(b>>3);
                    880:                        b |= b<<4;
                    881:                        HostScreen_setPaletteColor(i, r,g,b);
                    882:                }
                    883:                HostScreen_updatePalette(colors);
                    884:        }
                    885: 
1.1.1.8   root      886:        videl.hostColorsSync = true;
1.1       root      887: }
                    888: 
                    889: 
1.1.1.11! root      890: void VIDEL_ZoomModeChanged(bool bForceChange)
1.1       root      891: {
                    892:        /* User selected another zoom mode, so set a new screen resolution now */
1.1.1.11! root      893:        HostScreen_setWindowSize(videl.save_scrWidth, videl.save_scrHeight,
        !           894:                                 videl.save_scrBpp == 16 ? 16 : ConfigureParams.Screen.nForceBpp,
        !           895:                                 bForceChange);
1.1       root      896: }
                    897: 
                    898: 
1.1.1.2   root      899: bool VIDEL_renderScreen(void)
1.1       root      900: {
1.1.1.8   root      901:        /* Atari screen infos */
1.1       root      902:        int vw   = VIDEL_getScreenWidth();
                    903:        int vh   = VIDEL_getScreenHeight();
                    904:        int vbpp = VIDEL_getScreenBpp();
1.1.1.8   root      905: 
                    906:        int lineoffset = IoMem_ReadWord(0xff820e) & 0x01ff; /* 9 bits */
                    907:        int linewidth = IoMem_ReadWord(0xff8210) & 0x03ff;  /* 10 bits */
1.1.1.9   root      908:        int nextline;
1.1.1.8   root      909: 
1.1.1.6   root      910:        bool change = false;
1.1       root      911: 
1.1.1.9   root      912:        videl.videoBaseAddr = VIDEL_getVideoramAddress(); // Todo: to be removed when all code is in Videl
                    913: 
1.1.1.8   root      914:        if (vw > 0 && vw != videl.save_scrWidth) {
                    915:                LOG_TRACE(TRACE_VIDEL, "Videl : width change from %d to %d\n", videl.save_scrWidth, vw);
                    916:                videl.save_scrWidth = vw;
1.1.1.6   root      917:                change = true;
1.1       root      918:        }
1.1.1.8   root      919:        if (vh > 0 && vh != videl.save_scrHeight) {
                    920:                LOG_TRACE(TRACE_VIDEL, "Videl : height change from %d to %d\n", videl.save_scrHeight, vh);
                    921:                videl.save_scrHeight = vh;
1.1.1.6   root      922:                change = true;
1.1       root      923:        }
1.1.1.8   root      924:        if (vbpp != videl.save_scrBpp) {
                    925:                LOG_TRACE(TRACE_VIDEL, "Videl : bpp change from %d to %d\n", videl.save_scrBpp, vbpp);
                    926:                videl.save_scrBpp = vbpp;
1.1.1.6   root      927:                change = true;
                    928:        }
                    929:        if (change) {
1.1.1.8   root      930:                LOG_TRACE(TRACE_VIDEL, "Videl : video mode change to %dx%d@%d\n", videl.save_scrWidth, videl.save_scrHeight, videl.save_scrBpp);
1.1.1.11! root      931:                HostScreen_setWindowSize(videl.save_scrWidth, videl.save_scrHeight, videl.save_scrBpp == 16 ? 16 : ConfigureParams.Screen.nForceBpp, false);
1.1       root      932:        }
                    933: 
                    934:        if (!HostScreen_renderBegin())
1.1.1.2   root      935:                return false;
1.1       root      936: 
1.1.1.8   root      937:        /* 
                    938:           I think this implementation is naive: 
                    939:           indeed, I suspect that we should instead skip lineoffset
                    940:           words each time we have read "more" than linewidth words
                    941:           (possibly "more" because of the number of bit planes).
                    942:           Moreover, the 1 bit plane mode is particular;
                    943:           while doing some experiments on my Falcon, it seems to
                    944:           behave like the 4 bit planes mode.
                    945:           At last, we have also to take into account the 4 bits register
                    946:           located at the word $ffff8264 (bit offset). This register makes
                    947:           the semantics of the lineoffset register change a little.
                    948:           int bitoffset = IoMem_ReadWord(0xff8264) & 0x000f;
                    949:           The meaning of this register in True Color mode is not clear
                    950:           for me at the moment (and my experiments on the Falcon don't help
                    951:           me).
                    952:        */
1.1.1.9   root      953:        nextline = linewidth + lineoffset;
1.1.1.8   root      954: 
1.1.1.11! root      955:        if ((vw < 32) || (vh < 32)) {
        !           956:                LOG_TRACE(TRACE_VIDEL, "Videl : %dx%d screen size, not drawing\n", vw, vh);
1.1.1.8   root      957:                return false;
1.1.1.11! root      958:        }
1.1.1.8   root      959:        if (videl.save_scrBpp < 16 && videl.hostColorsSync == 0)
                    960:                VIDEL_updateColors();
                    961: 
1.1.1.5   root      962:        if (nScreenZoomX * nScreenZoomY != 1) {
1.1.1.8   root      963:                VIDEL_ConvertScreenZoom(vw, vh, videl.save_scrBpp, nextline);
1.1       root      964:        } else {
1.1.1.8   root      965:                VIDEL_ConvertScreenNoZoom(vw, vh, videl.save_scrBpp, nextline);
1.1       root      966:        }
                    967: 
1.1.1.10  root      968:        HostScreen_update1(HostScreen_renderEnd(), false);
1.1.1.2   root      969: 
                    970:        return true;
1.1       root      971: }
                    972: 
                    973: 
1.1.1.4   root      974: /**
                    975:  * Performs conversion from the TOS's bitplane word order (big endian) data
                    976:  * into the native chunky color index.
                    977:  */
1.1.1.8   root      978: static void VIDEL_bitplaneToChunky(Uint16 *atariBitplaneData, Uint16 bpp,
1.1.1.4   root      979:                                    Uint8 colorValues[16])
                    980: {
                    981:        Uint32 a, b, c, d, x;
                    982: 
                    983:        /* Obviously the different cases can be broken out in various
                    984:         * ways to lessen the amount of work needed for <8 bit modes.
                    985:         * It's doubtful if the usage of those modes warrants it, though.
                    986:         * The branches below should be ~100% correctly predicted and
                    987:         * thus be more or less for free.
                    988:         * Getting the palette values inline does not seem to help
                    989:         * enough to worry about. The palette lookup is much slower than
                    990:         * this code, though, so it would be nice to do something about it.
                    991:         */
                    992:        if (bpp >= 4) {
                    993:                d = *(Uint32 *)&atariBitplaneData[0];
                    994:                c = *(Uint32 *)&atariBitplaneData[2];
                    995:                if (bpp == 4) {
                    996:                        a = b = 0;
                    997:                } else {
                    998:                        b = *(Uint32 *)&atariBitplaneData[4];
                    999:                        a = *(Uint32 *)&atariBitplaneData[6];
                   1000:                }
                   1001:        } else {
                   1002:                a = b = c = 0;
                   1003:                if (bpp == 2) {
                   1004:                        d = *(Uint32 *)&atariBitplaneData[0];
                   1005:                } else {
                   1006: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
                   1007:                        d = atariBitplaneData[0]<<16;
                   1008: #else
                   1009:                        d = atariBitplaneData[0];
                   1010: #endif
                   1011:                }
                   1012:        }
                   1013: 
                   1014:        x = a;
                   1015:        a =  (a & 0xf0f0f0f0)       | ((c & 0xf0f0f0f0) >> 4);
                   1016:        c = ((x & 0x0f0f0f0f) << 4) |  (c & 0x0f0f0f0f);
                   1017:        x = b;
                   1018:        b =  (b & 0xf0f0f0f0)       | ((d & 0xf0f0f0f0) >> 4);
                   1019:        d = ((x & 0x0f0f0f0f) << 4) |  (d & 0x0f0f0f0f);
                   1020: 
                   1021:        x = a;
                   1022:        a =  (a & 0xcccccccc)       | ((b & 0xcccccccc) >> 2);
                   1023:        b = ((x & 0x33333333) << 2) |  (b & 0x33333333);
                   1024:        x = c;
                   1025:        c =  (c & 0xcccccccc)       | ((d & 0xcccccccc) >> 2);
                   1026:        d = ((x & 0x33333333) << 2) |  (d & 0x33333333);
                   1027: 
                   1028: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
                   1029:        a = (a & 0x5555aaaa) | ((a & 0x00005555) << 17) | ((a & 0xaaaa0000) >> 17);
                   1030:        b = (b & 0x5555aaaa) | ((b & 0x00005555) << 17) | ((b & 0xaaaa0000) >> 17);
                   1031:        c = (c & 0x5555aaaa) | ((c & 0x00005555) << 17) | ((c & 0xaaaa0000) >> 17);
                   1032:        d = (d & 0x5555aaaa) | ((d & 0x00005555) << 17) | ((d & 0xaaaa0000) >> 17);
                   1033: 
                   1034:        colorValues[ 8] = a;
                   1035:        a >>= 8;
                   1036:        colorValues[ 0] = a;
                   1037:        a >>= 8;
                   1038:        colorValues[ 9] = a;
                   1039:        a >>= 8;
                   1040:        colorValues[ 1] = a;
                   1041: 
                   1042:        colorValues[10] = b;
                   1043:        b >>= 8;
                   1044:        colorValues[ 2] = b;
                   1045:        b >>= 8;
                   1046:        colorValues[11] = b;
                   1047:        b >>= 8;
                   1048:        colorValues[ 3] = b;
                   1049: 
                   1050:        colorValues[12] = c;
                   1051:        c >>= 8;
                   1052:        colorValues[ 4] = c;
                   1053:        c >>= 8;
                   1054:        colorValues[13] = c;
                   1055:        c >>= 8;
                   1056:        colorValues[ 5] = c;
                   1057: 
                   1058:        colorValues[14] = d;
                   1059:        d >>= 8;
                   1060:        colorValues[ 6] = d;
                   1061:        d >>= 8;
                   1062:        colorValues[15] = d;
                   1063:        d >>= 8;
                   1064:        colorValues[ 7] = d;
                   1065: #else
                   1066:        a = (a & 0xaaaa5555) | ((a & 0x0000aaaa) << 15) | ((a & 0x55550000) >> 15);
                   1067:        b = (b & 0xaaaa5555) | ((b & 0x0000aaaa) << 15) | ((b & 0x55550000) >> 15);
                   1068:        c = (c & 0xaaaa5555) | ((c & 0x0000aaaa) << 15) | ((c & 0x55550000) >> 15);
                   1069:        d = (d & 0xaaaa5555) | ((d & 0x0000aaaa) << 15) | ((d & 0x55550000) >> 15);
                   1070: 
                   1071:        colorValues[ 1] = a;
                   1072:        a >>= 8;
                   1073:        colorValues[ 9] = a;
                   1074:        a >>= 8;
                   1075:        colorValues[ 0] = a;
                   1076:        a >>= 8;
                   1077:        colorValues[ 8] = a;
                   1078: 
                   1079:        colorValues[ 3] = b;
                   1080:        b >>= 8;
                   1081:        colorValues[11] = b;
                   1082:        b >>= 8;
                   1083:        colorValues[ 2] = b;
                   1084:        b >>= 8;
                   1085:        colorValues[10] = b;
                   1086: 
                   1087:        colorValues[ 5] = c;
                   1088:        c >>= 8;
                   1089:        colorValues[13] = c;
                   1090:        c >>= 8;
                   1091:        colorValues[ 4] = c;
                   1092:        c >>= 8;
                   1093:        colorValues[12] = c;
                   1094: 
                   1095:        colorValues[ 7] = d;
                   1096:        d >>= 8;
                   1097:        colorValues[15] = d;
                   1098:        d >>= 8;
                   1099:        colorValues[ 6] = d;
                   1100:        d >>= 8;
                   1101:        colorValues[14] = d;
                   1102: #endif
                   1103: }
                   1104: 
1.1       root     1105: void VIDEL_ConvertScreenNoZoom(int vw, int vh, int vbpp, int nextline)
                   1106: {
                   1107:        int scrpitch = HostScreen_getPitch();
1.1.1.8   root     1108:        int h, w, j;
1.1       root     1109: 
1.1.1.8   root     1110:        Uint16 *fvram = (Uint16 *) Atari2HostAddr(videl.videoBaseAddr);
1.1.1.9   root     1111:        Uint16 *fvram_line;
1.1.1.2   root     1112:        Uint8 *hvram = HostScreen_getVideoramAddress();
1.1.1.6   root     1113:        SDL_PixelFormat *scrfmt = HostScreen_getFormat();
1.1       root     1114: 
1.1.1.8   root     1115:        Uint16 lowBorderSize, rightBorderSize;
1.1.1.9   root     1116:        int scrwidth, scrheight;
                   1117:        int vw_clip, vh_clip;
1.1.1.8   root     1118: 
                   1119:        int hscrolloffset = IoMem_ReadByte(0xff8265) & 0x0f;
                   1120: 
                   1121:        /* Horizontal scroll register set? */
                   1122:        if (hscrolloffset) {
                   1123:                /* Yes, so we need to adjust offset to next line: */
                   1124:                nextline += vbpp;
                   1125:        }
                   1126: 
                   1127:        /* If emulated computer is the TT, we use the same rendering for display, but without the borders */
                   1128:        if (ConfigureParams.System.nMachineType == MACHINE_TT) {
                   1129:                videl.leftBorderSize = 0;
                   1130:                videl.rightBorderSize = 0;
                   1131:                videl.upperBorderSize = 0;
                   1132:                videl.lowerBorderSize = 0;
                   1133:                fvram = (Uint16 *) Atari2HostAddr(VIDEL_getVideoramAddress());
1.1.1.9   root     1134:        } else {
                   1135:                bTTSampleHold = false;
1.1.1.8   root     1136:        }
1.1       root     1137: 
                   1138:        /* Clip to SDL_Surface dimensions */
1.1.1.9   root     1139:        scrwidth = HostScreen_getWidth();
                   1140:        scrheight = HostScreen_getHeight();
                   1141:        vw_clip = vw;
                   1142:        vh_clip = vh;
1.1       root     1143:        if (vw>scrwidth) vw_clip = scrwidth;
                   1144:        if (vh>scrheight) vh_clip = scrheight;  
                   1145: 
1.1.1.8   root     1146:        /* If emulated computer is the FALCON, we must take :
1.1.1.11! root     1147:         * vw = display width without borders
        !          1148:         * vh = display height without borders
1.1.1.8   root     1149:         */
                   1150:        if (ConfigureParams.System.nMachineType == MACHINE_FALCON) {
                   1151:                vw = videl.XSize;
                   1152:                vh = videl.YSize;
1.1       root     1153:        }
                   1154: 
1.1.1.8   root     1155:        /* If there's not enough space to display the left border, just return */
                   1156:        if (vw_clip < videl.leftBorderSize)
                   1157:                return;
                   1158:        /* If there's not enough space for the left border + the graphic area, we clip */ 
                   1159:        if (vw_clip < vw + videl.leftBorderSize) {
                   1160:                vw = vw_clip - videl.leftBorderSize;
                   1161:                rightBorderSize = 0;
                   1162:        }
                   1163:        /* if there's not enough space for the left border + the graphic area + the right border, we clip the border */
                   1164:        else if (vw_clip < vw + videl.leftBorderSize + videl.rightBorderSize)
                   1165:                rightBorderSize = vw_clip - videl.leftBorderSize - vw;
                   1166:        else
                   1167:                rightBorderSize = videl.rightBorderSize;
                   1168: 
                   1169:        /* If there's not enough space to display the upper border, just return */
                   1170:        if (vh_clip < videl.upperBorderSize)
                   1171:                return;
                   1172: 
                   1173:        /* If there's not enough space for the upper border + the graphic area, we clip */ 
                   1174:        if (vh_clip < vh + videl.upperBorderSize) {
                   1175:                vh = vh_clip - videl.upperBorderSize;
                   1176:                lowBorderSize = 0;
                   1177:        }
                   1178:        /* if there's not enough space for the upper border + the graphic area + the lower border, we clip the border */
                   1179:        else if (vh_clip < vh + videl.upperBorderSize + videl.lowerBorderSize)
                   1180:                lowBorderSize = vh_clip - videl.upperBorderSize - vh;
                   1181:        else
                   1182:                lowBorderSize = videl.lowerBorderSize;
                   1183: 
1.1       root     1184:        /* Center screen */
                   1185:        hvram += ((scrheight-vh_clip)>>1)*scrpitch;
                   1186:        hvram += ((scrwidth-vw_clip)>>1)*HostScreen_getBpp();
                   1187: 
1.1.1.9   root     1188:        fvram_line = fvram;
1.1.1.8   root     1189:        scrwidth = videl.leftBorderSize + vw + videl.rightBorderSize;
                   1190: 
                   1191:        /* render the graphic area */
1.1       root     1192:        if (vbpp < 16) {
                   1193:                /* Bitplanes modes */
                   1194: 
1.1.1.8   root     1195:                /* The SDL colors blitting... */
1.1.1.2   root     1196:                Uint8 color[16];
1.1       root     1197: 
1.1.1.8   root     1198:                /* FIXME: The byte swap could be done here by enrolling the loop into 2 each by 8 pixels */
1.1       root     1199:                switch ( HostScreen_getBpp() ) {
                   1200:                        case 1:
1.1.1.8   root     1201:                        {
                   1202:                                Uint8 *hvram_line = hvram;
1.1       root     1203: 
1.1.1.8   root     1204:                                /* Render the upper border */
                   1205:                                for (h = 0; h < videl.upperBorderSize; h++) {
                   1206:                                        VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   1207:                                        hvram_line += scrpitch;
                   1208:                                }
1.1       root     1209: 
1.1.1.8   root     1210:                                /* Render the graphical area */
                   1211:                                for (h = 0; h < vh; h++) {
                   1212:                                        Uint16 *fvram_column = fvram_line;
                   1213:                                        Uint8 *hvram_column = hvram_line;
                   1214: 
                   1215:                                        /* Left border first */
                   1216:                                        VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize);
                   1217:                                        hvram_column += videl.leftBorderSize;
                   1218:                                
                   1219:                                        /* First 16 pixels */
                   1220:                                        VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
                   1221:                                        memcpy(hvram_column, color+hscrolloffset, 16-hscrolloffset);
                   1222:                                        hvram_column += 16-hscrolloffset;
                   1223:                                        fvram_column += vbpp;
                   1224:                                        /* Now the main part of the line */
                   1225:                                        for (w = 1; w < (vw+15)>>4; w++) {
                   1226:                                                VIDEL_bitplaneToChunky( fvram_column, vbpp, color );
                   1227:                                                memcpy(hvram_column, color, 16);
                   1228:                                                hvram_column += 16;
1.1       root     1229:                                                fvram_column += vbpp;
                   1230:                                        }
1.1.1.8   root     1231:                                        /* Last pixels of the line for fine scrolling */
                   1232:                                        if (hscrolloffset) {
                   1233:                                                VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
                   1234:                                                memcpy(hvram_column, color, hscrolloffset);
                   1235:                                        }
                   1236:                                        /* Right border */
                   1237:                                        VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), rightBorderSize);
                   1238: 
1.1.1.9   root     1239:                                        if (bTTSampleHold) {
                   1240:                                                Uint8 TMPPixel = 0;
                   1241:                                                for (w=0; w < (vw); w++) {
                   1242:                                                        if (hvram_line[w] == 0) {
                   1243:                                                                hvram_line[w] = TMPPixel;
                   1244:                                                        } else {
                   1245:                                                                TMPPixel = hvram_line[w];
                   1246:                                                        }
                   1247:                                                }
                   1248:                                        }
                   1249: 
1.1.1.8   root     1250:                                        fvram_line += nextline;
                   1251:                                        hvram_line += scrpitch;
1.1       root     1252:                                }
1.1.1.8   root     1253: 
                   1254:                                /* Render the lower border */
                   1255:                                for (h = 0; h < lowBorderSize; h++) {
                   1256:                                        VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   1257:                                        hvram_line += scrpitch;
                   1258:                                }
                   1259:                        }
                   1260:                        break;
1.1       root     1261:                        case 2:
1.1.1.8   root     1262:                        {
                   1263:                                Uint16 *hvram_line = (Uint16 *)hvram;
1.1       root     1264: 
1.1.1.8   root     1265:                                /* Render the upper border */
                   1266:                                for (h = 0; h < videl.upperBorderSize; h++) {
                   1267:                                        VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   1268:                                        hvram_line += scrpitch>>1;
                   1269:                                }
1.1       root     1270: 
1.1.1.8   root     1271:                                /* Render the graphical area */
                   1272:                                for (h = 0; h < vh; h++) {
                   1273:                                        Uint16 *fvram_column = fvram_line;
                   1274:                                        Uint16 *hvram_column = hvram_line;
                   1275: 
                   1276:                                        /* Left border first */
                   1277:                                        VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize);
                   1278:                                        hvram_column += videl.leftBorderSize;
                   1279:                                
                   1280:                                        /* First 16 pixels */
                   1281:                                        VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
                   1282:                                        for (j = 0; j < 16 - hscrolloffset; j++) {
                   1283:                                                *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]);
                   1284:                                        }
                   1285:                                        fvram_column += vbpp;
                   1286:                                        /* Now the main part of the line */
                   1287:                                        for (w = 1; w < (vw+15)>>4; w++) {
                   1288:                                                VIDEL_bitplaneToChunky( fvram_column, vbpp, color );
                   1289:                                                for (j=0; j<16; j++) {
                   1290:                                                        *hvram_column++ = HostScreen_getPaletteColor( color[j] );
1.1.1.4   root     1291:                                                }
                   1292:                                                fvram_column += vbpp;
1.1.1.8   root     1293:                                        }
                   1294:                                        /* Last pixels of the line for fine scrolling */
                   1295:                                        if (hscrolloffset) {
                   1296:                                                VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
                   1297:                                                for (j = 0; j < hscrolloffset; j++) {
                   1298:                                                        *hvram_column++ = HostScreen_getPaletteColor(color[j]);
1.1       root     1299:                                                }
                   1300:                                        }
1.1.1.8   root     1301:                                        /* Right border */
                   1302:                                        VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), rightBorderSize);
                   1303: 
                   1304:                                        fvram_line += nextline;
                   1305:                                        hvram_line += scrpitch>>1;
1.1       root     1306:                                }
1.1.1.8   root     1307: 
                   1308:                                /* Render the lower border */
                   1309:                                for (h = 0; h < lowBorderSize; h++) {
                   1310:                                        VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   1311:                                        hvram_line += scrpitch>>1;
                   1312:                                }
                   1313:                        }
                   1314:                        break;
1.1       root     1315:                        case 4:
1.1.1.8   root     1316:                        {
                   1317:                                Uint32 *hvram_line = (Uint32 *)hvram;
1.1       root     1318: 
1.1.1.8   root     1319:                                /* Render the upper border */
                   1320:                                for (h = 0; h < videl.upperBorderSize; h++) {
                   1321:                                        VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   1322:                                        hvram_line += scrpitch>>2;
                   1323:                                }
1.1       root     1324: 
1.1.1.8   root     1325:                                /* Render the graphical area */
                   1326:                                for (h = 0; h < vh; h++) {
                   1327:                                        Uint16 *fvram_column = fvram_line;
                   1328:                                        Uint32 *hvram_column = hvram_line;
                   1329: 
                   1330:                                        /* Left border first */
                   1331:                                        VIDEL_memset_uint32 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize);
                   1332:                                        hvram_column += videl.leftBorderSize;
                   1333:                                
                   1334:                                        /* First 16 pixels */
                   1335:                                        VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
                   1336:                                        for (j = 0; j < 16 - hscrolloffset; j++) {
                   1337:                                                *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]);
                   1338:                                        }
                   1339:                                        fvram_column += vbpp;
                   1340:                                        /* Now the main part of the line */
                   1341:                                        for (w = 1; w < (vw+15)>>4; w++) {
                   1342:                                                VIDEL_bitplaneToChunky( fvram_column, vbpp, color );
                   1343:                                                for (j=0; j<16; j++) {
                   1344:                                                        *hvram_column++ = HostScreen_getPaletteColor( color[j] );
1.1.1.4   root     1345:                                                }
                   1346:                                                fvram_column += vbpp;
1.1.1.8   root     1347:                                        }
                   1348:                                        /* Last pixels of the line for fine scrolling */
                   1349:                                        if (hscrolloffset) {
                   1350:                                                VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
                   1351:                                                for (j = 0; j < hscrolloffset; j++) {
                   1352:                                                        *hvram_column++ = HostScreen_getPaletteColor(color[j]);
1.1.1.4   root     1353:                                                }
1.1       root     1354:                                        }
1.1.1.8   root     1355:                                        /* Right border */
                   1356:                                        VIDEL_memset_uint32 (hvram_column, HostScreen_getPaletteColor(0), rightBorderSize);
                   1357: 
                   1358:                                        fvram_line += nextline;
                   1359:                                        hvram_line += scrpitch>>2;
1.1       root     1360:                                }
1.1.1.8   root     1361: 
                   1362:                                /* Render the lower border */
                   1363:                                for (h = 0; h < lowBorderSize; h++) {
                   1364:                                        VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   1365:                                        hvram_line += scrpitch>>2;
                   1366:                                }
                   1367:                        }
                   1368:                        break;
1.1       root     1369:                }
                   1370: 
                   1371:        } else {
                   1372: 
1.1.1.8   root     1373:                /* Falcon TC (High Color) */
1.1       root     1374:                switch ( HostScreen_getBpp() )  {
                   1375:                        case 1:
1.1.1.8   root     1376:                        {
                   1377:                                /* FIXME: when Videl switches to 16bpp, set the palette to 3:3:2 */
                   1378:                                Uint8 *hvram_line = hvram;
                   1379: 
                   1380:                                /* Render the upper border */
                   1381:                                for (h = 0; h < videl.upperBorderSize; h++) {
                   1382:                                        VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   1383:                                        hvram_line += scrpitch;
                   1384:                                }
1.1       root     1385: 
1.1.1.8   root     1386:                                /* Render the graphical area */
                   1387:                                for (h = 0; h < vh; h++) {
                   1388:                                        Uint16 *fvram_column = fvram_line;
                   1389:                                        Uint8 *hvram_column = hvram_line;
                   1390:                                        int tmp;
                   1391: 
                   1392:                                        /* Left border first */
                   1393:                                        VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize);
                   1394:                                        hvram_column += videl.leftBorderSize;
                   1395: 
                   1396:                                        /* Graphical area */
                   1397:                                        for (w = 0; w < vw; w++) {
                   1398:                                                tmp = SDL_SwapBE16(*fvram_column++);
                   1399:                                                *hvram_column++ = (((tmp>>13) & 7) << 5) + (((tmp>>8) & 7) << 2) + (((tmp>>2) & 3));
                   1400:                                        }
1.1       root     1401: 
1.1.1.8   root     1402:                                        /* Right border */
                   1403:                                        VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), rightBorderSize);
1.1       root     1404: 
1.1.1.8   root     1405:                                        fvram_line += nextline;
                   1406:                                        hvram_line += scrpitch;
1.1       root     1407:                                }
1.1.1.8   root     1408:                                /* Render the bottom border */
                   1409:                                for (h = 0; h < lowBorderSize; h++) {
                   1410:                                        VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   1411:                                        hvram_line += scrpitch;
                   1412:                                }
                   1413:                        }
                   1414:                        break;
1.1       root     1415:                        case 2:
1.1.1.8   root     1416:                        {
                   1417:                                Uint16 *hvram_line = (Uint16 *)hvram;
                   1418: 
                   1419:                                /* Render the upper border */
                   1420:                                for (h = 0; h < videl.upperBorderSize; h++) {
                   1421:                                        VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   1422:                                        hvram_line += scrpitch>>1;
                   1423:                                }
                   1424: 
                   1425:                                /* Render the graphical area */
                   1426:                                for (h = 0; h < vh; h++) {
                   1427:                                        Uint16 *hvram_column = hvram_line;
1.1.1.9   root     1428: #if SDL_BYTEORDER != SDL_BIG_ENDIAN
                   1429:                                        Uint16 *fvram_column;
                   1430: #endif
1.1.1.8   root     1431:                                        /* Left border first */
                   1432:                                        VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize);
                   1433:                                        hvram_column += videl.leftBorderSize;
1.1       root     1434: 
                   1435: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1.1.1.8   root     1436:                                        /* FIXME: here might be a runtime little/big video endian switch like:
                   1437:                                                if ( " videocard memory in Motorola endian format " false)
                   1438:                                        */
                   1439:                                        memcpy(hvram_column, fvram_line, vw<<1);
                   1440:                                        hvram_column += vw<<1;
1.1       root     1441: #else
1.1.1.9   root     1442:                                        fvram_column = fvram_line;
1.1.1.8   root     1443:                                        /* Graphical area */
                   1444:                                        for (w = 0; w < vw; w++)
                   1445:                                                *hvram_column ++ = SDL_SwapBE16(*fvram_column++);
                   1446: #endif /* SDL_BYTEORDER == SDL_BIG_ENDIAN */
1.1       root     1447: 
1.1.1.8   root     1448:                                        /* Right border */
                   1449:                                        VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), rightBorderSize);
1.1       root     1450: 
1.1.1.8   root     1451:                                        fvram_line += nextline;
                   1452:                                        hvram_line += scrpitch>>1;
1.1       root     1453:                                }
                   1454: 
1.1.1.8   root     1455:                                /* Render the bottom border */
                   1456:                                for (h = 0; h < lowBorderSize; h++) {
                   1457:                                        VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   1458:                                        hvram_line += scrpitch>>1;
1.1       root     1459:                                }
1.1.1.8   root     1460:                        }
                   1461:                        break;
                   1462:                        case 4:
                   1463:                        {
                   1464:                                Uint32 *hvram_line = (Uint32 *)hvram;
1.1       root     1465: 
1.1.1.8   root     1466:                                /* Render the upper border */
                   1467:                                for (h = 0; h < videl.upperBorderSize; h++) {
                   1468:                                        VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   1469:                                        hvram_line += scrpitch>>2;
                   1470:                                }
1.1       root     1471: 
1.1.1.8   root     1472:                                /* Render the graphical area */
                   1473:                                for (h = 0; h < vh; h++) {
                   1474:                                        Uint16 *fvram_column = fvram_line;
                   1475:                                        Uint32 *hvram_column = hvram_line;
                   1476: 
                   1477:                                        /* Left border first */
                   1478:                                        VIDEL_memset_uint32 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize);
                   1479:                                        hvram_column += videl.leftBorderSize;
                   1480: 
                   1481:                                        /* Graphical area */
                   1482:                                        for (w = 0; w < vw; w++) {
                   1483:                                                Uint16 srcword = *fvram_column++;
                   1484:                                                *hvram_column ++ = SDL_MapRGB(scrfmt, (srcword & 0xf8), (((srcword & 0x07) << 5) | ((srcword >> 11) & 0x3c)), ((srcword >> 5) & 0xf8));
                   1485:                                        }
1.1       root     1486: 
1.1.1.8   root     1487:                                        /* Right border */
                   1488:                                        VIDEL_memset_uint32 (hvram_column, HostScreen_getPaletteColor(0), rightBorderSize);
                   1489:                                }
1.1       root     1490: 
1.1.1.8   root     1491:                                fvram_line += nextline;
                   1492:                                hvram_line += scrpitch>>2;
1.1       root     1493: 
1.1.1.8   root     1494:                                /* Render the bottom border */
                   1495:                                for (h = 0; h < lowBorderSize; h++) {
                   1496:                                        VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   1497:                                        hvram_line += scrpitch>>2;
                   1498:                                }
                   1499:                        }
                   1500:                        break;
                   1501:                }
1.1       root     1502:        }
                   1503: }
                   1504: 
                   1505: 
                   1506: void VIDEL_ConvertScreenZoom(int vw, int vh, int vbpp, int nextline)
                   1507: {
                   1508:        int i, j, w, h, cursrcline;
                   1509: 
1.1.1.8   root     1510:        Uint16 *fvram = (Uint16 *) Atari2HostAddr(videl.videoBaseAddr);
                   1511:        Uint16 *fvram_line;
                   1512:        Uint16 scrIdx = 0;
                   1513: 
                   1514:        int coefx = 1;
                   1515:        int coefy = 1;
1.1.1.9   root     1516:        int scrpitch, scrwidth, scrheight, scrbpp, hscrolloffset;
                   1517:        Uint8 *hvram;
                   1518:        SDL_PixelFormat *scrfmt;
1.1.1.8   root     1519: 
                   1520:        /* If emulated computer is the TT, we use the same rendering for display, but without the borders */
                   1521:        if (ConfigureParams.System.nMachineType == MACHINE_TT) {
                   1522:                videl.leftBorderSize = 0;
                   1523:                videl.rightBorderSize = 0;
                   1524:                videl.upperBorderSize = 0;
                   1525:                videl.lowerBorderSize = 0;
                   1526:                videl.XSize = vw;
                   1527:                videl.YSize = vh;
                   1528:                fvram = (Uint16 *) Atari2HostAddr(VIDEL_getVideoramAddress());
1.1.1.9   root     1529:        } else {
                   1530:                bTTSampleHold = false;
1.1.1.8   root     1531:        }
1.1       root     1532: 
                   1533:        /* Host screen infos */
1.1.1.9   root     1534:        scrpitch = HostScreen_getPitch();
                   1535:        scrwidth = HostScreen_getWidth();
                   1536:        scrheight = HostScreen_getHeight();
                   1537:        scrbpp = HostScreen_getBpp();
                   1538:        scrfmt = HostScreen_getFormat();
                   1539:        hvram = (Uint8 *) HostScreen_getVideoramAddress();
1.1       root     1540: 
1.1.1.9   root     1541:        hscrolloffset = IoMem_ReadByte(0xff8265) & 0x0f;
1.1       root     1542: 
                   1543:        /* Horizontal scroll register set? */
                   1544:        if (hscrolloffset) {
                   1545:                /* Yes, so we need to adjust offset to next line: */
                   1546:                nextline += vbpp;
                   1547:        }
                   1548: 
                   1549:        /* Integer zoom coef ? */
                   1550:        if (/*(bx_options.autozoom.integercoefs) &&*/ (scrwidth>=vw) && (scrheight>=vh)) {
1.1.1.8   root     1551:                coefx = scrwidth/vw;
                   1552:                coefy = scrheight/vh;
1.1       root     1553: 
                   1554:                scrwidth = vw * coefx;
                   1555:                scrheight = vh * coefy;
                   1556: 
                   1557:                /* Center screen */
                   1558:                hvram += ((HostScreen_getHeight()-scrheight)>>1)*scrpitch;
                   1559:                hvram += ((HostScreen_getWidth()-scrwidth)>>1)*scrbpp;
                   1560:        }
                   1561: 
                   1562:        /* New zoom ? */
1.1.1.8   root     1563:        if ((videl_zoom.zoomwidth != vw) || (scrwidth != videl_zoom.prev_scrwidth)) {
                   1564:                if (videl_zoom.zoomxtable) {
                   1565:                        free(videl_zoom.zoomxtable);
1.1       root     1566:                }
1.1.1.8   root     1567:                videl_zoom.zoomxtable = malloc(sizeof(int)*scrwidth);
1.1       root     1568:                for (i=0; i<scrwidth; i++) {
1.1.1.8   root     1569:                        videl_zoom.zoomxtable[i] = (vw*i)/scrwidth;
1.1       root     1570:                }
1.1.1.8   root     1571:                videl_zoom.zoomwidth = vw;
                   1572:                videl_zoom.prev_scrwidth = scrwidth;
1.1       root     1573:        }
1.1.1.8   root     1574:        if ((videl_zoom.zoomheight != vh) || (scrheight != videl_zoom.prev_scrheight)) {
                   1575:                if (videl_zoom.zoomytable) {
                   1576:                        free(videl_zoom.zoomytable);
1.1       root     1577:                }
1.1.1.8   root     1578:                videl_zoom.zoomytable = malloc(sizeof(int)*scrheight);
1.1       root     1579:                for (i=0; i<scrheight; i++) {
1.1.1.8   root     1580:                        videl_zoom.zoomytable[i] = (vh*i)/scrheight;
1.1       root     1581:                }
1.1.1.8   root     1582:                videl_zoom.zoomheight = vh;
                   1583:                videl_zoom.prev_scrheight = scrheight;
1.1       root     1584:        }
                   1585: 
                   1586:        cursrcline = -1;
                   1587: 
1.1.1.8   root     1588:        /* We reuse the following values to compute the display area size in zoom mode */
                   1589:        /* scrwidth must not change */
                   1590:        if (ConfigureParams.System.nMachineType == MACHINE_FALCON) {
1.1.1.11! root     1591:                /* get values without borders */
1.1.1.8   root     1592:                vw = videl.XSize;
                   1593:                vh = videl.YSize;
                   1594:                scrheight = vh * coefy;
                   1595:        }
1.1.1.11! root     1596:        if (vw < 16) {
        !          1597:                Log_Printf(LOG_WARN, "ERROR: Videl <16 screen width (%dx%d without borders)\nIf this happens at TOS boot, remove hatari.nvram,\nNVRAM video settings in it are corrupted.\n", vw, vh);
        !          1598:                /* prevent memory corruption */
        !          1599:                return;
        !          1600:        }
1.1.1.8   root     1601: 
1.1       root     1602:        if (vbpp<16) {
1.1.1.2   root     1603:                Uint8 color[16];
1.1       root     1604: 
                   1605:                /* Bitplanes modes */
                   1606:                switch(scrbpp) {
                   1607:                        case 1:
1.1.1.8   root     1608:                        {
                   1609:                                /* One complete 16-pixel aligned planar 2 chunky line */
                   1610:                                Uint8 *p2cline = malloc(sizeof(Uint8) * ((vw+15) & ~15));
                   1611:                                Uint8 *hvram_line = hvram;
                   1612:                                Uint8 *hvram_column = p2cline;
                   1613: 
                   1614:                                /* Render the upper border */
                   1615:                                for (h = 0; h < videl.upperBorderSize * coefy; h++) {
                   1616:                                        VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   1617:                                        hvram_line += scrpitch;
                   1618:                                }
1.1       root     1619: 
1.1.1.8   root     1620:                                /* Render the graphical area */
                   1621:                                for (h = 0; h < scrheight; h++) {
                   1622: 
                   1623:                                        fvram_line = fvram + (videl_zoom.zoomytable[scrIdx] * nextline);
                   1624:                                        scrIdx ++;
                   1625: 
                   1626:                                        /* Recopy the same line ? */
                   1627:                                        if (videl_zoom.zoomytable[h] == cursrcline) {
                   1628:                                                memcpy(hvram_line, hvram_line-scrpitch, scrwidth*scrbpp);
                   1629:                                        } else {
                   1630:                                                Uint16 *fvram_column = fvram_line;
                   1631:                                                hvram_column = p2cline;
                   1632: 
                   1633:                                                /* First 16 pixels of a new line */
                   1634:                                                VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
                   1635:                                                memcpy(hvram_column, color+hscrolloffset, 16-hscrolloffset);
                   1636:                                                hvram_column += 16-hscrolloffset;
                   1637:                                                fvram_column += vbpp;
                   1638:                                                /* Convert main part of the new line */
                   1639:                                                for (w=1; w < (vw+15)>>4; w++) {
                   1640:                                                        VIDEL_bitplaneToChunky( fvram_column, vbpp, color );
                   1641:                                                        memcpy(hvram_column, color, 16);
                   1642:                                                        hvram_column += 16;
                   1643:                                                        fvram_column += vbpp;
                   1644:                                                }
                   1645:                                                /* Last pixels of the line for fine scrolling */
                   1646:                                                if (hscrolloffset) {
                   1647:                                                        VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
                   1648:                                                        memcpy(hvram_column, color, hscrolloffset);
1.1       root     1649:                                                }
                   1650: 
1.1.1.8   root     1651:                                                hvram_column = hvram_line;
                   1652: 
                   1653:                                                /* Display the Left border */
                   1654:                                                VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize * coefx);
                   1655:                                                hvram_column += videl.leftBorderSize * coefx;
                   1656: 
                   1657:                                                /* Display the Graphical area */
                   1658:                                                for (w=0; w<(vw*coefx); w++)
                   1659:                                                        hvram_column[w] = p2cline[videl_zoom.zoomxtable[w - videl.leftBorderSize * coefx]];
                   1660:                                                hvram_column += vw * coefx;
                   1661: 
                   1662:                                                /* Display the Right border */
                   1663:                                                VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), videl.rightBorderSize * coefx);
                   1664:                                                hvram_column += videl.rightBorderSize * coefx;
1.1.1.9   root     1665: 
                   1666:                                                if (bTTSampleHold) {
                   1667:                                                        Uint8 TMPPixel = 0;
                   1668:                                                        for (w=0; w < (vw*coefx); w++) {
                   1669:                                                                if (hvram_line[w] == 0) {
                   1670:                                                                        hvram_line[w] = TMPPixel;
                   1671:                                                                } else {
                   1672:                                                                        TMPPixel = hvram_line[w];
                   1673:                                                                }
                   1674:                                                        }
                   1675:                                                }
                   1676: 
1.1       root     1677:                                        }
                   1678: 
1.1.1.8   root     1679:                                        hvram_line += scrpitch;
                   1680:                                        cursrcline = videl_zoom.zoomytable[h];
1.1       root     1681:                                }
1.1.1.8   root     1682: 
                   1683:                                /* Render the lower border */
                   1684:                                for (h = 0; h < videl.lowerBorderSize * coefy; h++) {
                   1685:                                        VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   1686:                                        hvram_line += scrpitch;
                   1687:                                }
                   1688: 
                   1689:                                free(p2cline);
                   1690:                        }
                   1691:                        break;
1.1       root     1692:                        case 2:
1.1.1.8   root     1693:                        {
                   1694:                                /* One complete 16-pixel aligned planar 2 chunky line */
                   1695:                                Uint16 *p2cline = malloc(sizeof(Uint16) * ((vw+15) & ~15));
                   1696:                                Uint16 *hvram_line = (Uint16 *)hvram;
                   1697:                                Uint16 *hvram_column = p2cline;
                   1698: 
                   1699:                                /* Render the upper border */
                   1700:                                for (h = 0; h < videl.upperBorderSize * coefy; h++) {
                   1701:                                        VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   1702:                                        hvram_line += scrpitch>>1;
                   1703:                                }
                   1704: 
                   1705:                                /* Render the graphical area */
                   1706:                                for (h = 0; h < scrheight; h++) {
                   1707:                                        fvram_line = fvram + (videl_zoom.zoomytable[scrIdx] * nextline);
                   1708:                                        scrIdx ++;
                   1709: 
                   1710:                                        /* Recopy the same line ? */
                   1711:                                        if (videl_zoom.zoomytable[h] == cursrcline) {
                   1712:                                                memcpy(hvram_line, hvram_line-(scrpitch>>1), scrwidth*scrbpp);
                   1713:                                        } else {
                   1714:                                                Uint16 *fvram_column = fvram_line;
                   1715:                                                hvram_column = p2cline;
                   1716: 
                   1717:                                                /* First 16 pixels of a new line */
                   1718:                                                VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
                   1719:                                                for (j = 0; j < 16 - hscrolloffset; j++) {
                   1720:                                                        *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]);
                   1721:                                                }
                   1722:                                                fvram_column += vbpp;
                   1723:                                                /* Convert the main part of the new line */
                   1724:                                                for (w = 1; w < (vw+15)>>4; w++) {
                   1725:                                                        VIDEL_bitplaneToChunky( fvram_column, vbpp, color );
                   1726:                                                        for (j=0; j<16; j++) {
                   1727:                                                                *hvram_column++ = HostScreen_getPaletteColor( color[j] );
1.1.1.4   root     1728:                                                        }
                   1729:                                                        fvram_column += vbpp;
1.1.1.8   root     1730:                                                }
                   1731:                                                /* Last pixels of the new line for fine scrolling */
                   1732:                                                if (hscrolloffset) {
                   1733:                                                        VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
                   1734:                                                        for (j = 0; j < hscrolloffset; j++) {
                   1735:                                                                *hvram_column++ = HostScreen_getPaletteColor(color[j]);
1.1       root     1736:                                                        }
                   1737:                                                }
                   1738: 
1.1.1.8   root     1739:                                                hvram_column = hvram_line;
                   1740: 
                   1741:                                                /* Display the Left border */
                   1742:                                                VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize * coefx);
                   1743:                                                hvram_column += videl.leftBorderSize * coefx;
                   1744: 
                   1745:                                                /* Display the Graphical area */
                   1746:                                                for (w=0; w<(vw*coefx); w++)
                   1747:                                                        hvram_column[w] = p2cline[videl_zoom.zoomxtable[w]];
                   1748:                                                hvram_column += vw * coefx;
                   1749: 
                   1750:                                                /* Display the Right border */
                   1751:                                                VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), videl.rightBorderSize * coefx);
                   1752:                                                hvram_column += videl.rightBorderSize * coefx;
1.1       root     1753:                                        }
                   1754: 
1.1.1.8   root     1755:                                        hvram_line += scrpitch>>1;
                   1756:                                        cursrcline = videl_zoom.zoomytable[h];
1.1       root     1757:                                }
1.1.1.8   root     1758: 
                   1759:                                /* Render the lower border */
                   1760:                                for (h = 0; h < videl.lowerBorderSize * coefy; h++) {
                   1761:                                        VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   1762:                                        hvram_line += scrpitch>>1;
                   1763:                                }
                   1764: 
                   1765:                                free(p2cline);
                   1766:                        }
                   1767:                        break;
1.1       root     1768:                        case 4:
1.1.1.8   root     1769:                        {
                   1770:                                /* One complete 16-pixel aligned planar 2 chunky line */
                   1771:                                Uint32 *p2cline = malloc(sizeof(Uint32) * ((vw+15) & ~15));
                   1772:                                Uint32 *hvram_line = (Uint32 *)hvram;
                   1773:                                Uint32 *hvram_column = p2cline;
                   1774: 
                   1775:                                /* Render the upper border */
                   1776:                                for (h = 0; h < videl.upperBorderSize * coefy; h++) {
                   1777:                                        VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   1778:                                        hvram_line += scrpitch>>2;
                   1779:                                }
                   1780: 
                   1781:                                /* Render the graphical area */
                   1782:                                for (h = 0; h < scrheight; h++) {
                   1783:                                        fvram_line = fvram + (videl_zoom.zoomytable[scrIdx] * nextline);
                   1784:                                        scrIdx ++;
                   1785:                                        /* Recopy the same line ? */
                   1786:                                        if (videl_zoom.zoomytable[h] == cursrcline) {
                   1787:                                                memcpy(hvram_line, hvram_line-(scrpitch>>2), scrwidth*scrbpp);
                   1788:                                        } else {
                   1789:                                                Uint16 *fvram_column = fvram_line;
                   1790:                                                hvram_column = p2cline;
                   1791: 
                   1792:                                                /* First 16 pixels of a new line */
                   1793:                                                VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
                   1794:                                                for (j = 0; j < 16 - hscrolloffset; j++) {
                   1795:                                                        *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]);
                   1796:                                                }
                   1797:                                                fvram_column += vbpp;
                   1798:                                                /* Convert the main part of the new line */
                   1799:                                                for (w = 1; w < (vw+15)>>4; w++) {
                   1800:                                                        VIDEL_bitplaneToChunky( fvram_column, vbpp, color );
                   1801:                                                        for (j=0; j<16; j++) {
                   1802:                                                                *hvram_column++ = HostScreen_getPaletteColor( color[j] );
1.1.1.4   root     1803:                                                        }
                   1804:                                                        fvram_column += vbpp;
1.1.1.8   root     1805:                                                }
                   1806:                                                /* Last pixels of the new line for fine scrolling */
                   1807:                                                if (hscrolloffset) {
                   1808:                                                        VIDEL_bitplaneToChunky(fvram_column, vbpp, color);
                   1809:                                                        for (j = 0; j < hscrolloffset; j++) {
                   1810:                                                                *hvram_column++ = HostScreen_getPaletteColor(color[j]);
1.1.1.4   root     1811:                                                        }
1.1.1.8   root     1812:                                                }
1.1.1.4   root     1813: 
1.1.1.8   root     1814:                                                hvram_column = hvram_line;
                   1815:                                                /* Display the Left border */
                   1816:                                                VIDEL_memset_uint32 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize * coefx);
                   1817:                                                hvram_column += videl.leftBorderSize * coefx;
                   1818: 
                   1819:                                                /* Display the Graphical area */
                   1820:                                                for (w=0; w<(vw*coefx); w++) {
                   1821:                                                        hvram_column[w] = p2cline[videl_zoom.zoomxtable[w]];
1.1       root     1822:                                                }
1.1.1.8   root     1823:                                                hvram_column += vw * coefx;
1.1       root     1824: 
1.1.1.8   root     1825:                                                /* Display the Right border */
                   1826:                                                VIDEL_memset_uint32 (hvram_column, HostScreen_getPaletteColor(0), videl.rightBorderSize * coefx);
                   1827:                                                hvram_column += videl.rightBorderSize * coefx;
1.1       root     1828:                                        }
                   1829: 
1.1.1.8   root     1830:                                        hvram_line += scrpitch>>2;
                   1831:                                        cursrcline = videl_zoom.zoomytable[h];
1.1       root     1832:                                }
1.1.1.8   root     1833: 
                   1834:                                /* Render the lower border */
                   1835:                                for (h = 0; h < videl.lowerBorderSize * coefy; h++) {
                   1836:                                        VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   1837:                                        hvram_line += scrpitch>>2;
                   1838:                                }
                   1839: 
                   1840:                                free(p2cline);
                   1841:                        }
                   1842:                        break;
1.1       root     1843:                }
                   1844:        } else {
1.1.1.4   root     1845:                /* Falcon high-color (16-bit) mode */
1.1       root     1846: 
                   1847:                switch(scrbpp) {
                   1848:                        case 1:
1.1.1.8   root     1849:                        {
                   1850:                                /* FIXME: when Videl switches to 16bpp, set the palette to 3:3:2 */
                   1851:                                Uint8 *hvram_line = hvram;
                   1852:                                Uint8 *hvram_column = hvram_line;
                   1853: 
                   1854:                                /* Render the upper border */
                   1855:                                for (h = 0; h < videl.upperBorderSize * coefy; h++) {
                   1856:                                        VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   1857:                                        hvram_line += scrpitch;
                   1858:                                }
1.1       root     1859: 
1.1.1.8   root     1860:                                /* Render the graphical area */
                   1861:                                for (h = 0; h < scrheight; h++) {
                   1862:                                        Uint16 *fvram_column;
                   1863: 
                   1864:                                        fvram_line = fvram + (videl_zoom.zoomytable[scrIdx] * nextline);
                   1865:                                        scrIdx ++;
                   1866: 
                   1867:                                        fvram_column = fvram_line;
                   1868: 
                   1869:                                        /* Recopy the same line ? */
                   1870:                                        if (videl_zoom.zoomytable[h] == cursrcline) {
                   1871:                                                memcpy(hvram_line, hvram_line-scrpitch, scrwidth*scrbpp);
                   1872:                                        } else {
1.1       root     1873: 
1.1.1.8   root     1874:                                                hvram_column = hvram_line;
                   1875:                                                /* Display the Left border */
                   1876:                                                VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize * coefx);
                   1877:                                                hvram_column += videl.leftBorderSize * coefx;
                   1878: 
                   1879:                                                /* Display the Graphical area */
                   1880:                                                for (w = 0; w<(vw*coefx); w++) {
                   1881:                                                        Uint16 srcword;
                   1882:                                                        Uint8 dstbyte;
1.1       root     1883:                                                        
1.1.1.8   root     1884:                                                        srcword = SDL_SwapBE16(fvram_column[videl_zoom.zoomxtable[w - videl.leftBorderSize * coefx]]);
1.1       root     1885: 
1.1.1.8   root     1886:                                                        dstbyte = ((srcword>>13) & 7) << 5;
                   1887:                                                        dstbyte |= ((srcword>>8) & 7) << 2;
                   1888:                                                        dstbyte |= ((srcword>>2) & 3);
                   1889:                                                        *hvram_column++ = dstbyte;
1.1       root     1890:                                                }
                   1891: 
1.1.1.8   root     1892:                                                /* Display the Right border */
                   1893:                                                VIDEL_memset_uint8 (hvram_column, HostScreen_getPaletteColor(0), videl.rightBorderSize * coefx);
                   1894:                                                hvram_column += videl.rightBorderSize * coefx;
1.1       root     1895:                                        }
1.1.1.8   root     1896: 
                   1897:                                        hvram_line += scrpitch;
                   1898:                                        cursrcline = videl_zoom.zoomytable[h];
1.1       root     1899:                                }
1.1.1.8   root     1900: 
                   1901:                                /* Render the lower border */
                   1902:                                for (h = 0; h < videl.lowerBorderSize * coefy; h++) {
                   1903:                                        VIDEL_memset_uint8 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   1904:                                        hvram_line += scrpitch;
                   1905:                                }
                   1906:                        }
                   1907:                        break;
1.1       root     1908:                        case 2:
1.1.1.8   root     1909:                        {
                   1910:                                Uint16 *hvram_line = (Uint16 *)hvram;
                   1911:                                Uint16 *hvram_column = hvram_line;
                   1912: 
                   1913:                                /* Render the upper border */
                   1914:                                for (h = 0; h < videl.upperBorderSize * coefy; h++) {
                   1915:                                        VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   1916:                                        hvram_line += scrpitch>>1;
                   1917:                                }
                   1918: 
                   1919:                                /* Render the graphical area */
                   1920:                                for (h = 0; h < scrheight; h++) {
                   1921:                                        Uint16 *fvram_column;
                   1922: 
                   1923:                                        fvram_line = fvram + (videl_zoom.zoomytable[scrIdx] * nextline);
                   1924:                                        scrIdx ++;
                   1925: 
                   1926:                                        fvram_column = fvram_line;
                   1927: 
                   1928:                                        /* Recopy the same line ? */
                   1929:                                        if (videl_zoom.zoomytable[h] == cursrcline) {
                   1930:                                                memcpy(hvram_line, hvram_line-(scrpitch>>1), scrwidth*scrbpp);
                   1931:                                        } else {
1.1       root     1932: 
                   1933:                                                hvram_column = hvram_line;
                   1934: 
1.1.1.8   root     1935:                                                /* Display the Left border */
                   1936:                                                VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize * coefx);
                   1937:                                                hvram_column += videl.leftBorderSize * coefx;
                   1938: 
                   1939:                                                /* Display the Graphical area */
                   1940:                                                for (w=0; w<(vw*coefx); w++)
                   1941:                                                        *hvram_column++ = SDL_SwapBE16(fvram_column[videl_zoom.zoomxtable[w]]);
                   1942: 
1.1       root     1943: 
1.1.1.8   root     1944:                                                /* Display the Right border */
                   1945:                                                VIDEL_memset_uint16 (hvram_column, HostScreen_getPaletteColor(0), videl.rightBorderSize * coefx);
                   1946:                                                hvram_column += videl.rightBorderSize * coefx;
1.1       root     1947:                                        }
1.1.1.8   root     1948: 
                   1949:                                        hvram_line += scrpitch>>1;
                   1950:                                        cursrcline = videl_zoom.zoomytable[h];
1.1       root     1951:                                }
1.1.1.8   root     1952: 
                   1953:                                /* Render the lower border */
                   1954:                                for (h = 0; h < videl.lowerBorderSize * coefy; h++) {
                   1955:                                        VIDEL_memset_uint16 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   1956:                                        hvram_line += scrpitch>>1;
                   1957:                                }
                   1958:                        }
                   1959:                        break;
1.1       root     1960:                        case 4:
1.1.1.8   root     1961:                        {
                   1962:                                Uint32 *hvram_line = (Uint32 *)hvram;
                   1963:                                Uint32 *hvram_column = hvram_line;
                   1964: 
                   1965:                                /* Render the upper border */
                   1966:                                for (h = 0; h < videl.upperBorderSize * coefy; h++) {
                   1967:                                        VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   1968:                                }
                   1969: 
                   1970:                                /* Render the graphical area */
                   1971:                                for (h = 0; h < scrheight; h++) {
                   1972:                                        Uint16 *fvram_column;
                   1973: 
                   1974:                                        fvram_line = fvram + (videl_zoom.zoomytable[scrIdx] * nextline);
                   1975:                                        scrIdx ++;
                   1976:                                        fvram_column = fvram_line;
                   1977: 
                   1978:                                        /* Recopy the same line ? */
                   1979:                                        if (videl_zoom.zoomytable[h] == cursrcline) {
                   1980:                                                memcpy(hvram_line, hvram_line-(scrpitch>>2), scrwidth*scrbpp);
                   1981:                                                hvram_line += scrpitch>>2;
                   1982:                                        } else {
1.1       root     1983: 
                   1984:                                                hvram_column = hvram_line;
                   1985: 
1.1.1.8   root     1986:                                                /* Display the Left border */
                   1987:                                                VIDEL_memset_uint32 (hvram_column, HostScreen_getPaletteColor(0), videl.leftBorderSize * coefx);
                   1988:                                                hvram_column += videl.leftBorderSize * coefx;
                   1989: 
                   1990:                                                /* Display the Graphical area */
                   1991:                                                for (w = 0; w<(vw*coefx); w++) {
                   1992:                                                        Uint16 srcword;
1.1       root     1993: 
1.1.1.8   root     1994:                                                        srcword = fvram_column[videl_zoom.zoomxtable[w]];
                   1995:                                                        *hvram_column++ = SDL_MapRGB(scrfmt, (srcword & 0xf8), (((srcword & 0x07) << 5) | ((srcword >> 11) & 0x3c)), ((srcword >> 5) & 0xf8));
1.1       root     1996:                                                }
                   1997: 
1.1.1.8   root     1998:                                                /* Display the Right border */
                   1999:                                                VIDEL_memset_uint32 (hvram_column, HostScreen_getPaletteColor(0), videl.rightBorderSize * coefx);
                   2000:                                                hvram_column += videl.rightBorderSize * coefx;
1.1       root     2001:                                        }
1.1.1.8   root     2002: 
                   2003:                                        hvram_line += scrpitch>>2;
                   2004:                                        cursrcline = videl_zoom.zoomytable[h];
1.1       root     2005:                                }
1.1.1.8   root     2006: 
                   2007:                                /* Render the lower border */
                   2008:                                for (h = 0; h < videl.lowerBorderSize * coefy; h++) {
                   2009:                                        VIDEL_memset_uint32 (hvram_line, HostScreen_getPaletteColor(0), scrwidth);
                   2010:                                        hvram_line += scrpitch>>2;
                   2011:                                }
                   2012:                        }
                   2013:                        break;
1.1       root     2014:                }
                   2015:        }
                   2016: }
1.1.1.8   root     2017: 
                   2018: static void VIDEL_memset_uint32(Uint32 *addr, Uint32 color, int count)
                   2019: {
                   2020:        while (count-- > 0) {
                   2021:                *addr++ = color;
                   2022:        }
                   2023: }
                   2024: 
                   2025: static void VIDEL_memset_uint16(Uint16 *addr, Uint16 color, int count)
                   2026: {
                   2027:        while (count-- > 0) {
                   2028:                *addr++ = color;
                   2029:        }
                   2030: }
                   2031: 
                   2032: static void VIDEL_memset_uint8(Uint8 *addr, Uint8 color, int count)
                   2033: {
                   2034:        memset(addr, color, count);
                   2035: }
1.1.1.10  root     2036: 
                   2037: 
                   2038: 
                   2039: /**
                   2040:  * Write to videl ST palette registers (0xff8240-0xff825e)
                   2041:  *
                   2042:  * [Laurent]: The following note should be verified on Falcon before being applied.
                   2043:  * 
                   2044:  * Note that there's a special "strange" case when writing only to the upper byte
                   2045:  * of the color reg (instead of writing 16 bits at once with .W/.L).
                   2046:  * In that case, the byte written to address x is automatically written
                   2047:  * to address x+1 too (but we shouldn't copy x in x+1 after masking x ; we apply the mask at the end)
                   2048:  * Similarly, when writing a byte to address x+1, it's also written to address x
                   2049:  * So :        move.w #0,$ff8240       -> color 0 is now $000
                   2050:  *     move.b #7,$ff8240       -> color 0 is now $707 !
                   2051:  *     move.b #$55,$ff8241     -> color 0 is now $555 !
                   2052:  *     move.b #$71,$ff8240     -> color 0 is now $171 (bytes are first copied, then masked)
                   2053:  */
1.1.1.11! root     2054: static void Videl_ColorReg_WriteWord(void)
1.1.1.10  root     2055: {
                   2056:        Uint16 col;
                   2057:        Uint32 addr = IoAccessCurrentAddress;
                   2058: 
                   2059:        videl.hostColorsSync = false;
                   2060: 
                   2061:        if (bUseHighRes || bUseVDIRes)               /* Don't store if hi-res or VDI resolution */
                   2062:                return;
                   2063: 
                   2064:        /* Note from laurent: The following special case should be verified on the real Falcon before uncommenting */
                   2065:        /* Handle special case when writing only to the upper byte of the color reg */
                   2066: //     if ( ( nIoMemAccessSize == SIZE_BYTE ) && ( ( IoAccessCurrentAddress & 1 ) == 0 ) )
                   2067: //             col = ( IoMem_ReadByte(addr) << 8 ) + IoMem_ReadByte(addr);             /* copy upper byte into lower byte */
                   2068:        /* Same when writing only to the lower byte of the color reg */
                   2069: //     else if ( ( nIoMemAccessSize == SIZE_BYTE ) && ( ( IoAccessCurrentAddress & 1 ) == 1 ) )
                   2070: //             col = ( IoMem_ReadByte(addr) << 8 ) + IoMem_ReadByte(addr);             /* copy lower byte into upper byte */
                   2071:        /* Usual case, writing a word or a long (2 words) */
                   2072: //     else
                   2073:                col = IoMem_ReadWord(addr);
                   2074: 
                   2075:        col &= 0xfff;                           /* Mask off to 4096 palette */
                   2076: 
                   2077:        addr &= 0xfffffffe;                     /* Ensure addr is even to store the 16 bit color */
                   2078: 
                   2079:        IoMem_WriteWord(addr, col);
                   2080: }
                   2081: 
                   2082: /*
                   2083:  * [NP] TODO : due to how .L accesses are handled in ioMem.c, we can't call directly
                   2084:  * Video_ColorReg_WriteWord from ioMemTabFalcon.c, we must use an intermediate
                   2085:  * function, else .L accesses will not change 2 .W color regs, but only one.
                   2086:  * This should be changed in ioMem.c to do 2 separate .W accesses, as would do a real 68000
                   2087:  */
                   2088: 
                   2089: void Videl_Color0_WriteWord(void)
                   2090: {
                   2091:        Videl_ColorReg_WriteWord();
                   2092: }
                   2093: 
                   2094: void Videl_Color1_WriteWord(void)
                   2095: {
                   2096:        Videl_ColorReg_WriteWord();
                   2097: }
                   2098: 
                   2099: void Videl_Color2_WriteWord(void)
                   2100: {
                   2101:        Videl_ColorReg_WriteWord();
                   2102: }
                   2103: 
                   2104: void Videl_Color3_WriteWord(void)
                   2105: {
                   2106:        Videl_ColorReg_WriteWord();
                   2107: }
                   2108: 
                   2109: void Videl_Color4_WriteWord(void)
                   2110: {
                   2111:        Videl_ColorReg_WriteWord();
                   2112: }
                   2113: 
                   2114: void Videl_Color5_WriteWord(void)
                   2115: {
                   2116:        Videl_ColorReg_WriteWord();
                   2117: }
                   2118: 
                   2119: void Videl_Color6_WriteWord(void)
                   2120: {
                   2121:        Videl_ColorReg_WriteWord();
                   2122: }
                   2123: 
                   2124: void Videl_Color7_WriteWord(void)
                   2125: {
                   2126:        Videl_ColorReg_WriteWord();
                   2127: }
                   2128: 
                   2129: void Videl_Color8_WriteWord(void)
                   2130: {
                   2131:        Videl_ColorReg_WriteWord();
                   2132: }
                   2133: 
                   2134: void Videl_Color9_WriteWord(void)
                   2135: {
                   2136:        Videl_ColorReg_WriteWord();
                   2137: }
                   2138: 
                   2139: void Videl_Color10_WriteWord(void)
                   2140: {
                   2141:        Videl_ColorReg_WriteWord();
                   2142: }
                   2143: 
                   2144: void Videl_Color11_WriteWord(void)
                   2145: {
                   2146:        Videl_ColorReg_WriteWord();
                   2147: }
                   2148: 
                   2149: void Videl_Color12_WriteWord(void)
                   2150: {
                   2151:        Videl_ColorReg_WriteWord();
                   2152: }
                   2153: 
                   2154: void Videl_Color13_WriteWord(void)
                   2155: {
                   2156:        Videl_ColorReg_WriteWord();
                   2157: }
                   2158: 
                   2159: void Videl_Color14_WriteWord(void)
                   2160: {
                   2161:        Videl_ColorReg_WriteWord();
                   2162: }
                   2163: 
                   2164: void Videl_Color15_WriteWord(void)
                   2165: {
                   2166:        Videl_ColorReg_WriteWord();
                   2167: }
                   2168: 
                   2169: /**
                   2170:  * display Videl registers values (for debugger info command)
                   2171:  */
1.1.1.11! root     2172: void Videl_Info(FILE *fp, Uint32 dummy)
1.1.1.10  root     2173: {
                   2174:        if (ConfigureParams.System.nMachineType != MACHINE_FALCON) {
1.1.1.11! root     2175:                fprintf(fp, "Not Falcon - no Videl!\n");
1.1.1.10  root     2176:                return;
                   2177:        }
                   2178: 
1.1.1.11! root     2179:        fprintf(fp, "$FF8006.b : monitor type                     : %02x\n", IoMem_ReadByte(0xff8006));
        !          2180:        fprintf(fp, "$FF8201.b : Video Base Hi                    : %02x\n", IoMem_ReadByte(0xff8201));
        !          2181:        fprintf(fp, "$FF8203.b : Video Base Mi                    : %02x\n", IoMem_ReadByte(0xff8203));
        !          2182:        fprintf(fp, "$FF8205.b : Video Count Hi                   : %02x\n", IoMem_ReadByte(0xff8205));
        !          2183:        fprintf(fp, "$FF8207.b : Video Count Mi                   : %02x\n", IoMem_ReadByte(0xff8207));
        !          2184:        fprintf(fp, "$FF8209.b : Video Count Lo                   : %02x\n", IoMem_ReadByte(0xff8209));
        !          2185:        fprintf(fp, "$FF820A.b : Sync mode                        : %02x\n", IoMem_ReadByte(0xff820a));
        !          2186:        fprintf(fp, "$FF820D.b : Video Base Lo                    : %02x\n", IoMem_ReadByte(0xff820d));
        !          2187:        fprintf(fp, "$FF820E.w : offset to next line              : %04x\n", IoMem_ReadWord(0xff820e));
        !          2188:        fprintf(fp, "$FF8210.w : VWRAP - line width               : %04x\n", IoMem_ReadWord(0xff8210));
        !          2189:        fprintf(fp, "$FF8260.b : ST shift mode                    : %02x\n", IoMem_ReadByte(0xff8260));
        !          2190:        fprintf(fp, "$FF8264.w : Horizontal scroll register       : %04x\n", IoMem_ReadWord(0xff8264));
        !          2191:        fprintf(fp, "$FF8266.w : Falcon shift mode                : %04x\n", IoMem_ReadWord(0xff8266));
        !          2192:        fprintf(fp, "\n");
        !          2193:        fprintf(fp, "$FF8280.w : HHC - Horizontal Hold Counter    : %04x\n", IoMem_ReadWord(0xff8280));
        !          2194:        fprintf(fp, "$FF8282.w : HHT - Horizontal Hold Timer      : %04x\n", IoMem_ReadWord(0xff8282));
        !          2195:        fprintf(fp, "$FF8284.w : HBB - Horizontal Border Begin    : %04x\n", IoMem_ReadWord(0xff8284));
        !          2196:        fprintf(fp, "$FF8286.w : HBE - Horizontal Border End      : %04x\n", IoMem_ReadWord(0xff8286));
        !          2197:        fprintf(fp, "$FF8288.w : HDB - Horizontal Display Begin   : %04x\n", IoMem_ReadWord(0xff8288));
        !          2198:        fprintf(fp, "$FF828A.w : HDE - Horizontal Display End     : %04x\n", IoMem_ReadWord(0xff828a));
        !          2199:        fprintf(fp, "$FF828C.w : HSS - Horizontal SS              : %04x\n", IoMem_ReadWord(0xff828c));
        !          2200:        fprintf(fp, "$FF828E.w : HFS - Horizontal FS              : %04x\n", IoMem_ReadWord(0xff828e));
        !          2201:        fprintf(fp, "$FF8290.w : HEE - Horizontal EE              : %04x\n", IoMem_ReadWord(0xff8290));
        !          2202:        fprintf(fp, "\n");
        !          2203:        fprintf(fp, "$FF82A0.w : VFC - Vertical Frequency Counter : %04x\n", IoMem_ReadWord(0xff82a0));
        !          2204:        fprintf(fp, "$FF82A2.w : VFT - Vertical Frequency Timer   : %04x\n", IoMem_ReadWord(0xff82a2));
        !          2205:        fprintf(fp, "$FF82A4.w : VBB - Vertical Border Begin      : %04x\n", IoMem_ReadWord(0xff82a4));
        !          2206:        fprintf(fp, "$FF82A6.w : VBE - Vertical Border End        : %04x\n", IoMem_ReadWord(0xff82a6));
        !          2207:        fprintf(fp, "$FF82A8.w : VDB - Vertical Display Begin     : %04x\n", IoMem_ReadWord(0xff82a8));
        !          2208:        fprintf(fp, "$FF82AA.w : VDE - Vertical Display End       : %04x\n", IoMem_ReadWord(0xff82aa));
        !          2209:        fprintf(fp, "$FF82AC.w : VSS - Vertical SS                : %04x\n", IoMem_ReadWord(0xff82ac));
        !          2210:        fprintf(fp, "\n");
        !          2211:        fprintf(fp, "$FF82C0.w : VCO - Video control              : %04x\n", IoMem_ReadWord(0xff82c0));
        !          2212:        fprintf(fp, "$FF82C2.w : VMD - Video mode                 : %04x\n", IoMem_ReadWord(0xff82c2));
        !          2213:        fprintf(fp, "\n-------------------------\n");
1.1.1.10  root     2214: 
1.1.1.11! root     2215:        fprintf(fp, "Video base  : %08x\n",
1.1.1.10  root     2216:                (IoMem_ReadByte(0xff8201)<<16) + 
                   2217:                (IoMem_ReadByte(0xff8203)<<8)  + 
                   2218:                 IoMem_ReadByte(0xff820d));
1.1.1.11! root     2219:        fprintf(fp, "Video count : %08x\n",
1.1.1.10  root     2220:                (IoMem_ReadByte(0xff8205)<<16) + 
                   2221:                (IoMem_ReadByte(0xff8207)<<8)  + 
                   2222:                 IoMem_ReadByte(0xff8209));
                   2223: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.