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

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

unix.superglobalmegacorp.com

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