Annotation of hatari/src/spec512.c, revision 1.1.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.