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

1.1       root        1: /*
                      2:   Hatari - videl.c
                      3: 
                      4:   This file is distributed under the GNU Public License, version 2 or at
                      5:   your option any later version. Read the file gpl.txt for details.
                      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
                     36:        $FFFF8265 (byte) : Horizontal scroll register
                     37:        $FFFF8266 (word) : Falcon shift mode
                     38:        
                     39:        $FFFF8280 (word) : HHC - Horizontal Hold Counter
                     40:        $FFFF8282 (word) : HHT - Horizontal Hold Timer
                     41:        $FFFF8284 (word) : HBB - Horizontal Border Begin
                     42:        $FFFF8286 (word) : HBE - Horizontal Border End
                     43:        $FFFF8288 (word) : HDB - Horizontal Display Begin
                     44:        $FFFF828A (word) : HDE - Horizontal Display End
                     45:        $FFFF828C (word) : HSS - Horizontal SS
                     46:        $FFFF828E (word) : HFS - Horizontal FS
                     47:        $FFFF8290 (word) : HEE - Horizontal EE
                     48:        
                     49:        $FFFF82A0 (word) : VFC - Vertical Frequency Counter
                     50:        $FFFF82A2 (word) : VFT - Vertical Frequency Timer
                     51:        $FFFF82A4 (word) : VBB - Vertical Border Begin
                     52:        $FFFF82A6 (word) : VBE - Vertical Border End
                     53:        $FFFF82A8 (word) : VDB - Vertical Display Begin
                     54:        $FFFF82AA (word) : VDE - Vertical Display End
                     55:        $FFFF82AC (word) : VSS - Vertical SS
                     56:        
                     57:        $FFFF82C0 (word) : VCO - Video control
                     58:        $FFFF82C2 (word) : VMD - Video mode
                     59: 
                     60:        $FFFF9800 (long) : VDL_PAL - Videl palette Register 000
                     61:        ...........
                     62:        $FFFF98FC (long) : VDL_PAL - Videl palette Register 255
1.1       root       63: */
1.1.1.6   root       64: 
1.1.1.4   root       65: const char VIDEL_fileid[] = "Hatari videl.c : " __DATE__ " " __TIME__;
1.1       root       66: 
1.1.1.6   root       67: #include <SDL_endian.h>
                     68: #include <SDL.h>
1.1       root       69: #include "main.h"
                     70: #include "configuration.h"
1.1.1.6   root       71: #include "memorySnapShot.h"
1.1       root       72: #include "ioMem.h"
1.1.1.6   root       73: #include "log.h"
1.1       root       74: #include "hostscreen.h"
                     75: #include "screen.h"
                     76: #include "stMemory.h"
                     77: #include "video.h"
                     78: #include "videl.h"
                     79: 
                     80: 
                     81: #define handleRead(a) IoMem_ReadByte(a)
                     82: #define handleReadW(a) IoMem_ReadWord(a)
                     83: #define Atari2HostAddr(a) (&STRam[a])
                     84: 
                     85: #define VIDEL_DEBUG 0
                     86: 
                     87: #if VIDEL_DEBUG
                     88: #define Dprintf(a) printf a
                     89: #else
                     90: #define Dprintf(a)
                     91: #endif
                     92: 
                     93: #define HW     0xff8200
                     94: #define VIDEL_COLOR_REGS_BEGIN 0xff9800
                     95: 
1.1.1.6   root       96: struct videl_s {
                     97:        bool   bUseSTShifter;                   /* whether to use ST or Falcon palette */
                     98:        Uint8  reg_ffff8006_save;               /* save reg_ffff8006 as it's a read only register */
                     99:        Uint8  monitor_type;                    /* 00 Monochrome (SM124) / 01 Color (SC1224) / 10 VGA Color / 11 Television ($FFFF8006) */
                    100: };
                    101: 
                    102: static struct videl_s videl;
                    103: 
1.1.1.5   root      104: /* TODO: put these to some struct so that it's easier to see
                    105:  * they're VIDEL global
                    106:  */
1.1.1.6   root      107: static int width, height, bpp;
1.1.1.2   root      108: static bool hostColorsSync;
1.1       root      109: 
1.1.1.6   root      110: Uint16 vfc_counter;                    /* counter for VFC register $ff82a0 (to be internalized when VIDEL emulation is complete) */
                    111: 
1.1       root      112: /* Autozoom */
                    113: static int zoomwidth, prev_scrwidth;
                    114: static int zoomheight, prev_scrheight;
                    115: static int *zoomxtable;
                    116: static int *zoomytable;
                    117: 
1.1.1.6   root      118: 
                    119: 
1.1       root      120: static void VIDEL_renderScreenNoZoom(void);
                    121: static void VIDEL_renderScreenZoom(void);
                    122: 
1.1.1.6   root      123:        
1.1       root      124: // Called upon startup and when CPU encounters a RESET instruction.
                    125: void VIDEL_reset(void)
                    126: {
1.1.1.6   root      127:        videl.bUseSTShifter = false;                            /* Use Falcon color palette by default */
                    128:        videl.reg_ffff8006_save = IoMem_ReadByte(0xff8006);
                    129:        videl.monitor_type  = videl.reg_ffff8006_save & 0xc0;
                    130:        
                    131:        hostColorsSync = false; 
1.1       root      132: 
1.1.1.6   root      133:        vfc_counter = 0;
                    134:        
1.1       root      135:        /* Autozoom */
                    136:        zoomwidth=prev_scrwidth=0;
                    137:        zoomheight=prev_scrheight=0;
                    138:        zoomxtable=NULL;
                    139:        zoomytable=NULL;
                    140: 
1.1.1.4   root      141:        /* Default resolution to boot with */
1.1       root      142:        width = 640;
                    143:        height = 480;
1.1.1.4   root      144:        HostScreen_setWindowSize(width, height, ConfigureParams.Screen.nForceBpp);
                    145: 
                    146:        /* Reset IO register (some are not initialized by TOS) */
                    147:        IoMem_WriteWord(0xff820e, 0);    /* Line offset */
                    148:        IoMem_WriteWord(0xff8264, 0);    /* Horizontal scroll */
1.1       root      149: }
                    150: 
1.1.1.6   root      151: /**
                    152:  * Save/Restore snapshot of local variables ('MemorySnapShot_Store' handles type)
                    153:  */
                    154: void VIDEL_MemorySnapShot_Capture(bool bSave)
                    155: {
                    156:        /* Save/Restore details */
                    157:        MemorySnapShot_Store(&videl, sizeof(videl));
                    158:        MemorySnapShot_Store(&vfc_counter, sizeof(vfc_counter));
                    159: }
                    160: 
                    161: /**
                    162:  * Monitor write access to ST/E color palette registers
                    163:  */
1.1       root      164: void VIDEL_ColorRegsWrite(void)
                    165: {
1.1.1.4   root      166:        hostColorsSync = false;
1.1       root      167: }
                    168: 
1.1.1.6   root      169: /**
                    170:  * VIDEL_Monitor_WriteByte : Contains memory and monitor configuration. 
                    171:  *                           This register is  read only.
                    172:  */
                    173: void VIDEL_Monitor_WriteByte(void)
                    174: {
                    175:        LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8006 Monitor and memory conf write (Read only)\n");
                    176:        /* Restore hardware value */
                    177:        IoMem_WriteByte(0xff8006, videl.reg_ffff8006_save);
                    178: }
                    179: 
                    180: /**
                    181:  * Write to video address base high, med and low register (0xff8201/03/0d).
                    182:  * On Falcon, when a program writes to high or med registers, base low register
                    183:  * is reset to zero.
                    184:  */
                    185: void VIDEL_ScreenBase_WriteByte(void)
                    186: {
                    187:        Uint32 screenBase;
                    188:        
                    189:        if ((IoAccessCurrentAddress == 0xff8201) || (IoAccessCurrentAddress == 0xff8203)) {
                    190:                /* Reset screen base low register */
                    191:                IoMem[0xff820d] = 0;
                    192:        }
                    193:        
                    194:        screenBase = (IoMem[0xff8201]<<16)+(IoMem[0xff8203]<<8)+IoMem[0xff820d];
                    195: 
                    196:        LOG_TRACE(TRACE_VIDEL, "Videl : $%04x Screen base write: 0x%01x\t (screen: 0x%04x)\n", 
                    197:                                                IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress], screenBase);
                    198: }
                    199: 
                    200: /**
                    201:     VIDEL_ST_ShiftModeWriteByte : 
                    202:        $FFFF8260 [R/W] B  ______10  ST Shift Mode
                    203:                                 ||
                    204:                                 ||                           others   vga
                    205:                                 ||                  $FF8210 $FF82C2 $FF82C2
                    206:                                 00--4BP/320 Pixels=> $0050   $0000   $0005
                    207:                                 01--2BP/640 Pixels=> $0050   $0004   $0009
                    208:                                 10--1BP/640 Pixels=> $0028   $0006   $0008
                    209:                                 11--???/320 Pixels=> $0050   $0000   $0000
                    210: 
                    211:        Writing to this register does the following things:
                    212:                - activate STE palette
                    213:                - sets line width ($ffff8210)
                    214:                - sets video mode in $ffff82c2 (double lines/interlace & cycles/pixel)
                    215:  */
                    216: void VIDEL_ST_ShiftModeWriteByte(void)
                    217: {
                    218:        Uint16 line_width, video_mode;
                    219:        Uint8 st_shiftMode;
                    220: 
                    221:        st_shiftMode = IoMem_ReadByte(0xff8260);
                    222:        LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8260 ST Shift Mode (STSHIFT) write: 0x%x\n", st_shiftMode);
                    223: 
                    224:        /* Activate STE palette */
                    225:        videl.bUseSTShifter = true;
                    226: 
                    227:        /*  Compute line width and video mode */
                    228:        switch (st_shiftMode & 0x3) {
                    229:                case 0: /* 4BP/320 Pixels */
                    230:                        line_width = 0x50;
                    231:                        /* half pixels + double lines vs. no scaling */
                    232:                        video_mode = videl.monitor_type == FALCON_MONITOR_VGA ? 0x5 : 0x0;
                    233:                        break;
                    234:                case 1: /* 2BP/640 Pixels */
                    235:                        line_width = 0x50;
                    236:                        /* quarter pixels + double lines vs. half pixels */
                    237:                        video_mode = videl.monitor_type == FALCON_MONITOR_VGA ? 0x9 : 0x4;
                    238:                        break;
                    239:                case 2: /* 1BP/640 Pixels */
                    240:                        line_width = 0x28;
                    241:                        if (videl.monitor_type == FALCON_MONITOR_MONO) {
                    242:                                video_mode = 0x0;
                    243:                                break;
                    244:                        }
                    245:                        /* quarter pixels vs. half pixels + interlace */
                    246:                        video_mode = videl.monitor_type == FALCON_MONITOR_VGA ? 0x8 : 0x6;
                    247:                        break;
                    248:                case 3: /* ???/320 Pixels */
                    249:                        line_width = 0x50;
                    250:                        video_mode = 0x0;
                    251:                        break;
                    252:        }
                    253: 
                    254:        /* Set line width ($FFFF8210) */
                    255:        IoMem_WriteWord(0xff8210, line_width); 
                    256:        
                    257:        /* Set video mode ($FFFF82C2) */
                    258:        IoMem_WriteWord(0xff82c2, video_mode); 
                    259: }
                    260: 
                    261: /**
                    262:     VIDEL_FALCON_ShiftModeWriteWord :
                    263:        $FFFF8266 [R/W] W  _____A98_6543210  Falcon Shift Mode (SPSHIFT)
                    264:                                ||| |||||||
                    265:                                ||| |||++++- 0..15: Colourbank setting in 8BP
                    266:                                ||| ||+----- 0: 8 Bitplanes (256 Colors) off
                    267:                                ||| ||+----- 1: 8 Bitplanes (256 Colors) on
                    268:                                ||| |+------ 0: internal Vertical Sync
                    269:                                ||| |        1: external Vertical Sync
                    270:                                ||| +------- 0: internal Horizontal Sync
                    271:                                |||          1: external Horizontal Sync
                    272:                                ||+--------- 0: True-Color-Mode off
                    273:                                ||           1: True-Color-Mode on
                    274:                                |+---------- 0: Overlay-Mode off
                    275:                                |            1: Overlay-Mode on
                    276:                                +----------- 0: 2-Color-Mode off
                    277:                                             1: 2-Color-Mode on
                    278: 
                    279:        Writing to this register does the following things:
                    280:                - activate Falcon palette
                    281:                - if you set Bits A/8/4 == 0, it selects 16-Color-Falcon-Mode (NOT the
                    282:                  same as ST LOW since Falcon palette is used!)
                    283:                - $8260 register is ignored, you don't need to write here anything
                    284: 
                    285:        Note: 4-Color-Mode isn't realisable with Falcon palette.
                    286:  */
                    287: void VIDEL_FALC_ShiftModeWriteWord(void)
                    288: {
                    289:        Uint16 falc_shiftMode = IoMem_ReadWord(0xff8266);
                    290: 
                    291:        LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8266 Falcon Shift Mode (SPSHIFT) write: 0x%02x\n", falc_shiftMode);
                    292: 
                    293:        videl.bUseSTShifter = false;
                    294: }
                    295: 
                    296: /**
                    297:  *  Write Horizontal Hold Counter (HHC)
                    298:  */
                    299: void VIDEL_HHC_WriteWord(void)
                    300: {
                    301:        Uint16 hhc = IoMem_ReadWord(0xff8280);
                    302: 
                    303:        LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8280 Horizontal Hold Counter (HHC) write: 0x%02x\n", hhc);
                    304: }
                    305: 
                    306: /**
                    307:  *  Write Horizontal Hold Timer (HHT)
                    308:  */
                    309: void VIDEL_HHT_WriteWord(void)
                    310: {
                    311:        Uint16 hht = IoMem_ReadWord(0xff8282);
                    312: 
                    313:        LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8282 Horizontal Hold Timer (HHT) write: 0x%02x\n", hht);
                    314: }
                    315: 
                    316: /**
                    317:  *  Write Horizontal Border Begin (HBB)
                    318:  */
                    319: void VIDEL_HBB_WriteWord(void)
                    320: {
                    321:        Uint16 hbb = IoMem_ReadWord(0xff8284);
                    322: 
                    323:        LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8284 Horizontal Border Begin (HBB) write: 0x%02x\n", hbb);
                    324: }
                    325: 
                    326: /**
                    327:  *  Write Horizontal Border End (HBE)
                    328:  */
                    329: void VIDEL_HBE_WriteWord(void)
                    330: {
                    331:        Uint16 hbe = IoMem_ReadWord(0xff8286);
                    332: 
                    333:        LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8286 Horizontal Border End (HBE) write: 0x%02x\n", hbe);
                    334: }
                    335: 
                    336: /**
                    337:  *  Write Horizontal Display Begin (HDB)
                    338:  */
                    339: void VIDEL_HDB_WriteWord(void)
                    340: {
                    341:        Uint16 hdb = IoMem_ReadWord(0xff8288);
                    342: 
                    343:        LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8288 Horizontal Display Begin (HDB) write: 0x%02x\n", hdb);
                    344: }
                    345: 
                    346: /**
                    347:  *  Write Horizontal Display End (HDE)
                    348:  */
                    349: void VIDEL_HDE_WriteWord(void)
                    350: {
                    351:        Uint16 hde = IoMem_ReadWord(0xff828a);
                    352: 
                    353:        LOG_TRACE(TRACE_VIDEL, "Videl : $ffff828a Horizontal Display End (HDE) write: 0x%02x\n", hde);
                    354: }
                    355: 
                    356: /**
                    357:  *  Write Horizontal SS (HSS)
                    358:  */
                    359: void VIDEL_HSS_WriteWord(void)
                    360: {
                    361:        Uint16 hss = IoMem_ReadWord(0xff828c);
                    362: 
                    363:        LOG_TRACE(TRACE_VIDEL, "Videl : $ffff828c Horizontal SS (HSS) write: 0x%02x\n", hss);
                    364: }
                    365: 
                    366: /**
                    367:  *  Write Horizontal FS (HFS)
                    368:  */
                    369: void VIDEL_HFS_WriteWord(void)
                    370: {
                    371:        Uint16 hfs = IoMem_ReadWord(0xff828e);
                    372: 
                    373:        LOG_TRACE(TRACE_VIDEL, "Videl : $ffff828e Horizontal FS (HFS) write: 0x%02x\n", hfs);
                    374: }
                    375: 
                    376: /**
                    377:  *  Write Horizontal EE (HEE)
                    378:  */
                    379: void VIDEL_HEE_WriteWord(void)
                    380: {
                    381:        Uint16 hee = IoMem_ReadWord(0xff8290);
                    382: 
                    383:        LOG_TRACE(TRACE_VIDEL, "Videl : $ffff8290 Horizontal EE (HEE) write: 0x%02x\n", hee);
                    384: }
                    385: 
                    386: /**
                    387:  *  Write Vertical Frequency Counter (VFC)
                    388:  */
                    389: void VIDEL_VFC_ReadWord(void)
                    390: {
                    391:        IoMem_WriteWord(0xff82a0, vfc_counter);
                    392:        LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82a0 Vertical Frequency Counter (VFC) read: 0x%02x\n", vfc_counter);
                    393: }
                    394: 
                    395: /**
                    396:  *  Write Vertical Frequency Timer (VFT)
                    397:  */
                    398: void VIDEL_VFT_WriteWord(void)
                    399: {
                    400:        Uint16 vft = IoMem_ReadWord(0xff82a2);
                    401: 
                    402:        LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82a2 Vertical Frequency Timer (VFT) write: 0x%02x\n", vft);
                    403: }
                    404: 
                    405: /**
                    406:  *  Write Vertical Border Begin (VBB)
                    407:  */
                    408: void VIDEL_VBB_WriteWord(void)
                    409: {
                    410:        Uint16 vbb = IoMem_ReadWord(0xff82a4);
                    411: 
                    412:        LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82a4 Vertical Border Begin (VBB) write: 0x%02x\n", vbb);
                    413: }
                    414: 
                    415: /**
                    416:  *  Write Vertical Border End (VBE)
                    417:  */
                    418: void VIDEL_VBE_WriteWord(void)
                    419: {
                    420:        Uint16 vbe = IoMem_ReadWord(0xff82a6);
                    421: 
                    422:        LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82a6 Vertical Border End (VBE) write: 0x%02x\n", vbe);
                    423: }
                    424: 
                    425: /**
                    426:  *  Write Vertical Display Begin (VDB)
                    427:  */
                    428: void VIDEL_VDB_WriteWord(void)
1.1       root      429: {
1.1.1.6   root      430:        Uint16 vdb = IoMem_ReadWord(0xff82a8);
                    431: 
                    432:        LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82a8 Vertical Display Begin (VDB) write: 0x%02x\n", vdb);
1.1       root      433: }
                    434: 
1.1.1.6   root      435: /**
                    436:  *  Write Vertical Display End (VDE)
                    437:  */
                    438: void VIDEL_VDE_WriteWord(void)
                    439: {
                    440:        Uint16 vde = IoMem_ReadWord(0xff82aa);
                    441: 
                    442:        LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82aa Vertical Display End (VDE) write: 0x%02x\n", vde);
                    443: }
                    444: 
                    445: /**
                    446:  *  Write Vertical SS (VSS)
                    447:  */
                    448: void VIDEL_VSS_WriteWord(void)
                    449: {
                    450:        Uint16 vss = IoMem_ReadWord(0xff82ac);
                    451: 
                    452:        LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82ac Vertical SS (VSS) write: 0x%02x\n", vss);
                    453: }
                    454: 
                    455: /**
                    456:  *  Write Video Control (VCO)
                    457:  */
                    458: void VIDEL_VCO_WriteWord(void)
                    459: {
                    460:        Uint16 vco = IoMem_ReadWord(0xff82c0);
                    461: 
                    462:        LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82c0 Video control (VCO) write: 0x%02x\n", vco);
                    463: }
                    464: 
                    465: /**
                    466:  *  Write Video Mode (VDM)
                    467:  */
                    468: void VIDEL_VMD_WriteWord(void)
                    469: {
                    470:        Uint16 vdm = IoMem_ReadWord(0xff82c2);
                    471: 
                    472:        LOG_TRACE(TRACE_VIDEL, "Videl : $ffff82c2 Video Mode (VDM) write: 0x%02x\n", vdm);
                    473: }
                    474: 
                    475: 
1.1       root      476: static long VIDEL_getVideoramAddress(void)
                    477: {
                    478:        return (handleRead(HW + 1) << 16) | (handleRead(HW + 3) << 8) | handleRead(HW + 0x0d);
                    479: }
                    480: 
                    481: static int VIDEL_getScreenBpp(void)
                    482: {
                    483:        int f_shift = handleReadW(HW + 0x66);
                    484:        int st_shift = handleRead(HW + 0x60);
                    485:        /* to get bpp, we must examine f_shift and st_shift.
                    486:         * f_shift is valid if any of bits no. 10, 8 or 4
                    487:         * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
                    488:         * if bit 10 set then bit 8 and bit 4 don't care...
                    489:         * If all these bits are 0 and ST shifter is written
                    490:         * after Falcon one, get display depth from st_shift
                    491:         * (as for ST and STE)
                    492:         */
                    493:        int bits_per_pixel;
                    494:        if (f_shift & 0x400)            /* Falcon: 2 colors */
                    495:                bits_per_pixel = 1;
                    496:        else if (f_shift & 0x100)       /* Falcon: hicolor */
                    497:                bits_per_pixel = 16;
                    498:        else if (f_shift & 0x010)       /* Falcon: 8 bitplanes */
                    499:                bits_per_pixel = 8;
1.1.1.6   root      500:        else if (!videl.bUseSTShifter)  /* Falcon: 4 bitplanes */
1.1       root      501:                bits_per_pixel = 4;
                    502:        else if (st_shift == 0)
                    503:                bits_per_pixel = 4;
                    504:        else if (st_shift == 0x01)
                    505:                bits_per_pixel = 2;
                    506:        else /* if (st_shift == 0x02) */
                    507:                bits_per_pixel = 1;
                    508: 
                    509:        // Dprintf(("Videl works in %d bpp, f_shift=%04x, st_shift=%d", bits_per_pixel, f_shift, st_shift));
                    510: 
                    511:        return bits_per_pixel;
                    512: }
                    513: 
                    514: static int VIDEL_getScreenWidth(void)
                    515: {
1.1.1.4   root      516:        return (handleReadW(HW + 0x10) & 0x03ff) * 16 / VIDEL_getScreenBpp();
1.1       root      517: }
                    518: 
                    519: static int VIDEL_getScreenHeight(void)
                    520: {
1.1.1.4   root      521:        int vdb = handleReadW(HW + 0xa8) & 0x07ff;
                    522:        int vde = handleReadW(HW + 0xaa) & 0x07ff;
1.1       root      523:        int vmode = handleReadW(HW + 0xc2);
                    524: 
                    525:        /* visible y resolution:
                    526:         * Graphics display starts at line VDB and ends at line
                    527:         * VDE. If interlace mode off unit of VC-registers is
                    528:         * half lines, else lines.
                    529:         */
                    530:        int yres = vde - vdb;
                    531:        if (!(vmode & 0x02))            // interlace
                    532:                yres >>= 1;
1.1.1.4   root      533:        if (vmode & 0x01)               // double
1.1       root      534:                yres >>= 1;
                    535: 
                    536:        return yres;
                    537: }
                    538: 
1.1.1.5   root      539: #if 0
                    540: /* this is easier & more robustly done in hostscreen.c just by
                    541:  * comparing requested screen width & height to each other.
                    542:  */
                    543: static void VIDEL_getMonitorScale(int *sx, int *sy)
                    544: {
                    545:        /* Videl video mode register bits and resulting desktop resolution:
                    546:         * 
                    547:         * quarter, half, interlace, double:   pixels: -> zoom:
                    548:         * rgb:
                    549:         *    0       0       0         0      320x200 -> 2 x 2
                    550:         *    0       0       1         0      320x400 -> 2 x 1
                    551:         *    0       1       0         0      640x200 -> 1 x 2 !
                    552:         *    0       1       1         0      640x400 -> 1 x 1
                    553:         * vga:
                    554:         *    0       0       0         1      (just double ?)
                    555:         *    0       0       1         1      (double & interlace ???)
                    556:         *    0       1       0         0      320x480 -> 2 x 1 !
                    557:         *    0       1       0         1      320x240 -> 2 x 2
                    558:         *    0       1       1         1      (double + interlace ???)
                    559:         *    1       0       0         0      640x480 -> 1 x 1
                    560:         *    1       0       0         1      640x240 -> 1 x 2
                    561:         */
                    562:        int vmode = handleReadW(HW + 0xc2);
                    563: 
                    564:        /* half pixel seems to have opposite meaning on
                    565:         * VGA and RGB monitor, so they need to handled separately
                    566:         */
1.1.1.6   root      567:        if (videl.monitor_type) == FALCON_MONITOR_VGA) {
1.1.1.5   root      568:                if (vmode & 0x08) {  // quarter pixel
                    569:                        *sx = 1;
                    570:                } else {
                    571:                        *sx = 2;
                    572:                }
                    573:                if (vmode & 0x01) {  // double line
                    574:                        *sy = 2;
                    575:                } else {
                    576:                        *sy = 1;
                    577:                }
                    578:        } else {
                    579:                if (vmode & 0x04) {  // half pixel
                    580:                        *sx = 1;
                    581:                } else {
                    582:                        *sx = 2;
                    583:                }
                    584:                if (vmode & 0x02) {  // interlace used only on RGB?
                    585:                        *sy = 1;
                    586:                } else {
                    587:                        *sy = 2;
                    588:                }
                    589:        }
                    590: }
                    591: #endif
                    592: 
1.1       root      593: 
                    594: /** map the correct colortable into the correct pixel format
                    595:  */
                    596: static void VIDEL_updateColors(void)
                    597: {
                    598:        //Dprintf(("ColorUpdate in progress\n"));
                    599: 
                    600:        int i, r, g, b, colors = 1 << bpp;
                    601: 
                    602: #define F_COLORS(i) handleRead(VIDEL_COLOR_REGS_BEGIN + (i))
                    603: #define STE_COLORS(i)  handleRead(0xff8240 + (i))
                    604: 
1.1.1.6   root      605:        if (!videl.bUseSTShifter) {
1.1       root      606:                for (i = 0; i < colors; i++) {
                    607:                        int offset = i << 2;
                    608:                        r = F_COLORS(offset) & 0xfc;
                    609:                        r |= r>>6;
                    610:                        g = F_COLORS(offset + 1) & 0xfc;
                    611:                        g |= g>>6;
                    612:                        b = F_COLORS(offset + 3) & 0xfc;
                    613:                        b |= b>>6;
                    614:                        HostScreen_setPaletteColor(i, r,g,b);
                    615:                }
                    616:                HostScreen_updatePalette(colors);
                    617:        } else {
                    618:                for (i = 0; i < colors; i++) {
                    619:                        int offset = i << 1;
                    620:                        r = STE_COLORS(offset) & 0x0f;
                    621:                        r = ((r & 7)<<1)|(r>>3);
                    622:                        r |= r<<4;
                    623:                        g = (STE_COLORS(offset + 1)>>4) & 0x0f;
                    624:                        g = ((g & 7)<<1)|(g>>3);
                    625:                        g |= g<<4;
                    626:                        b = STE_COLORS(offset + 1) & 0x0f;
                    627:                        b = ((b & 7)<<1)|(b>>3);
                    628:                        b |= b<<4;
                    629:                        HostScreen_setPaletteColor(i, r,g,b);
                    630:                }
                    631:                HostScreen_updatePalette(colors);
                    632:        }
                    633: 
1.1.1.4   root      634:        hostColorsSync = true;
1.1       root      635: }
                    636: 
                    637: 
                    638: void VIDEL_ZoomModeChanged(void)
                    639: {
                    640:        /* User selected another zoom mode, so set a new screen resolution now */
1.1.1.4   root      641:        HostScreen_setWindowSize(width, height, bpp == 16 ? 16 : ConfigureParams.Screen.nForceBpp);
1.1       root      642: }
                    643: 
                    644: 
1.1.1.2   root      645: bool VIDEL_renderScreen(void)
1.1       root      646: {
                    647:        int vw   = VIDEL_getScreenWidth();
                    648:        int vh   = VIDEL_getScreenHeight();
                    649:        int vbpp = VIDEL_getScreenBpp();
1.1.1.6   root      650:        bool change = false;
1.1       root      651: 
1.1.1.6   root      652:        if (vw > 0 && vw != width) {
                    653:                Dprintf(("CH width %d\n", width));
                    654:                width = vw;
                    655:                change = true;
1.1       root      656:        }
1.1.1.6   root      657:        if (vh > 0 && vh != height) {
                    658:                Dprintf(("CH height %d\n", width));
                    659:                height = vh;
                    660:                change = true;
1.1       root      661:        }
1.1.1.6   root      662:        if (vbpp != bpp) {
                    663:                Dprintf(("CH bpp %d\n", vbpp));
                    664:                bpp = vbpp;
                    665:                change = true;
                    666:        }
                    667:        if (change) {
                    668:                LOG_TRACE(TRACE_VIDEL, "Videl : video mode change to %dx%d@%d\n", width, height, bpp);
                    669:                HostScreen_setWindowSize(width, height, bpp == 16 ? 16 : ConfigureParams.Screen.nForceBpp);
1.1       root      670:        }
                    671: 
                    672:        if (!HostScreen_renderBegin())
1.1.1.2   root      673:                return false;
1.1       root      674: 
1.1.1.5   root      675:        if (nScreenZoomX * nScreenZoomY != 1) {
1.1       root      676:                VIDEL_renderScreenZoom();
                    677:        } else {
                    678:                VIDEL_renderScreenNoZoom();
                    679:        }
                    680: 
                    681:        HostScreen_renderEnd();
                    682: 
1.1.1.4   root      683:        HostScreen_update1(false);
1.1.1.2   root      684: 
                    685:        return true;
1.1       root      686: }
                    687: 
                    688: 
1.1.1.4   root      689: /**
                    690:  * Performs conversion from the TOS's bitplane word order (big endian) data
                    691:  * into the native chunky color index.
                    692:  */
                    693: static void Videl_bitplaneToChunky(Uint16 *atariBitplaneData, Uint16 bpp,
                    694:                                    Uint8 colorValues[16])
                    695: {
                    696:        Uint32 a, b, c, d, x;
                    697: 
                    698:        /* Obviously the different cases can be broken out in various
                    699:         * ways to lessen the amount of work needed for <8 bit modes.
                    700:         * It's doubtful if the usage of those modes warrants it, though.
                    701:         * The branches below should be ~100% correctly predicted and
                    702:         * thus be more or less for free.
                    703:         * Getting the palette values inline does not seem to help
                    704:         * enough to worry about. The palette lookup is much slower than
                    705:         * this code, though, so it would be nice to do something about it.
                    706:         */
                    707:        if (bpp >= 4) {
                    708:                d = *(Uint32 *)&atariBitplaneData[0];
                    709:                c = *(Uint32 *)&atariBitplaneData[2];
                    710:                if (bpp == 4) {
                    711:                        a = b = 0;
                    712:                } else {
                    713:                        b = *(Uint32 *)&atariBitplaneData[4];
                    714:                        a = *(Uint32 *)&atariBitplaneData[6];
                    715:                }
                    716:        } else {
                    717:                a = b = c = 0;
                    718:                if (bpp == 2) {
                    719:                        d = *(Uint32 *)&atariBitplaneData[0];
                    720:                } else {
                    721: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
                    722:                        d = atariBitplaneData[0]<<16;
                    723: #else
                    724:                        d = atariBitplaneData[0];
                    725: #endif
                    726:                }
                    727:        }
                    728: 
                    729:        x = a;
                    730:        a =  (a & 0xf0f0f0f0)       | ((c & 0xf0f0f0f0) >> 4);
                    731:        c = ((x & 0x0f0f0f0f) << 4) |  (c & 0x0f0f0f0f);
                    732:        x = b;
                    733:        b =  (b & 0xf0f0f0f0)       | ((d & 0xf0f0f0f0) >> 4);
                    734:        d = ((x & 0x0f0f0f0f) << 4) |  (d & 0x0f0f0f0f);
                    735: 
                    736:        x = a;
                    737:        a =  (a & 0xcccccccc)       | ((b & 0xcccccccc) >> 2);
                    738:        b = ((x & 0x33333333) << 2) |  (b & 0x33333333);
                    739:        x = c;
                    740:        c =  (c & 0xcccccccc)       | ((d & 0xcccccccc) >> 2);
                    741:        d = ((x & 0x33333333) << 2) |  (d & 0x33333333);
                    742: 
                    743: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
                    744:        a = (a & 0x5555aaaa) | ((a & 0x00005555) << 17) | ((a & 0xaaaa0000) >> 17);
                    745:        b = (b & 0x5555aaaa) | ((b & 0x00005555) << 17) | ((b & 0xaaaa0000) >> 17);
                    746:        c = (c & 0x5555aaaa) | ((c & 0x00005555) << 17) | ((c & 0xaaaa0000) >> 17);
                    747:        d = (d & 0x5555aaaa) | ((d & 0x00005555) << 17) | ((d & 0xaaaa0000) >> 17);
                    748: 
                    749:        colorValues[ 8] = a;
                    750:        a >>= 8;
                    751:        colorValues[ 0] = a;
                    752:        a >>= 8;
                    753:        colorValues[ 9] = a;
                    754:        a >>= 8;
                    755:        colorValues[ 1] = a;
                    756: 
                    757:        colorValues[10] = b;
                    758:        b >>= 8;
                    759:        colorValues[ 2] = b;
                    760:        b >>= 8;
                    761:        colorValues[11] = b;
                    762:        b >>= 8;
                    763:        colorValues[ 3] = b;
                    764: 
                    765:        colorValues[12] = c;
                    766:        c >>= 8;
                    767:        colorValues[ 4] = c;
                    768:        c >>= 8;
                    769:        colorValues[13] = c;
                    770:        c >>= 8;
                    771:        colorValues[ 5] = c;
                    772: 
                    773:        colorValues[14] = d;
                    774:        d >>= 8;
                    775:        colorValues[ 6] = d;
                    776:        d >>= 8;
                    777:        colorValues[15] = d;
                    778:        d >>= 8;
                    779:        colorValues[ 7] = d;
                    780: #else
                    781:        a = (a & 0xaaaa5555) | ((a & 0x0000aaaa) << 15) | ((a & 0x55550000) >> 15);
                    782:        b = (b & 0xaaaa5555) | ((b & 0x0000aaaa) << 15) | ((b & 0x55550000) >> 15);
                    783:        c = (c & 0xaaaa5555) | ((c & 0x0000aaaa) << 15) | ((c & 0x55550000) >> 15);
                    784:        d = (d & 0xaaaa5555) | ((d & 0x0000aaaa) << 15) | ((d & 0x55550000) >> 15);
                    785: 
                    786:        colorValues[ 1] = a;
                    787:        a >>= 8;
                    788:        colorValues[ 9] = a;
                    789:        a >>= 8;
                    790:        colorValues[ 0] = a;
                    791:        a >>= 8;
                    792:        colorValues[ 8] = a;
                    793: 
                    794:        colorValues[ 3] = b;
                    795:        b >>= 8;
                    796:        colorValues[11] = b;
                    797:        b >>= 8;
                    798:        colorValues[ 2] = b;
                    799:        b >>= 8;
                    800:        colorValues[10] = b;
                    801: 
                    802:        colorValues[ 5] = c;
                    803:        c >>= 8;
                    804:        colorValues[13] = c;
                    805:        c >>= 8;
                    806:        colorValues[ 4] = c;
                    807:        c >>= 8;
                    808:        colorValues[12] = c;
                    809: 
                    810:        colorValues[ 7] = d;
                    811:        d >>= 8;
                    812:        colorValues[15] = d;
                    813:        d >>= 8;
                    814:        colorValues[ 6] = d;
                    815:        d >>= 8;
                    816:        colorValues[14] = d;
                    817: #endif
                    818: }
                    819: 
                    820: 
1.1       root      821: static void VIDEL_renderScreenNoZoom(void)
                    822: {
                    823:        int vw   = VIDEL_getScreenWidth();
                    824:        int vh   = VIDEL_getScreenHeight();
                    825: 
                    826:        int lineoffset = handleReadW(HW + 0x0e) & 0x01ff; // 9 bits
                    827:        int linewidth = handleReadW(HW + 0x10) & 0x03ff; // 10 bits
                    828:        /* 
                    829:           I think this implementation is naive: 
                    830:           indeed, I suspect that we should instead skip lineoffset
                    831:           words each time we have read "more" than linewidth words
                    832:           (possibly "more" because of the number of bit planes).
                    833:           Moreover, the 1 bit plane mode is particular;
                    834:           while doing some experiments on my Falcon, it seems to
                    835:           behave like the 4 bit planes mode.
                    836:           At last, we have also to take into account the 4 bits register
                    837:           located at the word $ffff8264 (bit offset). This register makes
                    838:           the semantics of the lineoffset register change a little.
                    839:           int bitoffset = handleReadW(HW + 0x64) & 0x000f;
                    840:           The meaning of this register in True Color mode is not clear
                    841:           for me at the moment (and my experiments on the Falcon don't help
                    842:           me).
                    843:        */
                    844:        int nextline = linewidth + lineoffset;
                    845: 
                    846:        if (bpp < 16 && !hostColorsSync) {
                    847:                VIDEL_updateColors();
                    848:        }
                    849: 
                    850:        VIDEL_ConvertScreenNoZoom(vw, vh, bpp, nextline);
                    851: }
                    852: 
                    853: 
                    854: void VIDEL_ConvertScreenNoZoom(int vw, int vh, int vbpp, int nextline)
                    855: {
                    856:        int scrpitch = HostScreen_getPitch();
                    857: 
                    858:        long atariVideoRAM = VIDEL_getVideoramAddress();
                    859: 
1.1.1.2   root      860:        Uint16 *fvram = (Uint16 *) Atari2HostAddr(atariVideoRAM);
                    861:        Uint8 *hvram = HostScreen_getVideoramAddress();
1.1.1.6   root      862:        SDL_PixelFormat *scrfmt = HostScreen_getFormat();
1.1       root      863: 
                    864:        int hscrolloffset = (handleRead(HW + 0x65) & 0x0f);
                    865: 
                    866:        /* Clip to SDL_Surface dimensions */
                    867:        int scrwidth = HostScreen_getWidth();
                    868:        int scrheight = HostScreen_getHeight();
                    869:        int vw_clip = vw;
                    870:        int vh_clip = vh;
                    871:        if (vw>scrwidth) vw_clip = scrwidth;
                    872:        if (vh>scrheight) vh_clip = scrheight;  
                    873: 
                    874:        /* Horizontal scroll register set? */
                    875:        if (hscrolloffset) {
                    876:                /* Yes, so we need to adjust offset to next line: */
                    877:                nextline += vbpp;
                    878:        }
                    879: 
                    880:        /* Center screen */
                    881:        hvram += ((scrheight-vh_clip)>>1)*scrpitch;
                    882:        hvram += ((scrwidth-vw_clip)>>1)*HostScreen_getBpp();
                    883: 
                    884:        /* Render */
                    885:        if (vbpp < 16) {
                    886:                /* Bitplanes modes */
                    887: 
                    888:                // The SDL colors blitting...
1.1.1.2   root      889:                Uint8 color[16];
1.1       root      890: 
                    891:                // FIXME: The byte swap could be done here by enrolling the loop into 2 each by 8 pixels
                    892:                switch ( HostScreen_getBpp() ) {
                    893:                        case 1:
                    894:                                {
1.1.1.2   root      895:                                        Uint16 *fvram_line = fvram;
                    896:                                        Uint8 *hvram_line = hvram;
1.1       root      897:                                        int h;
                    898: 
                    899:                                        for (h = 0; h < vh_clip; h++) {
1.1.1.2   root      900:                                                Uint16 *fvram_column = fvram_line;
                    901:                                                Uint8 *hvram_column = hvram_line;
1.1       root      902:                                                int w;
                    903: 
                    904:                                                /* First 16 pixels: */
1.1.1.4   root      905:                                                Videl_bitplaneToChunky(fvram_column, vbpp, color);
1.1       root      906:                                                memcpy(hvram_column, color+hscrolloffset, 16-hscrolloffset);
                    907:                                                hvram_column += 16-hscrolloffset;
                    908:                                                fvram_column += vbpp;
                    909:                                                /* Now the main part of the line: */
                    910:                                                for (w = 1; w < (vw_clip+15)>>4; w++) {
1.1.1.4   root      911:                                                        Videl_bitplaneToChunky( fvram_column, vbpp, color );
1.1       root      912:                                                        memcpy(hvram_column, color, 16);
                    913:                                                        hvram_column += 16;
                    914:                                                        fvram_column += vbpp;
                    915:                                                }
                    916:                                                /* Last pixels of the line for fine scrolling: */
                    917:                                                if (hscrolloffset) {
1.1.1.4   root      918:                                                        Videl_bitplaneToChunky(fvram_column, vbpp, color);
1.1       root      919:                                                        memcpy(hvram_column, color, hscrolloffset);
                    920:                                                }
                    921: 
                    922:                                                hvram_line += scrpitch;
                    923:                                                fvram_line += nextline;
                    924:                                        }
                    925:                                }
                    926:                                break;
                    927:                        case 2:
                    928:                                {
1.1.1.2   root      929:                                        Uint16 *fvram_line = fvram;
                    930:                                        Uint16 *hvram_line = (Uint16 *)hvram;
1.1       root      931:                                        int h;
                    932: 
                    933:                                        for (h = 0; h < vh_clip; h++) {
1.1.1.2   root      934:                                                Uint16 *fvram_column = fvram_line;
                    935:                                                Uint16 *hvram_column = hvram_line;
1.1.1.4   root      936:                                                int w, j;
1.1       root      937: 
1.1.1.4   root      938:                                                /* First 16 pixels: */
                    939:                                                Videl_bitplaneToChunky(fvram_column, vbpp, color);
                    940:                                                for (j = 0; j < 16 - hscrolloffset; j++) {
                    941:                                                        *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]);
                    942:                                                }
                    943:                                                fvram_column += vbpp;
                    944:                                                /* Now the main part of the line: */
                    945:                                                for (w = 1; w < (vw_clip+15)>>4; w++) {
                    946:                                                        Videl_bitplaneToChunky( fvram_column, vbpp, color );
1.1       root      947:                                                        for (j=0; j<16; j++) {
                    948:                                                                *hvram_column++ = HostScreen_getPaletteColor( color[j] );
                    949:                                                        }
                    950:                                                        fvram_column += vbpp;
                    951:                                                }
1.1.1.4   root      952:                                                /* Last pixels of the line for fine scrolling: */
                    953:                                                if (hscrolloffset) {
                    954:                                                        Videl_bitplaneToChunky(fvram_column, vbpp, color);
                    955:                                                        for (j = 0; j < hscrolloffset; j++) {
                    956:                                                                *hvram_column++ = HostScreen_getPaletteColor(color[j]);
1.1       root      957:                                                        }
                    958:                                                }
                    959: 
1.1.1.4   root      960:                                                hvram_line += scrpitch>>1;
1.1       root      961:                                                fvram_line += nextline;
                    962:                                        }
                    963:                                }
                    964:                                break;
                    965:                        case 4:
                    966:                                {
1.1.1.2   root      967:                                        Uint16 *fvram_line = fvram;
                    968:                                        Uint32 *hvram_line = (Uint32 *)hvram;
1.1       root      969:                                        int h;
                    970: 
                    971:                                        for (h = 0; h < vh_clip; h++) {
1.1.1.2   root      972:                                                Uint16 *fvram_column = fvram_line;
                    973:                                                Uint32 *hvram_column = hvram_line;
1.1.1.4   root      974:                                                int w, j;
1.1       root      975: 
1.1.1.4   root      976:                                                /* First 16 pixels: */
                    977:                                                Videl_bitplaneToChunky(fvram_column, vbpp, color);
                    978:                                                for (j = 0; j < 16 - hscrolloffset; j++) {
                    979:                                                        *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]);
                    980:                                                }
                    981:                                                fvram_column += vbpp;
                    982:                                                /* Now the main part of the line: */
                    983:                                                for (w = 1; w < (vw_clip+15)>>4; w++) {
                    984:                                                        Videl_bitplaneToChunky( fvram_column, vbpp, color );
1.1       root      985:                                                        for (j=0; j<16; j++) {
                    986:                                                                *hvram_column++ = HostScreen_getPaletteColor( color[j] );
                    987:                                                        }
                    988:                                                        fvram_column += vbpp;
                    989:                                                }
1.1.1.4   root      990:                                                /* Last pixels of the line for fine scrolling: */
                    991:                                                if (hscrolloffset) {
                    992:                                                        Videl_bitplaneToChunky(fvram_column, vbpp, color);
                    993:                                                        for (j = 0; j < hscrolloffset; j++) {
                    994:                                                                *hvram_column++ = HostScreen_getPaletteColor(color[j]);
                    995:                                                        }
                    996:                                                }
1.1       root      997: 
                    998:                                                hvram_line += scrpitch>>2;
                    999:                                                fvram_line += nextline;
                   1000:                                        }
                   1001:                                }
                   1002:                                break;
                   1003:                }
                   1004: 
                   1005:        } else {
                   1006: 
                   1007:                // Falcon TC (High Color)
                   1008:                switch ( HostScreen_getBpp() )  {
                   1009:                        case 1:
                   1010:                                {
                   1011:                                        /* FIXME: when Videl switches to 16bpp, set the palette to 3:3:2 */
1.1.1.2   root     1012:                                        Uint16 *fvram_line = fvram;
                   1013:                                        Uint8 *hvram_line = hvram;
1.1       root     1014:                                        int h;
                   1015: 
                   1016:                                        for (h = 0; h < vh_clip; h++) {
1.1.1.2   root     1017:                                                Uint16 *fvram_column = fvram_line;
                   1018:                                                Uint8 *hvram_column = hvram_line;
1.1       root     1019:                                                int w, tmp;
                   1020: 
                   1021:                                                for (w = 0; w < vw_clip; w++) {
                   1022:                                                        
                   1023:                                                        tmp = SDL_SwapBE16(*fvram_column);
                   1024: 
                   1025:                                                        *hvram_column = ((tmp>>13) & 7) << 5;
                   1026:                                                        *hvram_column |= ((tmp>>8) & 7) << 2;
                   1027:                                                        *hvram_column |= ((tmp>>2) & 3);
                   1028: 
                   1029:                                                        hvram_column++;
                   1030:                                                        fvram_column++;
                   1031:                                                }
                   1032: 
                   1033:                                                hvram_line += scrpitch;
                   1034:                                                fvram_line += nextline;
                   1035:                                        }
                   1036:                                }
                   1037:                                break;
                   1038:                        case 2:
                   1039:                                {
1.1.1.2   root     1040:                                        Uint16 *fvram_line = fvram;
                   1041:                                        Uint16 *hvram_line = (Uint16 *)hvram;
1.1       root     1042:                                        int h;
                   1043: 
                   1044:                                        for (h = 0; h < vh_clip; h++) {
                   1045: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
                   1046:                                                //FIXME: here might be a runtime little/big video endian switch like:
                   1047:                                                //      if ( /* videocard memory in Motorola endian format */ false)
                   1048:                                                memcpy(hvram_line, fvram_line, vw_clip<<1);
                   1049: #else
                   1050:                                                int w;
1.1.1.2   root     1051:                                                Uint16 *fvram_column = fvram_line;
                   1052:                                                Uint16 *hvram_column = hvram_line;
1.1       root     1053: 
                   1054:                                                for (w = 0; w < vw_clip; w++) {
                   1055:                                                        // byteswap with SDL asm macros
                   1056:                                                        *hvram_column++ = SDL_SwapBE16(*fvram_column++);
                   1057:                                                }
                   1058: #endif // SDL_BYTEORDER == SDL_BIG_ENDIAN
                   1059: 
                   1060:                                                hvram_line += scrpitch>>1;
                   1061:                                                fvram_line += nextline;
                   1062:                                        }
                   1063:                                }
                   1064:                                break;
                   1065:                        case 4:
                   1066:                                {
1.1.1.2   root     1067:                                        Uint16 *fvram_line = fvram;
                   1068:                                        Uint32 *hvram_line = (Uint32 *)hvram;
1.1       root     1069:                                        int h;
                   1070: 
                   1071:                                        for (h = 0; h < vh_clip; h++) {
1.1.1.2   root     1072:                                                Uint16 *fvram_column = fvram_line;
                   1073:                                                Uint32 *hvram_column = hvram_line;
1.1       root     1074:                                                int w;
                   1075: 
                   1076:                                                for (w = 0; w < vw_clip; w++) {
1.1.1.6   root     1077:                                                        Uint16 srcword = *fvram_column++;
1.1       root     1078: 
                   1079:                                                        *hvram_column++ =
1.1.1.6   root     1080:                                                                SDL_MapRGB(scrfmt,
                   1081:                                                                           (srcword & 0xf8),
                   1082:                                                                           (((srcword & 0x07) << 5) |
                   1083:                                                                                   ((srcword >> 11) & 0x3c)),
                   1084:                                                                           ((srcword >> 5) & 0xf8));
1.1       root     1085:                                                }
                   1086: 
                   1087:                                                hvram_line += scrpitch>>2;
                   1088:                                                fvram_line += nextline;
                   1089:                                        }
                   1090:                                }
                   1091:                                break;
                   1092:                }
                   1093:        }
                   1094: }
                   1095: 
                   1096: 
                   1097: static void VIDEL_renderScreenZoom(void)
                   1098: {
                   1099:        /* Atari screen infos */
                   1100:        int vw   = VIDEL_getScreenWidth();
                   1101:        int vh   = VIDEL_getScreenHeight();
                   1102: 
                   1103:        int lineoffset = handleReadW(HW + 0x0e) & 0x01ff; // 9 bits
                   1104:        int linewidth = handleReadW(HW + 0x10) & 0x03ff; // 10 bits
                   1105:        /* same remark as before: too naive */
                   1106:        int nextline = linewidth + lineoffset;
                   1107: 
                   1108:        if ((vw<32) || (vh<32))  return;
                   1109: 
                   1110:        if (bpp<16 && !hostColorsSync) {
                   1111:                VIDEL_updateColors();
                   1112:        }
                   1113: 
                   1114:        VIDEL_ConvertScreenZoom(vw, vh, bpp, nextline);
                   1115: }
                   1116: 
                   1117: 
                   1118: void VIDEL_ConvertScreenZoom(int vw, int vh, int vbpp, int nextline)
                   1119: {
                   1120:        int i, j, w, h, cursrcline;
                   1121: 
1.1.1.2   root     1122:        Uint16 *fvram = (Uint16 *) Atari2HostAddr(VIDEL_getVideoramAddress());
1.1       root     1123: 
                   1124:        /* Host screen infos */
                   1125:        int scrpitch = HostScreen_getPitch();
                   1126:        int scrwidth = HostScreen_getWidth();
                   1127:        int scrheight = HostScreen_getHeight();
                   1128:        int scrbpp = HostScreen_getBpp();
1.1.1.6   root     1129:        SDL_PixelFormat *scrfmt = HostScreen_getFormat();
1.1.1.2   root     1130:        Uint8 *hvram = (Uint8 *) HostScreen_getVideoramAddress();
1.1       root     1131: 
                   1132:        int hscrolloffset = (handleRead(HW + 0x65) & 0x0f);
                   1133: 
                   1134:        /* Horizontal scroll register set? */
                   1135:        if (hscrolloffset) {
                   1136:                /* Yes, so we need to adjust offset to next line: */
                   1137:                nextline += vbpp;
                   1138:        }
                   1139: 
                   1140:        /* Integer zoom coef ? */
                   1141:        if (/*(bx_options.autozoom.integercoefs) &&*/ (scrwidth>=vw) && (scrheight>=vh)) {
                   1142:                int coefx = scrwidth/vw;
                   1143:                int coefy = scrheight/vh;
                   1144: 
                   1145:                scrwidth = vw * coefx;
                   1146:                scrheight = vh * coefy;
                   1147: 
                   1148:                /* Center screen */
                   1149:                hvram += ((HostScreen_getHeight()-scrheight)>>1)*scrpitch;
                   1150:                hvram += ((HostScreen_getWidth()-scrwidth)>>1)*scrbpp;
                   1151:        }
                   1152: 
                   1153:        /* New zoom ? */
                   1154:        if ((zoomwidth != vw) || (scrwidth != prev_scrwidth)) {
                   1155:                if (zoomxtable) {
                   1156:                        free(zoomxtable);
                   1157:                }
                   1158:                zoomxtable = malloc(sizeof(int)*scrwidth);
                   1159:                for (i=0; i<scrwidth; i++) {
                   1160:                        zoomxtable[i] = (vw*i)/scrwidth;
                   1161:                }
                   1162:                zoomwidth = vw;
                   1163:                prev_scrwidth = scrwidth;
                   1164:        }
                   1165:        if ((zoomheight != vh) || (scrheight != prev_scrheight)) {
                   1166:                if (zoomytable) {
                   1167:                        free(zoomytable);
                   1168:                }
                   1169:                zoomytable = malloc(sizeof(int)*scrheight);
                   1170:                for (i=0; i<scrheight; i++) {
                   1171:                        zoomytable[i] = (vh*i)/scrheight;
                   1172:                }
                   1173:                zoomheight = vh;
                   1174:                prev_scrheight = scrheight;
                   1175:        }
                   1176: 
                   1177:        cursrcline = -1;
                   1178: 
                   1179:        if (vbpp<16) {
1.1.1.2   root     1180:                Uint8 color[16];
1.1       root     1181: 
                   1182:                /* Bitplanes modes */
                   1183:                switch(scrbpp) {
                   1184:                        case 1:
                   1185:                                {
1.1.1.7 ! root     1186:                                        /* One complete 16-pixel aligned planar 2 chunky line */
        !          1187:                                        Uint8 *p2cline = malloc(sizeof(Uint8) * ((vw+15) & ~15));
1.1       root     1188: 
1.1.1.2   root     1189:                                        Uint16 *fvram_line;
                   1190:                                        Uint8 *hvram_line = hvram;
1.1       root     1191: 
                   1192:                                        for (h = 0; h < scrheight; h++) {
                   1193:                                                fvram_line = fvram + (zoomytable[h] * nextline);
                   1194: 
                   1195:                                                /* Recopy the same line ? */
                   1196:                                                if (zoomytable[h] == cursrcline) {
                   1197:                                                        memcpy(hvram_line, hvram_line-scrpitch, scrwidth*scrbpp);
                   1198:                                                } else {
1.1.1.2   root     1199:                                                        Uint16 *fvram_column = fvram_line;
                   1200:                                                        Uint8 *hvram_column = p2cline;
1.1       root     1201: 
                   1202:                                                        /* First 16 pixels of a new line */
1.1.1.4   root     1203:                                                        Videl_bitplaneToChunky(fvram_column, vbpp, color);
1.1       root     1204:                                                        memcpy(hvram_column, color+hscrolloffset, 16-hscrolloffset);
                   1205:                                                        hvram_column += 16-hscrolloffset;
                   1206:                                                        fvram_column += vbpp;
                   1207:                                                        /* Convert main part of the new line */
                   1208:                                                        for (w=1; w < (vw+15)>>4; w++) {
1.1.1.4   root     1209:                                                                Videl_bitplaneToChunky( fvram_column, vbpp, color );
1.1       root     1210:                                                                memcpy(hvram_column, color, 16);
                   1211:                                                                hvram_column += 16;
                   1212:                                                                fvram_column += vbpp;
                   1213:                                                        }
                   1214:                                                        /* Last pixels of the line for fine scrolling: */
                   1215:                                                        if (hscrolloffset) {
1.1.1.4   root     1216:                                                                Videl_bitplaneToChunky(fvram_column, vbpp, color);
1.1       root     1217:                                                                memcpy(hvram_column, color, hscrolloffset);
                   1218:                                                        }
                   1219: 
                   1220:                                                        /* Zoom a new line */
                   1221:                                                        for (w=0; w<scrwidth; w++) {
                   1222:                                                                hvram_line[w] = p2cline[zoomxtable[w]];
                   1223:                                                        }
                   1224:                                                }
                   1225: 
                   1226:                                                hvram_line += scrpitch;
                   1227:                                                cursrcline = zoomytable[h];
                   1228:                                        }
                   1229: 
                   1230:                                        free(p2cline);
                   1231:                                }
                   1232:                                break;
                   1233:                        case 2:
                   1234:                                {
1.1.1.7 ! root     1235:                                        /* One complete 16-pixel aligned planar 2 chunky line */
        !          1236:                                        Uint16 *p2cline = malloc(sizeof(Uint16) * ((vw+15) & ~15));
1.1       root     1237: 
1.1.1.6   root     1238:                                        Uint16 *fvram_line;
1.1.1.2   root     1239:                                        Uint16 *hvram_line = (Uint16 *)hvram;
1.1       root     1240: 
                   1241:                                        for (h = 0; h < scrheight; h++) {
                   1242:                                                fvram_line = fvram + (zoomytable[h] * nextline);
                   1243: 
                   1244:                                                /* Recopy the same line ? */
                   1245:                                                if (zoomytable[h] == cursrcline) {
                   1246:                                                        memcpy(hvram_line, hvram_line-(scrpitch>>1), scrwidth*scrbpp);
                   1247:                                                } else {
1.1.1.2   root     1248:                                                        Uint16 *fvram_column = fvram_line;
                   1249:                                                        Uint16 *hvram_column = p2cline;
1.1       root     1250: 
1.1.1.4   root     1251:                                                        /* First 16 pixels of a new line: */
                   1252:                                                        Videl_bitplaneToChunky(fvram_column, vbpp, color);
                   1253:                                                        for (j = 0; j < 16 - hscrolloffset; j++) {
                   1254:                                                                *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]);
                   1255:                                                        }
                   1256:                                                        fvram_column += vbpp;
                   1257:                                                        /* Convert the main part of the new line: */
                   1258:                                                        for (w = 1; w < (vw+15)>>4; w++) {
                   1259:                                                                Videl_bitplaneToChunky( fvram_column, vbpp, color );
1.1       root     1260:                                                                for (j=0; j<16; j++) {
                   1261:                                                                        *hvram_column++ = HostScreen_getPaletteColor( color[j] );
                   1262:                                                                }
                   1263:                                                                fvram_column += vbpp;
                   1264:                                                        }
1.1.1.4   root     1265:                                                        /* Last pixels of the new line for fine scrolling: */
                   1266:                                                        if (hscrolloffset) {
                   1267:                                                                Videl_bitplaneToChunky(fvram_column, vbpp, color);
                   1268:                                                                for (j = 0; j < hscrolloffset; j++) {
                   1269:                                                                        *hvram_column++ = HostScreen_getPaletteColor(color[j]);
1.1       root     1270:                                                                }
                   1271:                                                        }
1.1.1.4   root     1272: 
1.1       root     1273:                                                        /* Zoom a new line */
                   1274:                                                        for (w=0; w<scrwidth; w++) {
1.1.1.4   root     1275:                                                                hvram_line[w] = p2cline[zoomxtable[w]];
1.1       root     1276:                                                        }
                   1277:                                                }
                   1278: 
1.1.1.4   root     1279:                                                hvram_line += scrpitch>>1;
1.1       root     1280:                                                cursrcline = zoomytable[h];
                   1281:                                        }
                   1282: 
                   1283:                                        free(p2cline);
                   1284:                                }
                   1285:                                break;
                   1286:                        case 4:
                   1287:                                {
1.1.1.7 ! root     1288:                                        /* One complete 16-pixel aligned planar 2 chunky line */
        !          1289:                                        Uint32 *p2cline = malloc(sizeof(Uint32) * ((vw+15) & ~15));
1.1.1.2   root     1290:                                        Uint16 *fvram_line;
                   1291:                                        Uint32 *hvram_line = (Uint32 *)hvram;
1.1       root     1292: 
                   1293:                                        for (h = 0; h < scrheight; h++) {
                   1294:                                                fvram_line = fvram + (zoomytable[h] * nextline);
                   1295: 
                   1296:                                                /* Recopy the same line ? */
                   1297:                                                if (zoomytable[h] == cursrcline) {
                   1298:                                                        memcpy(hvram_line, hvram_line-(scrpitch>>2), scrwidth*scrbpp);
                   1299:                                                } else {
1.1.1.2   root     1300:                                                        Uint16 *fvram_column = fvram_line;
                   1301:                                                        Uint32 *hvram_column = p2cline;
1.1       root     1302: 
1.1.1.4   root     1303:                                                        /* First 16 pixels of a new line: */
                   1304:                                                        Videl_bitplaneToChunky(fvram_column, vbpp, color);
                   1305:                                                        for (j = 0; j < 16 - hscrolloffset; j++) {
                   1306:                                                                *hvram_column++ = HostScreen_getPaletteColor(color[j+hscrolloffset]);
                   1307:                                                        }
                   1308:                                                        fvram_column += vbpp;
                   1309:                                                        /* Convert the main part of the new line: */
                   1310:                                                        for (w = 1; w < (vw+15)>>4; w++) {
                   1311:                                                                Videl_bitplaneToChunky( fvram_column, vbpp, color );
1.1       root     1312:                                                                for (j=0; j<16; j++) {
                   1313:                                                                        *hvram_column++ = HostScreen_getPaletteColor( color[j] );
                   1314:                                                                }
                   1315:                                                                fvram_column += vbpp;
                   1316:                                                        }
1.1.1.4   root     1317:                                                        /* Last pixels of the new line for fine scrolling: */
                   1318:                                                        if (hscrolloffset) {
                   1319:                                                                Videl_bitplaneToChunky(fvram_column, vbpp, color);
                   1320:                                                                for (j = 0; j < hscrolloffset; j++) {
                   1321:                                                                        *hvram_column++ = HostScreen_getPaletteColor(color[j]);
                   1322:                                                                }
                   1323:                                                        }
                   1324: 
1.1       root     1325:                                                        /* Zoom a new line */
                   1326:                                                        for (w=0; w<scrwidth; w++) {
                   1327:                                                                hvram_line[w] = p2cline[zoomxtable[w]];
                   1328:                                                        }
                   1329:                                                }
                   1330: 
                   1331:                                                hvram_line += scrpitch>>2;
                   1332:                                                cursrcline = zoomytable[h];
                   1333:                                        }
                   1334: 
                   1335:                                        free(p2cline);
                   1336:                                }
                   1337:                                break;
                   1338:                }
                   1339:        } else {
1.1.1.4   root     1340:                /* Falcon high-color (16-bit) mode */
1.1       root     1341: 
                   1342:                switch(scrbpp) {
                   1343:                        case 1:
                   1344:                                {
                   1345:                                        /* FIXME: when Videl switches to 16bpp, set the palette to 3:3:2 */
1.1.1.2   root     1346:                                        Uint16 *fvram_line;
                   1347:                                        Uint8 *hvram_line = hvram;
1.1       root     1348: 
                   1349:                                        for (h = 0; h < scrheight; h++) {
1.1.1.2   root     1350:                                                Uint16 *fvram_column;
                   1351:                                                Uint8 *hvram_column;
1.1       root     1352: 
                   1353:                                                fvram_line = fvram + (zoomytable[h] * nextline);
                   1354:                                                fvram_column = fvram_line;
                   1355:                                                hvram_column = hvram_line;
                   1356: 
                   1357:                                                /* Recopy the same line ? */
                   1358:                                                if (zoomytable[h] == cursrcline) {
                   1359:                                                        memcpy(hvram_line, hvram_line-scrpitch, scrwidth*scrbpp);
                   1360:                                                } else {
                   1361:                                                        for (w = 0; w < scrwidth; w++) {
1.1.1.2   root     1362:                                                                Uint16 srcword;
                   1363:                                                                Uint8 dstbyte;
1.1       root     1364:                                                        
                   1365:                                                                srcword = SDL_SwapBE16(fvram_column[zoomxtable[w]]);
                   1366: 
                   1367:                                                                dstbyte = ((srcword>>13) & 7) << 5;
                   1368:                                                                dstbyte |= ((srcword>>8) & 7) << 2;
                   1369:                                                                dstbyte |= ((srcword>>2) & 3);
                   1370: 
                   1371:                                                                *hvram_column++ = dstbyte;
                   1372:                                                        }
                   1373:                                                }
                   1374: 
                   1375:                                                hvram_line += scrpitch;
                   1376:                                                cursrcline = zoomytable[h];
                   1377:                                        }
                   1378:                                }
                   1379:                                break;
                   1380:                        case 2:
                   1381:                                {
1.1.1.2   root     1382:                                        Uint16 *fvram_line;
                   1383:                                        Uint16 *hvram_line = (Uint16 *)hvram;
1.1       root     1384: 
                   1385:                                        for (h = 0; h < scrheight; h++) {
1.1.1.2   root     1386:                                                Uint16 *fvram_column;
                   1387:                                                Uint16 *hvram_column;
1.1       root     1388: 
                   1389:                                                fvram_line = fvram + (zoomytable[h] * nextline);
                   1390:                                                fvram_column = fvram_line;
                   1391:                                                hvram_column = hvram_line;
                   1392: 
                   1393:                                                /* Recopy the same line ? */
                   1394:                                                if (zoomytable[h] == cursrcline) {
                   1395:                                                        memcpy(hvram_line, hvram_line-(scrpitch>>1), scrwidth*scrbpp);
                   1396:                                                } else {
                   1397:                                                        for (w = 0; w < scrwidth; w++) {
1.1.1.2   root     1398:                                                                Uint16 srcword;
1.1       root     1399:                                                        
                   1400:                                                                srcword = SDL_SwapBE16(fvram_column[zoomxtable[w]]);
                   1401:                                                                *hvram_column++ = srcword;
                   1402:                                                        }
                   1403:                                                }
                   1404: 
                   1405:                                                hvram_line += scrpitch>>1;
                   1406:                                                cursrcline = zoomytable[h];
                   1407:                                        }
                   1408:                                }
                   1409:                                break;
                   1410:                        case 4:
                   1411:                                {
1.1.1.2   root     1412:                                        Uint16 *fvram_line;
                   1413:                                        Uint32 *hvram_line = (Uint32 *)hvram;
1.1       root     1414: 
                   1415:                                        for (h = 0; h < scrheight; h++) {
1.1.1.2   root     1416:                                                Uint16 *fvram_column;
                   1417:                                                Uint32 *hvram_column;
1.1       root     1418: 
                   1419:                                                fvram_line = fvram + (zoomytable[h] * nextline);
                   1420:                                                fvram_column = fvram_line;
                   1421:                                                hvram_column = hvram_line;
                   1422: 
                   1423:                                                /* Recopy the same line ? */
                   1424:                                                if (zoomytable[h] == cursrcline) {
                   1425:                                                        memcpy(hvram_line, hvram_line-(scrpitch>>2), scrwidth*scrbpp);
                   1426:                                                } else {
                   1427:                                                        for (w = 0; w < scrwidth; w++) {
1.1.1.2   root     1428:                                                                Uint16 srcword;
1.1       root     1429:                                                        
                   1430:                                                                srcword = fvram_column[zoomxtable[w]];
                   1431: 
                   1432:                                                                *hvram_column++ =
1.1.1.6   root     1433:                                                                        SDL_MapRGB(scrfmt,
                   1434:                                                                                   (srcword & 0xf8),
                   1435:                                                                                   (((srcword & 0x07) << 5) |
                   1436:                                                                                           ((srcword >> 11) & 0x3c)),
                   1437:                                                                                   ((srcword >> 5) & 0xf8));
1.1       root     1438:                                                        }
                   1439:                                                }
                   1440: 
                   1441:                                                hvram_line += scrpitch>>2;
                   1442:                                                cursrcline = zoomytable[h];
                   1443:                                        }
                   1444:                                }
                   1445:                                break;
                   1446:                }
                   1447:        }
                   1448: }

unix.superglobalmegacorp.com

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