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

1.1       root        1: /*
                      2:   Hatari - videl.c
                      3: 
1.1.1.9   root        4:   This file is distributed under the GNU General Public License, version 2
                      5:   or at your option any later version. Read the file gpl.txt for details.
1.1       root        6: 
                      7:   Falcon Videl emulation. The Videl is the graphics shifter chip of the Falcon.
                      8:   It supports free programmable resolutions with 1, 2, 4, 8 or 16 bits per
                      9:   pixel.
                     10: 
                     11:   This file originally came from the Aranym project and has been heavily
                     12:   modified to work for Hatari (but the kudos for the great Videl emulation
                     13:   code goes to the people from the Aranym project of course).
1.1.1.6   root       14: 
                     15:   Videl can run at 2 frequencies : 25.175 Mhz or 32 MHz
1.1.1.12  root       16: 
1.1.1.6   root       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
1.1.1.12  root       30: 
1.1.1.6   root       31:        $FFFF8240 (word) : VDL_STC - ST Palette Register 00
                     32:        .........
                     33:        $FFFF825E (word) : VDL_STC - ST Palette Register 15
                     34: 
                     35:        $FFFF8260 (byte) : ST shift mode
1.1.1.8   root       36:        $FFFF8264 (byte) : Horizontal scroll register shadow register
1.1.1.6   root       37:        $FFFF8265 (byte) : Horizontal scroll register
                     38:        $FFFF8266 (word) : Falcon shift mode
1.1.1.12  root       39: 
1.1.1.6   root       40:        $FFFF8280 (word) : HHC - Horizontal Hold Counter
                     41:        $FFFF8282 (word) : HHT - Horizontal Hold Timer
                     42:        $FFFF8284 (word) : HBB - Horizontal Border Begin
                     43:        $FFFF8286 (word) : HBE - Horizontal Border End
                     44:        $FFFF8288 (word) : HDB - Horizontal Display Begin
                     45:        $FFFF828A (word) : HDE - Horizontal Display End
                     46:        $FFFF828C (word) : HSS - Horizontal SS
                     47:        $FFFF828E (word) : HFS - Horizontal FS
                     48:        $FFFF8290 (word) : HEE - Horizontal EE
1.1.1.12  root       49: 
1.1.1.6   root       50:        $FFFF82A0 (word) : VFC - Vertical Frequency Counter
                     51:        $FFFF82A2 (word) : VFT - Vertical Frequency Timer
                     52:        $FFFF82A4 (word) : VBB - Vertical Border Begin
                     53:        $FFFF82A6 (word) : VBE - Vertical Border End
                     54:        $FFFF82A8 (word) : VDB - Vertical Display Begin
                     55:        $FFFF82AA (word) : VDE - Vertical Display End
                     56:        $FFFF82AC (word) : VSS - Vertical SS
1.1.1.12  root       57: 
1.1.1.6   root       58:        $FFFF82C0 (word) : VCO - Video control
                     59:        $FFFF82C2 (word) : VMD - Video mode
                     60: 
                     61:        $FFFF9800 (long) : VDL_PAL - Videl palette Register 000
                     62:        ...........
                     63:        $FFFF98FC (long) : VDL_PAL - Videl palette Register 255
1.1       root       64: */
1.1.1.6   root       65: 
1.1.1.4   root       66: const char VIDEL_fileid[] = "Hatari videl.c : " __DATE__ " " __TIME__;
1.1       root       67: 
                     68: #include "main.h"
                     69: #include "configuration.h"
1.1.1.6   root       70: #include "memorySnapShot.h"
1.1       root       71: #include "ioMem.h"
1.1.1.6   root       72: #include "log.h"
1.1       root       73: #include "screen.h"
1.1.1.12  root       74: #include "screenConvert.h"
1.1.1.13! root       75: #include "avi_record.h"
1.1.1.12  root       76: #include "statusbar.h"
1.1       root       77: #include "stMemory.h"
                     78: #include "videl.h"
1.1.1.13! root       79: #include "video.h"                             /* for bUseHighRes variable */
        !            80: #include "vdi.h"                               /* for bUseVDIRes variable */
1.1       root       81: 
                     82: #define VIDEL_COLOR_REGS_BEGIN 0xff9800
                     83: 
1.1.1.8   root       84: 
1.1.1.6   root       85: struct videl_s {
                     86:        Uint8  reg_ffff8006_save;               /* save reg_ffff8006 as it's a read only register */
                     87:        Uint8  monitor_type;                    /* 00 Monochrome (SM124) / 01 Color (SC1224) / 10 VGA Color / 11 Television ($FFFF8006) */
1.1.1.13! root       88: 
        !            89:        Uint16 vertFreqCounter;                 /* Counter for VFC register $ff82a0, restarted on each VBL */
        !            90:        Uint32 videoRaster;                     /* Video raster offset, restarted on each VBL */
1.1.1.6   root       91: 
1.1.1.8   root       92:        Sint16 leftBorderSize;                  /* Size of the left border */
                     93:        Sint16 rightBorderSize;                 /* Size of the right border */
                     94:        Sint16 upperBorderSize;                 /* Size of the upper border */
                     95:        Sint16 lowerBorderSize;                 /* Size of the lower border */
                     96:        Uint16 XSize;                           /* X size of the graphical area */
                     97:        Uint16 YSize;                           /* Y size of the graphical area */
                     98: 
                     99:        Uint16 save_scrWidth;                   /* save screen width to detect a change of X resolution */
                    100:        Uint16 save_scrHeight;                  /* save screen height to detect a change of Y resolution */
                    101:        Uint16 save_scrBpp;                     /* save screen Bpp to detect a change of bitplan mode */
1.1       root      102: 
1.1.1.8   root      103:        bool hostColorsSync;                    /* Sync palette with host's */
1.1.1.13! root      104:        bool bUseSTShifter;                     /* whether to use ST or Falcon palette */
1.1.1.8   root      105: };
1.1.1.6   root      106: 
1.1.1.8   root      107: static struct videl_s videl;
1.1.1.6   root      108: 
                    109: 
1.1.1.12  root      110: /**
                    111:  * Called upon startup (and via VIDEL_reset())
                    112:  */
                    113: void Videl_Init(void)
                    114: {
                    115:        videl.hostColorsSync = false;
1.1.1.10  root      116: 
1.1.1.12  root      117:        /* Default resolution to boot with */
                    118:        videl.save_scrWidth = 640;
                    119:        videl.save_scrHeight = 480;
                    120:        videl.save_scrBpp = 4;
                    121: }
1.1       root      122: 
1.1.1.8   root      123: /**
1.1.1.12  root      124:  *  Called when CPU encounters a RESET instruction.
1.1.1.8   root      125:  */
1.1       root      126: void VIDEL_reset(void)
                    127: {
1.1.1.12  root      128:        Videl_Init();
                    129:        Screen_SetGenConvSize(videl.save_scrWidth, videl.save_scrHeight,
                    130:                              ConfigureParams.Screen.nForceBpp, false);
                    131: 
1.1.1.6   root      132:        videl.bUseSTShifter = false;                            /* Use Falcon color palette by default */
                    133:        videl.reg_ffff8006_save = IoMem_ReadByte(0xff8006);
1.1.1.8   root      134:        videl.monitor_type = videl.reg_ffff8006_save & 0xc0;
1.1       root      135: 
1.1.1.13! root      136:        VIDEL_RestartVideoCounter();
1.1.1.4   root      137: 
                    138:        /* Reset IO register (some are not initialized by TOS) */
                    139:        IoMem_WriteWord(0xff820e, 0);    /* Line offset */
                    140:        IoMem_WriteWord(0xff8264, 0);    /* Horizontal scroll */
1.1.1.8   root      141: 
1.1.1.12  root      142:        /* Init sync mode register */
                    143:        VIDEL_SyncMode_WriteByte();
1.1       root      144: }
                    145: 
1.1.1.6   root      146: /**
                    147:  * Save/Restore snapshot of local variables ('MemorySnapShot_Store' handles type)
                    148:  */
                    149: void VIDEL_MemorySnapShot_Capture(bool bSave)
                    150: {
                    151:        /* Save/Restore details */
                    152:        MemorySnapShot_Store(&videl, sizeof(videl));
                    153: }
                    154: 
                    155: /**
1.1.1.10  root      156:  * Monitor write access to Falcon color palette registers
1.1.1.6   root      157:  */
1.1.1.10  root      158: void VIDEL_FalconColorRegsWrite(void)
1.1       root      159: {
1.1.1.10  root      160:        uint32_t color = IoMem_ReadLong(IoAccessBaseAddress & ~3);
                    161:        color &= 0xfcfc00fc;    /* Unused bits have to be set to 0 */
                    162:        IoMem_WriteLong(IoAccessBaseAddress & ~3, color);
1.1.1.8   root      163:        videl.hostColorsSync = false;
1.1       root      164: }
                    165: 
1.1.1.6   root      166: /**
1.1.1.12  root      167:  * VIDEL_Monitor_WriteByte : Contains memory and monitor configuration.
1.1.1.8   root      168:  *                           This register is read only.
1.1.1.6   root      169:  */
                    170: void VIDEL_Monitor_WriteByte(void)
                    171: {
1.1.1.8   root      172:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8006 Monitor and memory conf write (Read only)\n");
1.1.1.6   root      173:        /* Restore hardware value */
1.1.1.8   root      174: 
1.1.1.6   root      175:        IoMem_WriteByte(0xff8006, videl.reg_ffff8006_save);
                    176: }
                    177: 
                    178: /**
1.1.1.12  root      179:  * VIDEL_SyncMode_WriteByte : Videl synchronization mode.
1.1.1.8   root      180:  *             $FFFF820A [R/W] _______0  .................................. SYNC-MODE
                    181:                                      ||
                    182:                                      |+--Synchronisation [ 0:internal / 1:external ]
                    183:                                      +---Vertical frequency [ Read-only bit ]
                    184:                                          [ Monochrome monitor:0 / Colour monitor:1 ]
                    185:  */
                    186: void VIDEL_SyncMode_WriteByte(void)
                    187: {
                    188:        Uint8 syncMode = IoMem_ReadByte(0xff820a);
                    189:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff820a Sync Mode write: 0x%02x\n", syncMode);
                    190: 
                    191:        if (videl.monitor_type == FALCON_MONITOR_MONO)
                    192:                syncMode &= 0xfd;
                    193:        else
                    194:                syncMode |= 0x2;
1.1.1.12  root      195: 
1.1.1.8   root      196:        IoMem_WriteByte(0xff820a, syncMode);
                    197: }
                    198: 
                    199: /**
                    200:  * Read video address counter and update ff8205/07/09
                    201:  */
                    202: void VIDEL_ScreenCounter_ReadByte(void)
                    203: {
1.1.1.13! root      204:        Uint32 addr = videl.videoRaster;
1.1.1.8   root      205:        IoMem[0xff8205] = ( addr >> 16 ) & 0xff;
                    206:        IoMem[0xff8207] = ( addr >> 8 ) & 0xff;
                    207:        IoMem[0xff8209] = addr & 0xff;
                    208: 
                    209:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8205/07/09 Sync Mode read: 0x%08x\n", addr);
                    210: }
                    211: 
                    212: /**
                    213:  * Write video address counter
                    214:  */
                    215: void VIDEL_ScreenCounter_WriteByte(void)
                    216: {
1.1.1.13! root      217:        Uint32 addr_new = videl.videoRaster;
        !           218:        Uint8 AddrByte = IoMem[ IoAccessCurrentAddress ];
1.1.1.8   root      219: 
                    220:        /* Compute the new video address with one modified byte */
                    221:        if ( IoAccessCurrentAddress == 0xff8205 )
                    222:                addr_new = ( addr_new & 0x00ffff ) | ( AddrByte << 16 );
                    223:        else if ( IoAccessCurrentAddress == 0xff8207 )
                    224:                addr_new = ( addr_new & 0xff00ff ) | ( AddrByte << 8 );
                    225:        else if ( IoAccessCurrentAddress == 0xff8209 )
                    226:                addr_new = ( addr_new & 0xffff00 ) | ( AddrByte );
                    227: 
1.1.1.13! root      228:        videl.videoRaster = addr_new;
        !           229:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8205/07/09 Sync Mode write: 0x%08x\n", addr_new);
        !           230: }
        !           231: 
        !           232: /**
        !           233:  * VIDEL_LineOffset_ReadWord: $FFFF820E [R/W] W _______876543210  Line Offset
        !           234:  * How many words are added to the end of display line, i.e. how many words are
        !           235:  * 'behind' the display.
        !           236:  */
        !           237: void VIDEL_LineOffset_ReadWord(void)
        !           238: {
        !           239:        /* Unused bits in the first byte are read as zero, so mask them */
        !           240:        IoMem[0xff820e] &= 0x01;
1.1.1.8   root      241: }
                    242: 
                    243: /**
                    244:  * VIDEL_LineOffset_WriteWord: $FFFF820E [R/W] W _______876543210  Line Offset
                    245:  * How many words are added to the end of display line, i.e. how many words are
                    246:  * 'behind' the display.
                    247:  */
                    248: void VIDEL_LineOffset_WriteWord(void)
                    249: {
1.1.1.9   root      250:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff820e Line Offset write: 0x%04x\n",
                    251:                  IoMem_ReadWord(0xff820e));
1.1.1.8   root      252: }
                    253: 
                    254: /**
                    255:  * VIDEL_Line_Width_WriteWord: $FFFF8210 [R/W] W ______9876543210 Line Width (VWRAP)
                    256:  * Length of display line in words.Or, how many words should be added to
                    257:  * vram counter after every display line.
                    258:  */
                    259: void VIDEL_Line_Width_WriteWord(void)
                    260: {
1.1.1.9   root      261:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8210 Line Width write: 0x%04x\n",
                    262:                  IoMem_ReadWord(0xff8210));
1.1.1.8   root      263: }
                    264: 
                    265: /**
1.1.1.6   root      266:  * Write to video address base high, med and low register (0xff8201/03/0d).
                    267:  * On Falcon, when a program writes to high or med registers, base low register
                    268:  * is reset to zero.
                    269:  */
                    270: void VIDEL_ScreenBase_WriteByte(void)
                    271: {
                    272:        if ((IoAccessCurrentAddress == 0xff8201) || (IoAccessCurrentAddress == 0xff8203)) {
                    273:                /* Reset screen base low register */
                    274:                IoMem[0xff820d] = 0;
                    275:        }
                    276: 
1.1.1.9   root      277:        LOG_TRACE(TRACE_VIDEL, "Videl : $%04x Screen base write: 0x%02x\t (screen: 0x%04x)\n",
                    278:                  IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress],
                    279:                  (IoMem[0xff8201]<<16) + (IoMem[0xff8203]<<8) + IoMem[0xff820d]);
1.1.1.6   root      280: }
                    281: 
                    282: /**
1.1.1.12  root      283:     VIDEL_ST_ShiftModeWriteByte :
1.1.1.6   root      284:        $FFFF8260 [R/W] B  ______10  ST Shift Mode
                    285:                                 ||
                    286:                                 ||                           others   vga
                    287:                                 ||                  $FF8210 $FF82C2 $FF82C2
                    288:                                 00--4BP/320 Pixels=> $0050   $0000   $0005
                    289:                                 01--2BP/640 Pixels=> $0050   $0004   $0009
                    290:                                 10--1BP/640 Pixels=> $0028   $0006   $0008
                    291:                                 11--???/320 Pixels=> $0050   $0000   $0000
                    292: 
                    293:        Writing to this register does the following things:
                    294:                - activate STE palette
                    295:                - sets line width ($ffff8210)
                    296:                - sets video mode in $ffff82c2 (double lines/interlace & cycles/pixel)
                    297:  */
                    298: void VIDEL_ST_ShiftModeWriteByte(void)
                    299: {
                    300:        Uint16 line_width, video_mode;
                    301:        Uint8 st_shiftMode;
                    302: 
                    303:        st_shiftMode = IoMem_ReadByte(0xff8260);
1.1.1.8   root      304:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8260 ST Shift Mode (STSHIFT) write: 0x%02x\n", st_shiftMode);
                    305: 
                    306:        /* Bits 2-7 are set to 0 */
1.1.1.12  root      307:        IoMem_WriteByte(0xff8260, st_shiftMode & 3);
1.1.1.6   root      308: 
                    309:        /* Activate STE palette */
                    310:        videl.bUseSTShifter = true;
                    311: 
                    312:        /*  Compute line width and video mode */
                    313:        switch (st_shiftMode & 0x3) {
                    314:                case 0: /* 4BP/320 Pixels */
                    315:                        line_width = 0x50;
                    316:                        /* half pixels + double lines vs. no scaling */
                    317:                        video_mode = videl.monitor_type == FALCON_MONITOR_VGA ? 0x5 : 0x0;
                    318:                        break;
                    319:                case 1: /* 2BP/640 Pixels */
                    320:                        line_width = 0x50;
                    321:                        /* quarter pixels + double lines vs. half pixels */
                    322:                        video_mode = videl.monitor_type == FALCON_MONITOR_VGA ? 0x9 : 0x4;
                    323:                        break;
                    324:                case 2: /* 1BP/640 Pixels */
                    325:                        line_width = 0x28;
                    326:                        if (videl.monitor_type == FALCON_MONITOR_MONO) {
                    327:                                video_mode = 0x0;
                    328:                                break;
                    329:                        }
                    330:                        /* quarter pixels vs. half pixels + interlace */
                    331:                        video_mode = videl.monitor_type == FALCON_MONITOR_VGA ? 0x8 : 0x6;
                    332:                        break;
                    333:                case 3: /* ???/320 Pixels */
1.1.1.8   root      334:                default:
1.1.1.6   root      335:                        line_width = 0x50;
                    336:                        video_mode = 0x0;
                    337:                        break;
                    338:        }
                    339: 
                    340:        /* Set line width ($FFFF8210) */
1.1.1.12  root      341:        IoMem_WriteWord(0xff8210, line_width);
                    342: 
1.1.1.6   root      343:        /* Set video mode ($FFFF82C2) */
1.1.1.12  root      344:        IoMem_WriteWord(0xff82c2, video_mode);
1.1.1.6   root      345: }
                    346: 
                    347: /**
1.1.1.8   root      348:     VIDEL_HorScroll64_WriteByte : Horizontal scroll register (0-15)
                    349:                $FFFF8264 [R/W] ________  ................................ H-SCROLL HI
                    350:                                    ||||  [ Shadow register for $FFFF8265 ]
                    351:                                    ++++--Pixel shift [ 0:normal / 1..15:Left shift ]
                    352:                                        [ Change in line-width NOT required ]
                    353:  */
                    354: void VIDEL_HorScroll64_WriteByte(void)
                    355: {
1.1.1.9   root      356:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8264 Horizontal scroll 64 write: 0x%02x\n",
                    357:                  IoMem_ReadByte(0xff8264));
1.1.1.8   root      358: }
                    359: 
                    360: /**
                    361:     VIDEL_HorScroll65_WriteByte : Horizontal scroll register (0-15)
                    362:                $FFFF8265 [R/W] ____3210  .................................H-SCROLL LO
                    363:                                    ||||
                    364:                                    ++++--Pixel [ 0:normal / 1..15:Left shift ]
                    365:                                        [ Change in line-width NOT required ]
                    366:  */
                    367: void VIDEL_HorScroll65_WriteByte(void)
                    368: {
1.1.1.9   root      369:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8265 Horizontal scroll 65 write: 0x%02x\n",
                    370:                  IoMem_ReadByte(0xff8265));
1.1.1.8   root      371: }
                    372: 
                    373: /**
                    374:     VIDEL_Falcon_ShiftMode_WriteWord :
1.1.1.6   root      375:        $FFFF8266 [R/W] W  _____A98_6543210  Falcon Shift Mode (SPSHIFT)
                    376:                                ||| |||||||
1.1.1.8   root      377:                                ||| |||++++- 0..15: Colourbank choice from 256-colour table in 16 colour multiples
                    378:                                ||| ||+----- 8 Bitplanes mode (256 Colors) [0:off / 1:on]
                    379:                                ||| |+------ Vertical Sync [0: internal / 1: external]
                    380:                                ||| +------- Horizontal Sync [0: internal / 1: external]
                    381:                                ||+--------- True-Color-Mode [0:off / 1:on]
                    382:                                |+---------- Overlay-Mode [0:off / 1:on]
                    383:                                +----------- 0: 2-Color-Mode [0:off / 1:on]
1.1.1.6   root      384: 
                    385:        Writing to this register does the following things:
                    386:                - activate Falcon palette
                    387:                - if you set Bits A/8/4 == 0, it selects 16-Color-Falcon-Mode (NOT the
                    388:                  same as ST LOW since Falcon palette is used!)
                    389:                - $8260 register is ignored, you don't need to write here anything
                    390: 
                    391:        Note: 4-Color-Mode isn't realisable with Falcon palette.
                    392:  */
1.1.1.8   root      393: void VIDEL_Falcon_ShiftMode_WriteWord(void)
1.1.1.6   root      394: {
1.1.1.9   root      395:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8266 Falcon Shift Mode (SPSHIFT) write: 0x%04x\n",
                    396:                  IoMem_ReadWord(0xff8266));
1.1.1.6   root      397: 
                    398:        videl.bUseSTShifter = false;
                    399: }
                    400: 
                    401: /**
                    402:  *  Write Horizontal Hold Counter (HHC)
                    403:  */
                    404: void VIDEL_HHC_WriteWord(void)
                    405: {
1.1.1.9   root      406:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8280 Horizontal Hold Counter (HHC) write: 0x%04x\n",
                    407:                  IoMem_ReadWord(0xff8280));
1.1.1.6   root      408: }
                    409: 
                    410: /**
                    411:  *  Write Horizontal Hold Timer (HHT)
                    412:  */
                    413: void VIDEL_HHT_WriteWord(void)
                    414: {
1.1.1.9   root      415:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8282 Horizontal Hold Timer (HHT) write: 0x%04x\n",
                    416:                  IoMem_ReadWord(0xff8282));
1.1.1.6   root      417: }
                    418: 
                    419: /**
                    420:  *  Write Horizontal Border Begin (HBB)
                    421:  */
                    422: void VIDEL_HBB_WriteWord(void)
                    423: {
1.1.1.9   root      424:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8284 Horizontal Border Begin (HBB) write: 0x%04x\n",
                    425:                  IoMem_ReadWord(0xff8284));
1.1.1.6   root      426: }
                    427: 
                    428: /**
                    429:  *  Write Horizontal Border End (HBE)
                    430:  */
                    431: void VIDEL_HBE_WriteWord(void)
                    432: {
1.1.1.9   root      433:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8286 Horizontal Border End (HBE) write: 0x%04x\n",
                    434:                  IoMem_ReadWord(0xff8286));
1.1.1.6   root      435: }
                    436: 
                    437: /**
                    438:  *  Write Horizontal Display Begin (HDB)
1.1.1.8   root      439:        $FFFF8288 [R/W] W ______9876543210  Horizontal Display Begin (HDB)
                    440:                                |
                    441:                                +---------- Display will start in [0: 1st halfline / 1: 2nd halfline]
1.1.1.6   root      442:  */
                    443: void VIDEL_HDB_WriteWord(void)
                    444: {
1.1.1.9   root      445:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8288 Horizontal Display Begin (HDB) write: 0x%04x\n",
                    446:                  IoMem_ReadWord(0xff8288));
1.1.1.6   root      447: }
                    448: 
                    449: /**
                    450:  *  Write Horizontal Display End (HDE)
                    451:  */
                    452: void VIDEL_HDE_WriteWord(void)
                    453: {
1.1.1.9   root      454:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff828a Horizontal Display End (HDE) write: 0x%04x\n",
                    455:                  IoMem_ReadWord(0xff828a));
1.1.1.6   root      456: }
                    457: 
                    458: /**
                    459:  *  Write Horizontal SS (HSS)
                    460:  */
                    461: void VIDEL_HSS_WriteWord(void)
                    462: {
1.1.1.9   root      463:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff828c Horizontal SS (HSS) write: 0x%04x\n",
                    464:                  IoMem_ReadWord(0xff828c));
1.1.1.6   root      465: }
                    466: 
                    467: /**
                    468:  *  Write Horizontal FS (HFS)
                    469:  */
                    470: void VIDEL_HFS_WriteWord(void)
                    471: {
1.1.1.9   root      472:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff828e Horizontal FS (HFS) write: 0x%04x\n",
                    473:                  IoMem_ReadWord(0xff828e));
1.1.1.6   root      474: }
                    475: 
                    476: /**
                    477:  *  Write Horizontal EE (HEE)
                    478:  */
                    479: void VIDEL_HEE_WriteWord(void)
                    480: {
1.1.1.9   root      481:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff8290 Horizontal EE (HEE) write: 0x%04x\n",
                    482:                  IoMem_ReadWord(0xff8290));
1.1.1.6   root      483: }
                    484: 
                    485: /**
                    486:  *  Write Vertical Frequency Counter (VFC)
                    487:  */
                    488: void VIDEL_VFC_ReadWord(void)
                    489: {
1.1.1.13! root      490:        IoMem_WriteWord(0xff82a0, videl.vertFreqCounter);
        !           491:        videl.vertFreqCounter++;
        !           492:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a0 Vertical Frequency Counter (VFC) read: 0x%04x\n", videl.vertFreqCounter);
1.1.1.6   root      493: }
                    494: 
                    495: /**
                    496:  *  Write Vertical Frequency Timer (VFT)
                    497:  */
                    498: void VIDEL_VFT_WriteWord(void)
                    499: {
1.1.1.9   root      500:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a2 Vertical Frequency Timer (VFT) write: 0x%04x\n",
                    501:                  IoMem_ReadWord(0xff82a2));
1.1.1.6   root      502: }
                    503: 
                    504: /**
                    505:  *  Write Vertical Border Begin (VBB)
                    506:  */
                    507: void VIDEL_VBB_WriteWord(void)
                    508: {
1.1.1.9   root      509:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a4 Vertical Border Begin (VBB) write: 0x%04x\n",
                    510:                  IoMem_ReadWord(0xff82a4));
1.1.1.6   root      511: }
                    512: 
                    513: /**
                    514:  *  Write Vertical Border End (VBE)
                    515:  */
                    516: void VIDEL_VBE_WriteWord(void)
                    517: {
1.1.1.9   root      518:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a6 Vertical Border End (VBE) write: 0x%04x\n",
                    519:                  IoMem_ReadWord(0xff82a6));
1.1.1.6   root      520: }
                    521: 
                    522: /**
                    523:  *  Write Vertical Display Begin (VDB)
                    524:  */
                    525: void VIDEL_VDB_WriteWord(void)
1.1       root      526: {
1.1.1.9   root      527:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff82a8 Vertical Display Begin (VDB) write: 0x%04x\n",
                    528:                  IoMem_ReadWord(0xff82a8));
1.1       root      529: }
                    530: 
1.1.1.6   root      531: /**
                    532:  *  Write Vertical Display End (VDE)
                    533:  */
                    534: void VIDEL_VDE_WriteWord(void)
                    535: {
1.1.1.9   root      536:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff82aa Vertical Display End (VDE) write: 0x%04x\n",
                    537:                  IoMem_ReadWord(0xff82aa));
1.1.1.6   root      538: }
                    539: 
                    540: /**
                    541:  *  Write Vertical SS (VSS)
                    542:  */
                    543: void VIDEL_VSS_WriteWord(void)
                    544: {
1.1.1.9   root      545:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff82ac Vertical SS (VSS) write: 0x%04x\n",
                    546:                  IoMem_ReadWord(0xff82ac));
1.1.1.6   root      547: }
                    548: 
                    549: /**
                    550:  *  Write Video Control (VCO)
                    551:  */
                    552: void VIDEL_VCO_WriteWord(void)
                    553: {
1.1.1.9   root      554:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff82c0 Video control (VCO) write: 0x%04x\n",
                    555:                  IoMem_ReadWord(0xff82c0));
1.1.1.6   root      556: }
                    557: 
                    558: /**
                    559:  *  Write Video Mode (VDM)
                    560:  */
                    561: void VIDEL_VMD_WriteWord(void)
                    562: {
1.1.1.9   root      563:        LOG_TRACE(TRACE_VIDEL, "Videl : $ff82c2 Video Mode (VDM) write: 0x%04x\n",
                    564:                  IoMem_ReadWord(0xff82c2));
1.1.1.6   root      565: }
                    566: 
                    567: 
1.1.1.8   root      568: /**
                    569:  *  VIDEL_getVideoramAddress: returns the video RAM address.
                    570:  *  On Falcon, video address must be a multiple of four in bitplane modes.
                    571:  */
                    572: static Uint32 VIDEL_getVideoramAddress(void)
1.1       root      573: {
1.1.1.8   root      574:        Uint32 videoBase;
1.1.1.12  root      575: 
1.1.1.8   root      576:        videoBase  = (Uint32) IoMem_ReadByte(0xff8201) << 16;
                    577:        videoBase |= (Uint32) IoMem_ReadByte(0xff8203) << 8;
                    578:        videoBase |= IoMem_ReadByte(0xff820d) & ~3;
1.1.1.12  root      579: 
1.1.1.8   root      580:        return videoBase;
1.1       root      581: }
                    582: 
1.1.1.13! root      583: /**
        !           584:  * Reset appropriate registers on VBL etc
        !           585:  */
        !           586: void VIDEL_RestartVideoCounter(void)
        !           587: {
        !           588:        videl.videoRaster = VIDEL_getVideoramAddress();
        !           589:        /* counter for VFC register $ff82a0 */
        !           590:        videl.vertFreqCounter = 0;
        !           591: }
        !           592: 
        !           593: /**
        !           594:  * Increment appropriate registers on HBL
        !           595:  */
        !           596: void VIDEL_VideoRasterHBL(void)
        !           597: {
        !           598:        int lineoffset = IoMem_ReadWord(0xff820e) & 0x01ff; /* 9 bits */
        !           599:        int linewidth = IoMem_ReadWord(0xff8210) & 0x03ff;  /* 10 bits */
        !           600: 
        !           601:        videl.videoRaster += linewidth + lineoffset;
        !           602: 
        !           603:        /* TODO: VFC is incremented every half line, here, we increment it every line */
        !           604:        videl.vertFreqCounter++;
        !           605: }
        !           606: 
        !           607: 
1.1.1.8   root      608: static Uint16 VIDEL_getScreenBpp(void)
1.1       root      609: {
1.1.1.8   root      610:        Uint16 f_shift = IoMem_ReadWord(0xff8266);
                    611:        Uint16 bits_per_pixel;
                    612:        Uint8  st_shift = IoMem_ReadByte(0xff8260);
                    613: 
1.1       root      614:        /* to get bpp, we must examine f_shift and st_shift.
1.1.1.12  root      615:         * f_shift is valid if any of bits no. 10, 8 or 4 is set.
1.1.1.8   root      616:         * Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
1.1       root      617:         * if bit 10 set then bit 8 and bit 4 don't care...
                    618:         * If all these bits are 0 and ST shifter is written
                    619:         * after Falcon one, get display depth from st_shift
                    620:         * (as for ST and STE)
                    621:         */
                    622:        if (f_shift & 0x400)            /* Falcon: 2 colors */
                    623:                bits_per_pixel = 1;
                    624:        else if (f_shift & 0x100)       /* Falcon: hicolor */
                    625:                bits_per_pixel = 16;
                    626:        else if (f_shift & 0x010)       /* Falcon: 8 bitplanes */
                    627:                bits_per_pixel = 8;
1.1.1.6   root      628:        else if (!videl.bUseSTShifter)  /* Falcon: 4 bitplanes */
1.1       root      629:                bits_per_pixel = 4;
                    630:        else if (st_shift == 0)
                    631:                bits_per_pixel = 4;
                    632:        else if (st_shift == 0x01)
                    633:                bits_per_pixel = 2;
                    634:        else /* if (st_shift == 0x02) */
                    635:                bits_per_pixel = 1;
                    636: 
1.1.1.8   root      637: /*     LOG_TRACE(TRACE_VIDEL, "Videl works in %d bpp, f_shift=%04x, st_shift=%d", bits_per_pixel, f_shift, st_shift); */
1.1       root      638: 
                    639:        return bits_per_pixel;
                    640: }
                    641: 
1.1.1.8   root      642: /**
                    643:  *  VIDEL_getScreenWidth : returns the visible X resolution
                    644:  *     left border + graphic area + right border
                    645:  *     left border  : hdb - hbe-offset
                    646:  *     right border : hbb - hde-offset
1.1.1.12  root      647:  *     Graphics display : starts at cycle HDB and ends at cycle HDE.
1.1.1.8   root      648:  */
1.1       root      649: static int VIDEL_getScreenWidth(void)
                    650: {
1.1.1.9   root      651:        Uint16 hbb, hbe, hdb, hde, vdm, hht;
                    652:        Uint16 cycPerPixel, divider;
                    653:        Sint16 hdb_offset, hde_offset;
                    654:        Sint16 leftBorder, rightBorder;
1.1.1.8   root      655:        Uint16 bpp = VIDEL_getScreenBpp();
                    656: 
                    657:        /* X Size of the Display area */
                    658:        videl.XSize = (IoMem_ReadWord(0xff8210) & 0x03ff) * 16 / bpp;
                    659: 
1.1.1.13! root      660:        /* Sanity check - don't use unsupported texture sizes for SDL2:
        !           661:         *   http://answers.unity3d.com/questions/563094/mobile-max-texture-size.html
        !           662:         * (largest currently known real Videl width is ~1600)
        !           663:         */
        !           664:        while (videl.XSize > 2048)
        !           665:                videl.XSize /= 2;
        !           666: 
1.1.1.8   root      667:        /* If the user disabled the borders display from the gui, we suppress them */
                    668:        if (ConfigureParams.Screen.bAllowOverscan == 0) {
                    669:                videl.leftBorderSize = 0;
                    670:                videl.rightBorderSize = 0;
                    671:                return videl.XSize;
                    672:        }
                    673: 
                    674:        /* According to Aura and Animal Mine doc about Videl, if a monochrome monitor is connected,
                    675:         * HDB and HDE have no significance and no border is displayed.
                    676:         */
                    677:        if (videl.monitor_type == FALCON_MONITOR_MONO) {
                    678:                videl.leftBorderSize = 0;
                    679:                videl.rightBorderSize = 0;
                    680:                return videl.XSize;
                    681:        }
                    682: 
1.1.1.9   root      683:        hbb = IoMem_ReadWord(0xff8284) & 0x01ff;
                    684:        hbe = IoMem_ReadWord(0xff8286) & 0x01ff;
                    685:        hdb = IoMem_ReadWord(0xff8288) & 0x01ff;
                    686:        hde = IoMem_ReadWord(0xff828a) & 0x01ff;
                    687:        vdm = IoMem_ReadWord(0xff82c2) & 0xc;
                    688:        hht = IoMem_ReadWord(0xff8282) & 0x1ff;
1.1.1.8   root      689: 
                    690:        /* Compute cycles per pixel */
                    691:        if (vdm == 0)
                    692:                cycPerPixel = 4;
                    693:        else if (vdm == 4)
                    694:                cycPerPixel = 2;
                    695:        else
                    696:                cycPerPixel = 1;
                    697: 
                    698:        /* Compute the divider */
                    699:        if (videl.monitor_type == FALCON_MONITOR_VGA) {
                    700:                if (cycPerPixel == 4)
                    701:                        divider = 4;
                    702:                else
                    703:                        divider = 2;
                    704:        }
                    705:        else if (videl.bUseSTShifter == true) {
                    706:                divider = 16;
                    707:        }
                    708:        else {
                    709:                divider = cycPerPixel;
                    710:        }
                    711: 
                    712:        /* Compute hdb_offset and hde_offset */
                    713:        if (videl.bUseSTShifter == false) {
                    714:                if (bpp < 16) {
                    715:                        /* falcon mode bpp */
                    716:                        hdb_offset = ((64+(128/bpp + 16 + 2) * cycPerPixel) / divider ) + 1;
                    717:                        hde_offset = ((128/bpp + 2) * cycPerPixel) / divider;
                    718:                }
                    719:                else {
                    720:                        /* falcon mode true color */
                    721:                        hdb_offset = ((64 + 16 * cycPerPixel) / divider ) + 1;
                    722:                        hde_offset = 0;
                    723:                }
                    724:        }
                    725:        else {
                    726:                /* ST bitplan mode */
                    727:                hdb_offset = ((128+(128/bpp + 2) * cycPerPixel) / divider ) + 1;
                    728:                hde_offset = ((128/bpp + 2) * cycPerPixel) / divider;
                    729:        }
                    730: 
                    731:        LOG_TRACE(TRACE_VIDEL, "hdb_offset=%04x,    hde_offset=%04x\n", hdb_offset, hde_offset);
                    732: 
                    733:        /* Compute left border size in cycles */
                    734:        if (IoMem_ReadWord(0xff8288) & 0x0200)
                    735:                leftBorder = hdb - hbe + hdb_offset - hht - 2;
                    736:        else
                    737:                leftBorder = hdb - hbe + hdb_offset;
                    738: 
                    739:        /* Compute right border size in cycles */
                    740:        rightBorder = hbb - hde_offset - hde;
                    741: 
                    742:        videl.leftBorderSize = leftBorder / cycPerPixel;
                    743:        videl.rightBorderSize = rightBorder / cycPerPixel;
                    744:        LOG_TRACE(TRACE_VIDEL, "left border size=%04x,    right border size=%04x\n", videl.leftBorderSize, videl.rightBorderSize);
                    745: 
                    746:        if (videl.leftBorderSize < 0) {
                    747: //             fprintf(stderr, "BORDER LEFT < 0   %d\n", videl.leftBorderSize);
                    748:                videl.leftBorderSize = 0;
                    749:        }
                    750:        if (videl.rightBorderSize < 0) {
                    751: //             fprintf(stderr, "BORDER RIGHT < 0   %d\n", videl.rightBorderSize);
                    752:                videl.rightBorderSize = 0;
                    753:        }
                    754: 
                    755:        return videl.leftBorderSize + videl.XSize + videl.rightBorderSize;
1.1       root      756: }
                    757: 
1.1.1.8   root      758: /**
                    759:  *  VIDEL_getScreenHeight : returns the visible Y resolution
                    760:  *     upper border + graphic area + lower border
                    761:  *     upper border : vdb - vbe
                    762:  *     lower border : vbb - vde
1.1.1.12  root      763:  *     Graphics display : starts at line VDB and ends at line VDE.
1.1.1.8   root      764:  *     If interlace mode off unit of VC-registers is half lines, else lines.
                    765:  */
1.1       root      766: static int VIDEL_getScreenHeight(void)
                    767: {
1.1.1.8   root      768:        Uint16 vbb = IoMem_ReadWord(0xff82a4) & 0x07ff;
1.1.1.12  root      769:        Uint16 vbe = IoMem_ReadWord(0xff82a6) & 0x07ff;
1.1.1.8   root      770:        Uint16 vdb = IoMem_ReadWord(0xff82a8) & 0x07ff;
                    771:        Uint16 vde = IoMem_ReadWord(0xff82aa) & 0x07ff;
                    772:        Uint16 vmode = IoMem_ReadWord(0xff82c2);
                    773: 
                    774:        /* According to Aura and Animal Mine doc about Videl, if a monochrome monitor is connected,
                    775:         * VDB and VDE have no significance and no border is displayed.
1.1       root      776:         */
1.1.1.8   root      777:        if (videl.monitor_type == FALCON_MONITOR_MONO) {
                    778:                videl.upperBorderSize = 0;
                    779:                videl.lowerBorderSize = 0;
                    780:        }
                    781:        else {
                    782:                /* We must take the positive value only, as a program like AceTracker starts the */
                    783:                /* graphical area 1 line before the end of the upper border */
                    784:                videl.upperBorderSize = vdb - vbe > 0 ? vdb - vbe : 0;
                    785:                videl.lowerBorderSize = vbb - vde > 0 ? vbb - vde : 0;
                    786:        }
1.1       root      787: 
1.1.1.8   root      788:        /* Y Size of the Display area */
1.1.1.9   root      789:        if (vde >= vdb) {
                    790:                videl.YSize = vde - vdb;
                    791:        }
                    792:        else {
                    793:                LOG_TRACE(TRACE_VIDEL, "WARNING: vde=0x%x is less than vdb=0x%x\n",
                    794:                          vde, vdb);
                    795:        }
1.1.1.8   root      796: 
                    797:        /* If the user disabled the borders display from the gui, we suppress them */
                    798:        if (ConfigureParams.Screen.bAllowOverscan == 0) {
                    799:                videl.upperBorderSize = 0;
                    800:                videl.lowerBorderSize = 0;
                    801:        }
                    802: 
                    803:        if (!(vmode & 0x02)){           /* interlace */
                    804:                videl.YSize >>= 1;
                    805:                videl.upperBorderSize >>= 1;
                    806:                videl.lowerBorderSize >>= 1;
                    807:        }
1.1.1.12  root      808: 
1.1.1.8   root      809:        if (vmode & 0x01) {             /* double */
                    810:                videl.YSize >>= 1;
                    811:                videl.upperBorderSize >>= 1;
                    812:                videl.lowerBorderSize >>= 1;
                    813:        }
1.1.1.9   root      814: 
1.1.1.8   root      815:        return videl.upperBorderSize + videl.YSize + videl.lowerBorderSize;
1.1       root      816: }
                    817: 
                    818: 
1.1.1.12  root      819: /**
                    820:  * Map the correct colortable into the correct pixel format
1.1       root      821:  */
1.1.1.12  root      822: void VIDEL_UpdateColors(void)
1.1       root      823: {
1.1.1.8   root      824:        int i, r, g, b, colors = 1 << videl.save_scrBpp;
1.1       root      825: 
1.1.1.12  root      826:        if (videl.hostColorsSync)
                    827:                return;
                    828: 
1.1.1.8   root      829: #define F_COLORS(i) IoMem_ReadByte(VIDEL_COLOR_REGS_BEGIN + (i))
                    830: #define STE_COLORS(i)  IoMem_ReadByte(0xff8240 + (i))
1.1       root      831: 
1.1.1.12  root      832:        /* True color mode ? */
                    833:        if (videl.save_scrBpp > 8) {
                    834:                /* Videl color 0 ($ffff9800) must be taken into account as it is the border color in true color mode */
                    835:                r = F_COLORS(0) & 0xfc;
                    836:                r |= r>>6;
                    837:                g = F_COLORS(0 + 1) & 0xfc;
                    838:                g |= g>>6;
                    839:                b = F_COLORS(0 + 3) & 0xfc;
                    840:                b |= b>>6;
                    841:                Screen_SetPaletteColor(0, r,g,b);
                    842:                return;
                    843:        }
                    844: 
1.1.1.6   root      845:        if (!videl.bUseSTShifter) {
1.1       root      846:                for (i = 0; i < colors; i++) {
                    847:                        int offset = i << 2;
                    848:                        r = F_COLORS(offset) & 0xfc;
                    849:                        r |= r>>6;
                    850:                        g = F_COLORS(offset + 1) & 0xfc;
                    851:                        g |= g>>6;
                    852:                        b = F_COLORS(offset + 3) & 0xfc;
                    853:                        b |= b>>6;
1.1.1.12  root      854:                        Screen_SetPaletteColor(i, r,g,b);
1.1       root      855:                }
                    856:        } else {
                    857:                for (i = 0; i < colors; i++) {
                    858:                        int offset = i << 1;
                    859:                        r = STE_COLORS(offset) & 0x0f;
                    860:                        r = ((r & 7)<<1)|(r>>3);
                    861:                        r |= r<<4;
                    862:                        g = (STE_COLORS(offset + 1)>>4) & 0x0f;
                    863:                        g = ((g & 7)<<1)|(g>>3);
                    864:                        g |= g<<4;
                    865:                        b = STE_COLORS(offset + 1) & 0x0f;
                    866:                        b = ((b & 7)<<1)|(b>>3);
                    867:                        b |= b<<4;
1.1.1.12  root      868:                        Screen_SetPaletteColor(i, r,g,b);
1.1       root      869:                }
                    870:        }
                    871: 
1.1.1.8   root      872:        videl.hostColorsSync = true;
1.1       root      873: }
                    874: 
                    875: 
1.1.1.13! root      876: void Videl_ScreenModeChanged(bool bForceChange)
1.1       root      877: {
1.1.1.13! root      878:        int bpp;
        !           879: 
        !           880:        if (ConfigureParams.Screen.nForceBpp)
        !           881:        {
        !           882:                bpp = ConfigureParams.Screen.nForceBpp;
        !           883:        }
        !           884:        else if (Avi_AreWeRecording())
        !           885:        {
        !           886:                /* Avoid changing the bpp if we are recording */
        !           887:                bpp = sdlscrn->format->BitsPerPixel;
        !           888:        }
        !           889:        else
        !           890:        {
        !           891:                /* Using SDL's 16 bpp conversion function is a bit faster */
        !           892:                bpp = (videl.save_scrBpp == 16) ? 16 : 0;
        !           893:        }
        !           894: 
        !           895:        LOG_TRACE(TRACE_VIDEL, "Videl : video mode change to %dx%d@%d\n",
        !           896:                  videl.save_scrWidth, videl.save_scrHeight, videl.save_scrBpp);
1.1.1.12  root      897: 
                    898:        Screen_SetGenConvSize(videl.save_scrWidth, videl.save_scrHeight,
                    899:                              bpp, bForceChange);
1.1       root      900: }
                    901: 
                    902: 
1.1.1.2   root      903: bool VIDEL_renderScreen(void)
1.1       root      904: {
1.1.1.8   root      905:        /* Atari screen infos */
1.1       root      906:        int vw   = VIDEL_getScreenWidth();
                    907:        int vh   = VIDEL_getScreenHeight();
                    908:        int vbpp = VIDEL_getScreenBpp();
1.1.1.8   root      909: 
                    910:        int lineoffset = IoMem_ReadWord(0xff820e) & 0x01ff; /* 9 bits */
                    911:        int linewidth = IoMem_ReadWord(0xff8210) & 0x03ff;  /* 10 bits */
1.1.1.12  root      912:        int hscrolloffset = IoMem_ReadByte(0xff8265) & 0x0f;
1.1.1.9   root      913:        int nextline;
1.1.1.8   root      914: 
1.1.1.6   root      915:        bool change = false;
1.1       root      916: 
1.1.1.13! root      917:        Uint32 videoBase = VIDEL_getVideoramAddress();
1.1.1.9   root      918: 
1.1.1.8   root      919:        if (vw > 0 && vw != videl.save_scrWidth) {
                    920:                LOG_TRACE(TRACE_VIDEL, "Videl : width change from %d to %d\n", videl.save_scrWidth, vw);
                    921:                videl.save_scrWidth = vw;
1.1.1.6   root      922:                change = true;
1.1       root      923:        }
1.1.1.8   root      924:        if (vh > 0 && vh != videl.save_scrHeight) {
                    925:                LOG_TRACE(TRACE_VIDEL, "Videl : height change from %d to %d\n", videl.save_scrHeight, vh);
                    926:                videl.save_scrHeight = vh;
1.1.1.6   root      927:                change = true;
1.1       root      928:        }
1.1.1.8   root      929:        if (vbpp != videl.save_scrBpp) {
                    930:                LOG_TRACE(TRACE_VIDEL, "Videl : bpp change from %d to %d\n", videl.save_scrBpp, vbpp);
                    931:                videl.save_scrBpp = vbpp;
1.1.1.6   root      932:                change = true;
                    933:        }
                    934:        if (change) {
1.1.1.13! root      935:                Videl_ScreenModeChanged(false);
1.1       root      936:        }
                    937: 
1.1.1.12  root      938:        if (vw < 32 || vh < 32) {
                    939:                LOG_TRACE(TRACE_VIDEL, "Videl : %dx%d screen size, not drawing\n", vw, vh);
                    940:                return false;
                    941:        }
                    942: 
                    943:        if (!Screen_Lock())
1.1.1.2   root      944:                return false;
1.1       root      945: 
1.1.1.12  root      946:        /*
                    947:           I think this implementation is naive:
1.1.1.8   root      948:           indeed, I suspect that we should instead skip lineoffset
                    949:           words each time we have read "more" than linewidth words
                    950:           (possibly "more" because of the number of bit planes).
                    951:           Moreover, the 1 bit plane mode is particular;
                    952:           while doing some experiments on my Falcon, it seems to
                    953:           behave like the 4 bit planes mode.
                    954:           At last, we have also to take into account the 4 bits register
                    955:           located at the word $ffff8264 (bit offset). This register makes
                    956:           the semantics of the lineoffset register change a little.
                    957:           int bitoffset = IoMem_ReadWord(0xff8264) & 0x000f;
                    958:           The meaning of this register in True Color mode is not clear
                    959:           for me at the moment (and my experiments on the Falcon don't help
                    960:           me).
                    961:        */
1.1.1.9   root      962:        nextline = linewidth + lineoffset;
1.1.1.8   root      963: 
1.1.1.12  root      964:        VIDEL_UpdateColors();
1.1.1.8   root      965: 
1.1.1.13! root      966:        Screen_GenConvert(&STRam[videoBase], videl.XSize, videl.YSize,
1.1.1.12  root      967:                          videl.save_scrBpp, nextline, hscrolloffset,
                    968:                          videl.leftBorderSize, videl.rightBorderSize,
                    969:                          videl.upperBorderSize, videl.lowerBorderSize);
1.1       root      970: 
1.1.1.12  root      971:        Screen_UnLock();
                    972:        Screen_GenConvUpdate(Statusbar_Update(sdlscrn, false), false);
1.1.1.2   root      973: 
                    974:        return true;
1.1       root      975: }
                    976: 
                    977: 
1.1.1.4   root      978: /**
1.1.1.10  root      979:  * Write to videl ST palette registers (0xff8240-0xff825e)
                    980:  *
                    981:  * Note that there's a special "strange" case when writing only to the upper byte
                    982:  * of the color reg (instead of writing 16 bits at once with .W/.L).
                    983:  * In that case, the byte written to address x is automatically written
                    984:  * to address x+1 too (but we shouldn't copy x in x+1 after masking x ; we apply the mask at the end)
                    985:  * Similarly, when writing a byte to address x+1, it's also written to address x
                    986:  * So :        move.w #0,$ff8240       -> color 0 is now $000
                    987:  *     move.b #7,$ff8240       -> color 0 is now $707 !
                    988:  *     move.b #$55,$ff8241     -> color 0 is now $555 !
                    989:  *     move.b #$71,$ff8240     -> color 0 is now $171 (bytes are first copied, then masked)
                    990:  */
1.1.1.11  root      991: static void Videl_ColorReg_WriteWord(void)
1.1.1.10  root      992: {
                    993:        Uint16 col;
                    994:        Uint32 addr = IoAccessCurrentAddress;
                    995: 
                    996:        videl.hostColorsSync = false;
                    997: 
                    998:        if (bUseHighRes || bUseVDIRes)               /* Don't store if hi-res or VDI resolution */
                    999:                return;
                   1000: 
1.1.1.12  root     1001:        /* Handle special case when writing only to the lower or
                   1002:         * upper byte of the color reg: copy written byte also
                   1003:         * to the other byte before masking the color value.
                   1004:         */
                   1005:        if (nIoMemAccessSize == SIZE_BYTE)
                   1006:                col = (IoMem_ReadByte(addr) << 8) + IoMem_ReadByte(addr);
1.1.1.10  root     1007:        /* Usual case, writing a word or a long (2 words) */
1.1.1.12  root     1008:        else
1.1.1.10  root     1009:                col = IoMem_ReadWord(addr);
                   1010: 
                   1011:        col &= 0xfff;                           /* Mask off to 4096 palette */
                   1012: 
                   1013:        addr &= 0xfffffffe;                     /* Ensure addr is even to store the 16 bit color */
                   1014: 
                   1015:        IoMem_WriteWord(addr, col);
                   1016: }
                   1017: 
                   1018: /*
                   1019:  * [NP] TODO : due to how .L accesses are handled in ioMem.c, we can't call directly
                   1020:  * Video_ColorReg_WriteWord from ioMemTabFalcon.c, we must use an intermediate
                   1021:  * function, else .L accesses will not change 2 .W color regs, but only one.
                   1022:  * This should be changed in ioMem.c to do 2 separate .W accesses, as would do a real 68000
                   1023:  */
                   1024: 
                   1025: void Videl_Color0_WriteWord(void)
                   1026: {
                   1027:        Videl_ColorReg_WriteWord();
                   1028: }
                   1029: 
                   1030: void Videl_Color1_WriteWord(void)
                   1031: {
                   1032:        Videl_ColorReg_WriteWord();
                   1033: }
                   1034: 
                   1035: void Videl_Color2_WriteWord(void)
                   1036: {
                   1037:        Videl_ColorReg_WriteWord();
                   1038: }
                   1039: 
                   1040: void Videl_Color3_WriteWord(void)
                   1041: {
                   1042:        Videl_ColorReg_WriteWord();
                   1043: }
                   1044: 
                   1045: void Videl_Color4_WriteWord(void)
                   1046: {
                   1047:        Videl_ColorReg_WriteWord();
                   1048: }
                   1049: 
                   1050: void Videl_Color5_WriteWord(void)
                   1051: {
                   1052:        Videl_ColorReg_WriteWord();
                   1053: }
                   1054: 
                   1055: void Videl_Color6_WriteWord(void)
                   1056: {
                   1057:        Videl_ColorReg_WriteWord();
                   1058: }
                   1059: 
                   1060: void Videl_Color7_WriteWord(void)
                   1061: {
                   1062:        Videl_ColorReg_WriteWord();
                   1063: }
                   1064: 
                   1065: void Videl_Color8_WriteWord(void)
                   1066: {
                   1067:        Videl_ColorReg_WriteWord();
                   1068: }
                   1069: 
                   1070: void Videl_Color9_WriteWord(void)
                   1071: {
                   1072:        Videl_ColorReg_WriteWord();
                   1073: }
                   1074: 
                   1075: void Videl_Color10_WriteWord(void)
                   1076: {
                   1077:        Videl_ColorReg_WriteWord();
                   1078: }
                   1079: 
                   1080: void Videl_Color11_WriteWord(void)
                   1081: {
                   1082:        Videl_ColorReg_WriteWord();
                   1083: }
                   1084: 
                   1085: void Videl_Color12_WriteWord(void)
                   1086: {
                   1087:        Videl_ColorReg_WriteWord();
                   1088: }
                   1089: 
                   1090: void Videl_Color13_WriteWord(void)
                   1091: {
                   1092:        Videl_ColorReg_WriteWord();
                   1093: }
                   1094: 
                   1095: void Videl_Color14_WriteWord(void)
                   1096: {
                   1097:        Videl_ColorReg_WriteWord();
                   1098: }
                   1099: 
                   1100: void Videl_Color15_WriteWord(void)
                   1101: {
                   1102:        Videl_ColorReg_WriteWord();
                   1103: }
                   1104: 
                   1105: /**
                   1106:  * display Videl registers values (for debugger info command)
                   1107:  */
1.1.1.11  root     1108: void Videl_Info(FILE *fp, Uint32 dummy)
1.1.1.10  root     1109: {
                   1110:        if (ConfigureParams.System.nMachineType != MACHINE_FALCON) {
1.1.1.11  root     1111:                fprintf(fp, "Not Falcon - no Videl!\n");
1.1.1.10  root     1112:                return;
                   1113:        }
                   1114: 
1.1.1.11  root     1115:        fprintf(fp, "$FF8006.b : monitor type                     : %02x\n", IoMem_ReadByte(0xff8006));
                   1116:        fprintf(fp, "$FF8201.b : Video Base Hi                    : %02x\n", IoMem_ReadByte(0xff8201));
                   1117:        fprintf(fp, "$FF8203.b : Video Base Mi                    : %02x\n", IoMem_ReadByte(0xff8203));
                   1118:        fprintf(fp, "$FF8205.b : Video Count Hi                   : %02x\n", IoMem_ReadByte(0xff8205));
                   1119:        fprintf(fp, "$FF8207.b : Video Count Mi                   : %02x\n", IoMem_ReadByte(0xff8207));
                   1120:        fprintf(fp, "$FF8209.b : Video Count Lo                   : %02x\n", IoMem_ReadByte(0xff8209));
                   1121:        fprintf(fp, "$FF820A.b : Sync mode                        : %02x\n", IoMem_ReadByte(0xff820a));
                   1122:        fprintf(fp, "$FF820D.b : Video Base Lo                    : %02x\n", IoMem_ReadByte(0xff820d));
                   1123:        fprintf(fp, "$FF820E.w : offset to next line              : %04x\n", IoMem_ReadWord(0xff820e));
                   1124:        fprintf(fp, "$FF8210.w : VWRAP - line width               : %04x\n", IoMem_ReadWord(0xff8210));
                   1125:        fprintf(fp, "$FF8260.b : ST shift mode                    : %02x\n", IoMem_ReadByte(0xff8260));
                   1126:        fprintf(fp, "$FF8264.w : Horizontal scroll register       : %04x\n", IoMem_ReadWord(0xff8264));
                   1127:        fprintf(fp, "$FF8266.w : Falcon shift mode                : %04x\n", IoMem_ReadWord(0xff8266));
                   1128:        fprintf(fp, "\n");
                   1129:        fprintf(fp, "$FF8280.w : HHC - Horizontal Hold Counter    : %04x\n", IoMem_ReadWord(0xff8280));
                   1130:        fprintf(fp, "$FF8282.w : HHT - Horizontal Hold Timer      : %04x\n", IoMem_ReadWord(0xff8282));
                   1131:        fprintf(fp, "$FF8284.w : HBB - Horizontal Border Begin    : %04x\n", IoMem_ReadWord(0xff8284));
                   1132:        fprintf(fp, "$FF8286.w : HBE - Horizontal Border End      : %04x\n", IoMem_ReadWord(0xff8286));
                   1133:        fprintf(fp, "$FF8288.w : HDB - Horizontal Display Begin   : %04x\n", IoMem_ReadWord(0xff8288));
                   1134:        fprintf(fp, "$FF828A.w : HDE - Horizontal Display End     : %04x\n", IoMem_ReadWord(0xff828a));
                   1135:        fprintf(fp, "$FF828C.w : HSS - Horizontal SS              : %04x\n", IoMem_ReadWord(0xff828c));
                   1136:        fprintf(fp, "$FF828E.w : HFS - Horizontal FS              : %04x\n", IoMem_ReadWord(0xff828e));
                   1137:        fprintf(fp, "$FF8290.w : HEE - Horizontal EE              : %04x\n", IoMem_ReadWord(0xff8290));
                   1138:        fprintf(fp, "\n");
                   1139:        fprintf(fp, "$FF82A0.w : VFC - Vertical Frequency Counter : %04x\n", IoMem_ReadWord(0xff82a0));
                   1140:        fprintf(fp, "$FF82A2.w : VFT - Vertical Frequency Timer   : %04x\n", IoMem_ReadWord(0xff82a2));
                   1141:        fprintf(fp, "$FF82A4.w : VBB - Vertical Border Begin      : %04x\n", IoMem_ReadWord(0xff82a4));
                   1142:        fprintf(fp, "$FF82A6.w : VBE - Vertical Border End        : %04x\n", IoMem_ReadWord(0xff82a6));
                   1143:        fprintf(fp, "$FF82A8.w : VDB - Vertical Display Begin     : %04x\n", IoMem_ReadWord(0xff82a8));
                   1144:        fprintf(fp, "$FF82AA.w : VDE - Vertical Display End       : %04x\n", IoMem_ReadWord(0xff82aa));
                   1145:        fprintf(fp, "$FF82AC.w : VSS - Vertical SS                : %04x\n", IoMem_ReadWord(0xff82ac));
                   1146:        fprintf(fp, "\n");
                   1147:        fprintf(fp, "$FF82C0.w : VCO - Video control              : %04x\n", IoMem_ReadWord(0xff82c0));
                   1148:        fprintf(fp, "$FF82C2.w : VMD - Video mode                 : %04x\n", IoMem_ReadWord(0xff82c2));
                   1149:        fprintf(fp, "\n-------------------------\n");
1.1.1.10  root     1150: 
1.1.1.11  root     1151:        fprintf(fp, "Video base  : %08x\n",
1.1.1.12  root     1152:                (IoMem_ReadByte(0xff8201)<<16) +
                   1153:                (IoMem_ReadByte(0xff8203)<<8)  +
1.1.1.10  root     1154:                 IoMem_ReadByte(0xff820d));
1.1.1.11  root     1155:        fprintf(fp, "Video count : %08x\n",
1.1.1.12  root     1156:                (IoMem_ReadByte(0xff8205)<<16) +
                   1157:                (IoMem_ReadByte(0xff8207)<<8)  +
1.1.1.10  root     1158:                 IoMem_ReadByte(0xff8209));
                   1159: }

unix.superglobalmegacorp.com

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