| 
    
       #include "atx_eclaire.h"
 
     | 
  
  
     | 
    
       #include "atx.h"
 
     | 
  
  
     | 
    
       #include "regs.h"
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       struct SimpleFile * gAtxFile;
 
     | 
  
  
     | 
    
       u16 last_angle_returned; // extern so we can display it on the screen
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       extern unsigned char atari_sector_buffer[256];
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       void longbyteswap(u32 * x);
 
     | 
  
  
     | 
    
       void byteswap(u16 * x);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       void byteSwapAtxFileHeader(struct atxFileHeader * header)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
           // only swap the used entries
 
     | 
  
  
     | 
    
           byteswap(&header->version);
 
     | 
  
  
     | 
    
           byteswap(&header->minVersion);
 
     | 
  
  
     | 
    
           longbyteswap(&header->startData);
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       void byteSwapAtxTrackHeader(struct atxTrackHeader * header)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
           // only swap the used entries
 
     | 
  
  
     | 
    
           longbyteswap(&header->size); // used
 
     | 
  
  
     | 
    
           byteswap(&header->sectorCount); // used
 
     | 
  
  
     | 
    
           longbyteswap(&header->headerSize); // used
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       void byteSwapAtxSectorListHeader(struct atxSectorListHeader * header)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
       	longbyteswap(&header->next);
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       void byteSwapAtxSectorHeader(struct atxSectorHeader * header)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
       	byteswap(&header->timev);
 
     | 
  
  
     | 
    
       	longbyteswap(&header->data);
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       void byteSwapAtxTrackChunk(struct atxTrackChunk *header)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
       	byteswap(&header->data);
 
     | 
  
  
     | 
    
       	longbyteswap(&header->size);
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       void waitForAngularPosition(u16 pos)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
           int where = getCurrentHeadPosition();
 
     | 
  
  
     | 
    
           int diff = pos-where;
 
     | 
  
  
     | 
    
           if (diff < 0)
 
     | 
  
  
     | 
    
           {
 
     | 
  
  
     | 
    
       	    diff = 26042+diff;
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
           *zpu_pause = diff<<3;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       /*    // if the position is less than the current timer, we need to wait for a rollover 
 
     | 
  
  
     | 
    
           // to occur
 
     | 
  
  
     | 
    
           if (pos < TCNT1 / 2) {
 
     | 
  
  
     | 
    
               TIFR1 |= _BV(OCF1A);
 
     | 
  
  
     | 
    
               while (!(TIFR1 & _BV(OCF1A)));
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
           // wait for the timer to reach the target position
 
     | 
  
  
     | 
    
           while (TCNT1 / 2 < pos);*/
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       u16 getCurrentHeadPosition() {
 
     | 
  
  
     | 
    
           // TCNT1 is a variable driven by an Atmel timer that ticks every 4 microseconds. A full 
 
     | 
  
  
     | 
    
           // rotation of the disk is represented in an ATX file by an angular positional value 
 
     | 
  
  
     | 
    
           // between 1-26042 (or 8 microseconds based on 288 rpms). So, TCNT1 / 2 always gives the 
 
     | 
  
  
     | 
    
           // current angular position of the drive head on the track any given time assuming the 
 
     | 
  
  
     | 
    
           // disk is spinning continously.
 
     | 
  
  
     | 
    
           //return TCNT1 / 2;
 
     | 
  
  
     | 
    
           int res = *zpu_timer2;
 
     | 
  
  
     | 
    
           res = (res >> 3)+1;
 
     | 
  
  
     | 
    
           return res;
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       int faccess_offset(int type, int offset, int bytes)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
       	int read = 0;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
           	*zpu_timer2_threshold = 208335;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	file_seek(gAtxFile,offset);
 
     | 
  
  
     | 
    
       	file_read(gAtxFile,&atari_sector_buffer[0],bytes,&read);
 
     | 
  
  
     | 
    
       	return bytes==read;
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       int rand()
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
       	return *zpu_rand;
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       extern void byteswap(WORD * inw);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       void longbyteswap(u32 * inl)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
       #ifndef LITTLE_ENDIAN
 
     | 
  
  
     | 
    
       	unsigned char * in = (unsigned char *)inl;
 
     | 
  
  
     | 
    
       	unsigned char temp0  = in[0];
 
     | 
  
  
     | 
    
       	unsigned char temp1 = in[1];
 
     | 
  
  
     | 
    
       	in[0] = in[3];
 
     | 
  
  
     | 
    
       	in[1] = in[2];
 
     | 
  
  
     | 
    
       	in[2] = temp1;
 
     | 
  
  
     | 
    
       	in[3] = temp0;
 
     | 
  
  
     | 
    
       #endif
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     |