Annotation of hatari/src/spec512.c, revision 1.1

1.1     ! root        1: /*
        !             2:   Hatari
        !             3: 
        !             4:   Handle storing of writes to ST palette using clock-cycle counts. We can use this to accurately any form
        !             5:   of Spectrum512 style images - even down to the way the screen colours change on decompression routines in menus!
        !             6: 
        !             7:   As the 68000 has a 4-clock cycle increment we can only change palette every 4 cycles. This means that on one
        !             8:   scanline(512 cycles) we have just 512/4=128 places where palette writes can take place. We keep track of
        !             9:   this in a table(storing on each scanline and colour writes and the cycles on the scanline where they happen).
        !            10:   When we draw the screen we simply keep a cycle-count on the line and check this with our table and update
        !            11:   the 16-colour palette with each change. As the table is already ordered this makes things very simple. Speed
        !            12:   is a problem, though, as the palette can change once every 4 pixels - that's a lot of processing.
        !            13: */
        !            14: 
        !            15: #include "main.h"
        !            16: #include "debug.h"
        !            17: #include "decode.h"
        !            18: #include "int.h"
        !            19: #include "screen.h"
        !            20: #include "spec512.h"
        !            21: #include "video.h"
        !            22: 
        !            23: CYCLEPALETTE CyclePalettes[(SCANLINES_PER_FRAME+1)*MAX_CYCLEPALETTES_PERLINE];  // 314k; 1024-bytes per line
        !            24: CYCLEPALETTE *pCyclePalette;
        !            25: int nCyclePalettes[(SCANLINES_PER_FRAME+1)];                  // Number of entries in above table for each scanline
        !            26: int nPalettesAccess[(SCANLINES_PER_FRAME+1)];                 // Number of times accessed palette register 'x' in this scan line
        !            27: unsigned short int CycleColour;
        !            28: int CycleColourIndex;
        !            29: int nScanLine, ScanLineCycleCount;
        !            30: BOOL bIsSpec512Display;
        !            31: 
        !            32: //-----------------------------------------------------------------------
        !            33: /*
        !            34:   Return TRUE if this frame is a Spectrum 512 style image(MUST be low res/non-mix)
        !            35: */
        !            36: BOOL Spec512_IsImage(void)
        !            37: {
        !            38:   // Normal Low res screen?
        !            39:   if ( (STRes==ST_LOW_RES) && (bIsSpec512Display) )
        !            40:     return(TRUE);
        !            41: 
        !            42:   return(FALSE);
        !            43: }
        !            44: 
        !            45: //-----------------------------------------------------------------------
        !            46: /*
        !            47:   We store every palette access in a table to perform Spectrum 512 colour effects
        !            48:   This is cleared on each VBL
        !            49: */
        !            50: void Spec512_StartVBL(void)
        !            51: {
        !            52:   // Clear number of cycle palettes on each frame
        !            53:   memset(nCyclePalettes,0x0,(SCANLINES_PER_FRAME+1)*sizeof(int));
        !            54:   // Clear number of times accessed on entry in palette(used to check if is true Spectrum 512 image)
        !            55:   memset(nPalettesAccess,0x0,(SCANLINES_PER_FRAME+1)*sizeof(int));  
        !            56:   // Set as not Spectrum 512 displayed image
        !            57:   bIsSpec512Display = FALSE;
        !            58: }
        !            59: 
        !            60: //-----------------------------------------------------------------------
        !            61: /*
        !            62:   Store 'bx' colour into 'CyclePalettes[]' according to cycles into frame
        !            63:   Address is passed in 'ecx', eg 0xff8240
        !            64: */
        !            65: void Spec512_StoreCyclePalette_Execute(void)
        !            66: {
        !            67:   CYCLEPALETTE *pCyclePalette;
        !            68:   int FrameCycles,ScanLine;
        !            69: 
        !            70:   // Find number of cycles into frame
        !            71:   FrameCycles = Int_FindFrameCycles();
        !            72: 
        !            73:   // Find scan line we are currently on and get index into cycle-palette table
        !            74:   ScanLine = (FrameCycles/CYCLES_PER_LINE);
        !            75:   pCyclePalette = &CyclePalettes[ (ScanLine*MAX_CYCLEPALETTES_PERLINE) + nCyclePalettes[ScanLine] ];
        !            76:   // Do we have a previous entry at the same cycles? If so, 68000 have used a 'move.l' instruction so stagger writes
        !            77:   if (nCyclePalettes[ScanLine]>0) {
        !            78:     if ((pCyclePalette-1)->LineCycles==(FrameCycles&511))
        !            79:       FrameCycles += 4;              // Colours are staggered by [4,20] when writing a long word!
        !            80:   }
        !            81: 
        !            82:   // Store palette access
        !            83:   pCyclePalette->LineCycles = FrameCycles&511;    // Cycles into scanline
        !            84:   pCyclePalette->Colour = CycleColour&0x777;      // Store ST colour RGB
        !            85:   pCyclePalette->Index = CycleColourIndex;        // And Index (0...15)
        !            86:   // Increment count(this can never overflow as you cannot write to the palette more than 'MAX_CYCLEPALETTES_PERLINE' times per scanline)
        !            87:   nCyclePalettes[ScanLine]++;
        !            88: 
        !            89:   // Check if program wrote to certain palette entry multiple times on a single scan-line
        !            90:   // If we did then we must be using a Spectrum512 image or some kind of colour cycling...
        !            91:   nPalettesAccess[ScanLine]++;
        !            92:   if (nPalettesAccess[ScanLine]>=32)
        !            93:     bIsSpec512Display = TRUE;
        !            94: }
        !            95: 
        !            96: void Spec512_StoreCyclePalette(unsigned short col, unsigned long addr)
        !            97: {
        !            98:   CycleColour = col;
        !            99:   CycleColourIndex = (addr-0xff8240)>>1;
        !           100:   Spec512_StoreCyclePalette_Execute();    /* Store it in table for screen conversion */
        !           101: }
        !           102: 
        !           103: //-----------------------------------------------------------------------
        !           104: /*
        !           105:   Begin palette calculation for Spectrum 512 style images, 
        !           106: */
        !           107: void Spec512_StartFrame(void)
        !           108: {
        !           109:   int i;
        !           110: 
        !           111:   // Set so screen gets full-update when returns from Spectrum 512 display
        !           112:   Screen_SetFullUpdate();
        !           113: 
        !           114:   // Set terminators on each line, so when scan during conversion we know when to stop
        !           115:   for(i=0; i<(SCANLINES_PER_FRAME+1); i++) {
        !           116:     pCyclePalette = &CyclePalettes[ (i*MAX_CYCLEPALETTES_PERLINE) + nCyclePalettes[i] ];
        !           117:     pCyclePalette->LineCycles = -1;          // Term
        !           118:   }
        !           119: 
        !           120:   // Copy first line palette, kept in 'HBLPalettes' and store to 'STRGBPalette'
        !           121:   for(i=0; i<16; i++)
        !           122:     STRGBPalette[i] = ST2RGB[HBLPalettes[i]&0x777];
        !           123: 
        !           124:   // Ready for first call to 'Spec512_ScanLine'
        !           125:   nScanLine = 0;
        !           126: 
        !           127:   // Skip to first line(where start to draw screen from)
        !           128:   for (i=0; i<(STScreenStartHorizLine+(nStartHBL-OVERSCAN_TOP)); i++)
        !           129:     Spec512_ScanWholeLine();
        !           130: }
        !           131: 
        !           132: //-----------------------------------------------------------------------
        !           133: /*
        !           134:   Scan whole line and build up palette - need to do this so when get to screen line we have
        !           135:   the correct 16 colours set
        !           136: */
        !           137: void Spec512_ScanWholeLine(void)
        !           138: {
        !           139:   // Store pointer to line of palette cycle writes
        !           140:   pCyclePalette = &CyclePalettes[nScanLine*MAX_CYCLEPALETTES_PERLINE];
        !           141:   // Ready for next scan line
        !           142:   nScanLine++;
        !           143: 
        !           144:   // Update palette entries until we reach start of displayed screen
        !           145:   ScanLineCycleCount = 0;
        !           146:   Spec512_EndScanLine();                // Read whole line of palettes and update 'STRGBPalette'
        !           147: }
        !           148: 
        !           149: //-----------------------------------------------------------------------
        !           150: /*
        !           151:   Build up palette for this scan line and store in 'ScanLinePalettes'
        !           152: */
        !           153: void Spec512_StartScanLine(void)
        !           154: {
        !           155:   int i;
        !           156: 
        !           157:   // Store pointer to line of palette cycle writes
        !           158:   pCyclePalette = &CyclePalettes[nScanLine*MAX_CYCLEPALETTES_PERLINE];
        !           159:   // Ready for next scan line
        !           160:   nScanLine++;
        !           161: 
        !           162:   // Update palette entries until we reach start of displayed screen
        !           163:   ScanLineCycleCount = 0;
        !           164:   for(i=0; i<((SCREEN_START_CYCLE-8)/4); i++)      // This '8' is as we've already added in the 'move' instruction timing
        !           165:     Spec512_UpdatePaletteSpan();                   // Update palette for this 4-cycle period
        !           166:   // And skip for left border is not using overscan display to user
        !           167:   for (i=0; i<(STScreenLeftSkipBytes/2); i++)      // Eg, 16 bytes = 32 pixels or 8 palette periods
        !           168:     Spec512_UpdatePaletteSpan();
        !           169: }
        !           170: 
        !           171: //-----------------------------------------------------------------------
        !           172: /*
        !           173:   Run to end of scan line looking up palettes so 'STRGBPalette' is up-to-date
        !           174: */
        !           175: void Spec512_EndScanLine(void)
        !           176: {
        !           177:   // Continue to reads palette until complete so have correct version for next line
        !           178:   while(ScanLineCycleCount<CYCLES_PER_LINE)
        !           179:     Spec512_UpdatePaletteSpan();
        !           180: }
        !           181: 
        !           182: //-----------------------------------------------------------------------
        !           183: /*
        !           184:   Update palette for 4-pixels span, storing to 'STRGBPalette'
        !           185: */
        !           186: void Spec512_UpdatePaletteSpan(void)
        !           187: {
        !           188: /* FIXME!! */
        !           189: /*
        !           190:   __asm {
        !           191:     push  eax
        !           192:     push  ebx
        !           193: 
        !           194:     mov    ebx,[pCyclePalette]
        !           195:     mov    eax,[ebx]        // pCyclePalette->LineCycles
        !           196:     cmp    eax,[ScanLineCycleCount]    // == ScanLineCycleCount?
        !           197:     jne    no_cycle_match
        !           198: 
        !           199:     // Need to update palette with new entry
        !           200:     mov    eax,4[ebx]        // pCyclePalette->Colour
        !           201:     and    eax,0x777        // Colour&0x777
        !           202:     mov    eax,ST2RGB[eax*4]      // Convert to PC's RGB
        !           203:     movzx  ebx,WORD PTR 6[ebx]        // pCyclePalette->Index
        !           204:     shl    ebx,2          // as 'long' index
        !           205:     add    ebx,OFFSET [STRGBPalette]
        !           206:     mov    [ebx],eax        // Store as long's for speed
        !           207: 
        !           208:     add    [pCyclePalette],8      // sizeof(CYCLEPALETTE)
        !           209: 
        !           210: no_cycle_match:
        !           211:     add    [ScanLineCycleCount],4      // Next 4 cycles
        !           212: 
        !           213:     pop    ebx
        !           214:     pop    eax
        !           215:     ret
        !           216:   }
        !           217: */
        !           218: }

unix.superglobalmegacorp.com

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