Project

General

Profile

46 markw
#include "atari_drive_emulator.h"
49 markw
#include "fileutils.h"
46 markw
#include "uart.h"
283 markw
#include "regs.h"
46 markw
#include "pause.h"
#include "simplefile.h"
89 markw
#include "hexdump.h"
46 markw
803 markw
#include "atx_eclaire.h"
#include "atx.h"

#include "printf.h"
318 markw
//#include <stdio.h>
46 markw
#include "integer.h"

49 markw
extern int debug_pos; // ARG!
283 markw
extern unsigned char volatile * baseaddr;
49 markw
46 markw
#define send_ACK() USART_Transmit_Byte('A');
#define send_NACK() USART_Transmit_Byte('N');
#define send_CMPL() USART_Transmit_Byte('C');
#define send_ERR() USART_Transmit_Byte('E');

/* BiboDos needs at least 50us delay before ACK */
#define DELAY_T2_MIN wait_us(100);

/* the QMEG OS needs at least 300usec delay between ACK and complete */
#define DELAY_T5_MIN wait_us(300);

/* QMEG OS 3 needs a delay of 150usec between complete and data */
#define DELAY_T3_PERIPH wait_us(150);

#define speedslow 0x28
803 markw
#define speedfast (get_turbo_div(get_turbo_drive()))
348 markw
46 markw
#define XEX_SECTOR_SIZE 128

#define MAX_DRIVES 4

struct SimpleFile * drives[MAX_DRIVES];
62 markw
unsigned char drive_info[MAX_DRIVES];
enum DriveInfo {DI_XD=0,DI_SD=1,DI_MD=2,DI_DD=3,DI_BITS=3,DI_RO=4};
46 markw
318 markw
//#ifdef SOCKIT
//double when()
//{
// struct timeval tv;
// gettimeofday(&tv,0);
// double now = tv.tv_sec;
// now += tv.tv_usec/1e6;
// return now;
//}
//#endif

46 markw
struct ATRHeader
{
u16 wMagic;
u16 wPars;
u16 wSecSize;
u08 btParsHigh;
u32 dwCRC;
49 markw
u32 dwUNUSED;
u08 btFlags;
46 markw
} __attribute__((packed));
struct ATRHeader atr_header;
49 markw
int offset;
803 markw
char custom_loader;
49 markw
int xex_size;

803 markw
char speed;
char opendrive;
46 markw
803 markw
unsigned char atari_sector_status;
46 markw
unsigned char atari_sector_buffer[256];

49 markw
unsigned char get_checksum(unsigned char* buffer, int len);
46 markw
#define TWOBYTESTOWORD(ptr,val) (*((u08*)(ptr)) = val&0xff);(*(1+(u08*)(ptr)) = (val>>8)&0xff);

void processCommand();
803 markw
void USART_Send_cmpl_and_atari_sector_buffer_and_check_sum(unsigned short len, int success);
46 markw
void clearAtariSectorBuffer()
{
int i=256;
while (--i)
atari_sector_buffer[i] = 0;
}

uint8_t boot_xex_loader[179] = {
0x72,0x02,0x5f,0x07,0xf8,0x07,0xa9,0x00,0x8d,0x04,0x03,0x8d,0x44,0x02,0xa9,0x07,
0x8d,0x05,0x03,0xa9,0x70,0x8d,0x0a,0x03,0xa9,0x01,0x8d,0x0b,0x03,0x85,0x09,0x60,
0x7d,0x8a,0x48,0x20,0x53,0xe4,0x88,0xd0,0xfa,0x68,0xaa,0x8c,0x8e,0x07,0xad,0x7d,
0x07,0xee,0x8e,0x07,0x60,0xa9,0x93,0x8d,0xe2,0x02,0xa9,0x07,0x8d,0xe3,0x02,0xa2,
0x02,0x20,0xda,0x07,0x95,0x43,0x20,0xda,0x07,0x95,0x44,0x35,0x43,0xc9,0xff,0xf0,
0xf0,0xca,0xca,0x10,0xec,0x30,0x06,0xe6,0x45,0xd0,0x02,0xe6,0x46,0x20,0xda,0x07,
0xa2,0x01,0x81,0x44,0xb5,0x45,0xd5,0x43,0xd0,0xed,0xca,0x10,0xf7,0x20,0xd2,0x07,
0x4c,0x94,0x07,0xa9,0x03,0x8d,0x0f,0xd2,0x6c,0xe2,0x02,0xad,0x8e,0x07,0xcd,0x7f,
0x07,0xd0,0xab,0xee,0x0a,0x03,0xd0,0x03,0xee,0x0b,0x03,0xad,0x7d,0x07,0x0d,0x7e,
0x07,0xd0,0x8e,0x20,0xd2,0x07,0x6c,0xe0,0x02,0x20,0xda,0x07,0x8d,0xe0,0x02,0x20,
0xda,0x07,0x8d,0xe1,0x02,0x2d,0xe0,0x02,0xc9,0xff,0xf0,0xed,0xa9,0x00,0x8d,0x8e,
0x07,0xf0,0x82 };
// relokacni tabulka neni potreba, meni se vsechny hodnoty 0x07
// (melo by byt PRESNE 20 vyskytu! pokud je jich vic, pak bacha!!!)

void byteswap(WORD * inw)
{
#ifndef LITTLE_ENDIAN
unsigned char * in = (unsigned char *)inw;
unsigned char temp = in[0];
in[0] = in[1];
in[1] = temp;
#endif
}

struct command
{
u08 deviceId;
u08 command;
u08 aux1;
u08 aux2;
u08 chksum;
} __attribute__((packed));
374 markw
static void switch_speed()
{
803 markw
int tmp = *zpu_uart_divisor;
*zpu_uart_divisor = tmp-1;
374 markw
}

46 markw
void getCommand(struct command * cmd)
{
int expchk;
195 markw
int i;
374 markw
unsigned char cmdstat;
803 markw
int prob;
prob = 0;
283 markw
while (1)
{
803 markw
for (i=0;i!=5;++i)
374 markw
{
803 markw
u32 data = USART_Receive_Byte(); // Timeout?
*zpu_uart_debug = i;
*zpu_uart_debug = 1&(data>>8);
*zpu_uart_debug = data&0xff;
if (USART_Framing_Error() | ((data>>8)!=(i+1)))
{
prob = 1;
break;
}
((unsigned char *)cmd)[i] = data&0xff;
//*zpu_uart_debug = (data&0xff);
//*zpu_uart_debug3 = i;
374 markw
}
318 markw
283 markw
803 markw
if (prob) // command malformed, try again!
{
prob = 0;

*zpu_uart_debug2 = 0xf0;
// error
374 markw
continue;
}
46 markw
803 markw
*zpu_uart_debug = 0xba;
USART_Receive_Byte();
*zpu_uart_debug = 0xda;

*zpu_uart_debug = *zpu_uart_divisor;

374 markw
atari_sector_buffer[0] = cmd->deviceId;
atari_sector_buffer[1] = cmd->command;
atari_sector_buffer[2] = cmd->aux1;
atari_sector_buffer[3] = cmd->aux2;
expchk = get_checksum(&atari_sector_buffer[0],4);
283 markw
803 markw
//*zpu_uart_debug2 = expchk;
//*zpu_uart_debug2 = cmd->chksum;

374 markw
if (expchk==cmd->chksum) {
803 markw
*zpu_uart_debug2 = 0x44;
374 markw
// got a command frame
803 markw
//
switch_speed();
374 markw
break;
} else {
803 markw
*zpu_uart_debug2 = 0xff;
374 markw
// just an invalid checksum, switch speed anyways
46 markw
}
}

DELAY_T2_MIN;
}

// Called whenever file changed
void set_drive_status(int driveNumber, struct SimpleFile * file)
{
int read = 0;
int xfd = 0;
803 markw
int atx = 0;
89 markw
unsigned char info = 0;
46 markw
drives[driveNumber] = 0;
62 markw
drive_info[driveNumber] = 0;
46 markw
803 markw
*zpu_uart_debug2 = 0x11;

46 markw
if (!file) return;

803 markw
*zpu_uart_debug2 = 0x12;

52 markw
//printf("WTF:%d %x\n",driveNumber, file);

46 markw
// Read header
read = 0;
file_seek(file,0);
803 markw
*zpu_uart_debug2 = 0x23;
46 markw
file_read(file,(unsigned char *)&atr_header, 16, &read);
803 markw
*zpu_uart_debug2 = 0x33;
46 markw
if (read!=16)
{
52 markw
//printf("Could not read header\n");
46 markw
return; //while(1);
}
803 markw
*zpu_uart_debug2 = 0x13;

46 markw
byteswap(&atr_header.wMagic);
byteswap(&atr_header.wPars);
byteswap(&atr_header.wSecSize);
/*printf("\nHeader:");
printf("%d",atr_header.wMagic);
plotnext(toatarichar(' '));
printf("%d",atr_header.wPars);
plotnext(toatarichar(' '));
printf("%d",atr_header.wSecSize);
plotnext(toatarichar(' '));
printf("%d",atr_header.btParsHigh);
plotnext(toatarichar(' '));
printf("%d",atr_header.dwCRC);
printf("\n");
*/

803 markw
custom_loader = 0;
49 markw
xfd = compare_ext(file_name(file),"XFD");
803 markw
atx = compare_ext(file_name(file),"ATX");
46 markw
803 markw
atari_sector_status = 0xff;

46 markw
if (xfd == 1)
{
52 markw
//printf("XFD ");
46 markw
// build a fake atr header
offset = 0;
atr_header.wMagic = 0x296;
atr_header.wPars = file_size(file)/16;
atr_header.wSecSize = 0x80;
62 markw
atr_header.btFlags |= file_readonly(file);
46 markw
}
868 markw
#ifdef ATX
803 markw
else if (atx == 1)
{
int i;
unsigned char j;
int k;
int orig;
u16 sectorSize;
offset = -256;
custom_loader = 2;
atr_header.wMagic = 0xffff;
xex_size = file_size(file);
atr_header.wPars = xex_size/16;
atr_header.wSecSize = XEX_SECTOR_SIZE;
atr_header.btFlags = 1;

gAtxFile = file;
sectorSize = loadAtxFile(0);
}
868 markw
#endif
46 markw
else if (atr_header.wMagic == 0xFFFF) // XEX
{
int i;
52 markw
//printf("XEX ");
46 markw
offset = -256;
803 markw
custom_loader = 1;
46 markw
atr_header.wMagic = 0xffff;
xex_size = file_size(file);
atr_header.wPars = xex_size/16;
atr_header.wSecSize = XEX_SECTOR_SIZE;
49 markw
atr_header.btFlags = 1;
46 markw
}
else if (atr_header.wMagic == 0x296) // ATR
{
52 markw
//printf("ATR ");
46 markw
offset = 16;
62 markw
atr_header.btFlags |= file_readonly(file);
46 markw
}
else
{
52 markw
//printf("Unknown file type");
46 markw
return;
}

803 markw
*zpu_uart_debug2 = 0x14;

62 markw
if (atr_header.btFlags&1)
{
info |= DI_RO;
}

46 markw
if (atr_header.wSecSize == 0x80)
{
62 markw
if (atr_header.wPars>(720*128/16))
info |= DI_MD;
46 markw
else
62 markw
info |= DI_SD;
46 markw
}
else if (atr_header.wSecSize == 0x100)
{
62 markw
info |= DI_DD;
46 markw
}
else if (atr_header.wSecSize < 0x100)
{
62 markw
info |= DI_XD;
46 markw
}
else
{
52 markw
//printf("BAD sector size");
46 markw
return;
}
52 markw
//printf("%d",atr_header.wPars);
//printf("0\n");
803 markw
//
*zpu_uart_debug2 = 0x15;
46 markw
drives[driveNumber] = file;
62 markw
drive_info[driveNumber] = info;
52 markw
//printf("appears valid\n");
46 markw
}

69 markw
struct SimpleFile * get_drive_status(int driveNumber)
{
return drives[driveNumber];
}

46 markw
void init_drive_emulator()
{
int i;

opendrive = -1;
speed = speedslow;
USART_Init(speed+6);
for (i=0; i!=MAX_DRIVES; ++i)
{
drives[i] = 0;
}
}

void run_drive_emulator()
{
while (1)
{
processCommand();
}
}

/////////////////////////

803 markw
struct sio_action
{
int bytes;
int success;
int speed;
int respond;
};

typedef void (*CommandHandler)(struct command, struct SimpleFile *, struct sio_action *);
CommandHandler getCommandHandler(struct command);

46 markw
void processCommand()
{
struct command command;

getCommand(&command);

52 markw
if (command.deviceId >= 0x31 && command.deviceId <= 0x34)
46 markw
{
int drive = 0;
struct SimpleFile * file = 0;

52 markw
drive = (command.deviceId&0xf) -1;
// printf("Drive:");
// printf("%x %d",command.deviceId,drive);
46 markw
if (drive<0 || !drives[drive])
{
//send_NACK();
//wait_us(100); // Wait for transmission to complete - Pokey bug, gets stuck active...

52 markw
//printf("Drive not present:%d %x", drive, drives[drive]);
803 markw
//
//
*zpu_uart_debug2 = 0x16;
46 markw
return;
}

803 markw
*zpu_uart_debug3 = command.command;

46 markw
file = drives[opendrive];

803 markw
CommandHandler handleCommand = getCommandHandler(command);
DELAY_T2_MIN;
if (handleCommand)
46 markw
{
803 markw
struct sio_action action;
action.bytes = 0;
action.success = 1;
action.speed = -1;
action.respond = 1;

46 markw
send_ACK();
clearAtariSectorBuffer();
803 markw

if (drive!=opendrive)
{
*zpu_uart_debug3 = drive;
if (drive<MAX_DRIVES && drive>=0)
{
opendrive = drive;
set_drive_status(drive, drives[drive]);
//printf("HERE!:%d\n",drive);
}
}

handleCommand(command, drives[drive], &action); //TODO -> this should respond with more stuff and we handle result in a common way...

if (action.respond)
USART_Send_cmpl_and_atari_sector_buffer_and_check_sum(action.bytes, action.success);
if (action.speed>=0)
USART_Init(action.speed); // Wait until fifo is empty - then set speed!
}
else
{
send_NACK();
}
}
}

void handleSpeed(struct command command, struct SimpleFile * file, struct sio_action * action)
{
//printf("Speed:");
int sector = ((int)command.aux2)<<8;
atari_sector_buffer[0] = speedfast;
//hexdump_pure(atari_sector_buffer,1);
action->bytes = 1;

46 markw
if (sector == 0)
{
speed = speedfast;
52 markw
//printf("SPDF");
//printf("%d",speed);
46 markw
}
else
{
speed = speedslow;
52 markw
//printf("SPDS");
//printf("%d",speed);
46 markw
}

803 markw
action->speed = speed +6;
}
49 markw
803 markw
void handleFormat(struct command command,struct SimpleFile * file, struct sio_action * action)
{
if (atr_header.btFlags&1)
{
// fail, write protected
action->success = 0;
}
else
{
int i;
int pos = offset;
49 markw
803 markw
// fill image with zeros
int written = 0;
for (i=0; i!=(atr_header.wPars>>3); ++i)
{
file_seek(file,pos);
file_write(file,&atari_sector_buffer[0], 128, &written);
pos+=128;
}
file_write_flush();

// return done
atari_sector_buffer[0] = 0xff;
atari_sector_buffer[1] = 0xff;
for(i=2;i!=atr_header.wSecSize; ++i)
{
atari_sector_buffer[i] = 0;
}

action->bytes=atr_header.wSecSize;
}
}

void handleReadPercomBlock(struct command command, struct SimpleFile * file, struct sio_action * action)
{
unsigned totalSectors = (atr_header.wPars<<4)/atr_header.wSecSize;
//printf("Stat:");

atari_sector_buffer[0] = 1;
atari_sector_buffer[1] = 11;
atari_sector_buffer[2] = totalSectors>>8;
atari_sector_buffer[3] = totalSectors&0xff;
atari_sector_buffer[5] = (atr_header.wSecSize==256) ? 4 : 0;
atari_sector_buffer[6] = atr_header.wSecSize>>8;
atari_sector_buffer[7] = atr_header.wSecSize&0xff;
atari_sector_buffer[8] = 0x0ff;
//hexdump_pure(atari_sector_buffer,12); // Somehow with this...
49 markw
803 markw
action->bytes = 12;
//printf("%d",atari_sector_buffer[0]); // and this... The wrong checksum is sent!!
//printf(":done\n");
}
49 markw
803 markw
void handleGetStatus(struct command command, struct SimpleFile * file, struct sio_action * action)
{
unsigned char status;
//printf("Stat:");
49 markw
803 markw
status = 0x10; // Motor on;
if (atr_header.btFlags&1)
{
status |= 0x08; // write protected; // no write support yet...
}
if (atr_header.wSecSize == 0x80) // normal sector size
{
if (atr_header.wPars>(720*128/16))
{
status |= 0x80; // medium density - or a strange one...
}
}
else
{
status |= 0x20; // 256 byte sectors
}
atari_sector_buffer[0] = status;
atari_sector_buffer[1] = atari_sector_status;
atari_sector_buffer[2] = 0xe0;
atari_sector_buffer[3] = 0x0;
//hexdump_pure(atari_sector_buffer,4); // Somehow with this...

action->bytes = 4;
//printf("%d",atari_sector_buffer[0]); // and this... The wrong checksum is sent!!
//printf(":done\n");
}
49 markw
803 markw
void handleWrite(struct command command, struct SimpleFile * file, struct sio_action * action)
{
//debug_pos = 0;
49 markw
803 markw
int sector = ((int)command.aux1) + (((int)command.aux2)<<8);
int sectorSize = 0;
int location =0;
49 markw
803 markw
if (file_readonly(file))
{
action->success = 0;
return;
}
//printf("%f:WACK\n",when());
//
action->respond = 0;
49 markw
803 markw
location = offset;
if (sector>3)
{
sector-=4;
location += 128*3;
location += sector*atr_header.wSecSize;
sectorSize = atr_header.wSecSize;
}
else
{
location += 128*(sector-1);
sectorSize = 128;
}
49 markw
803 markw
// Receive the data
//printf("%f:Getting data\n",when());
int i;
for (i=0;i!=sectorSize;++i)
{
unsigned char temp = USART_Receive_Byte();
atari_sector_buffer[i] = temp;
//printf("%02x",temp);
}
unsigned char checksum = USART_Receive_Byte();
//hexdump_pure(atari_sector_buffer,sectorSize); // Somehow with this...
unsigned char expchk = get_checksum(&atari_sector_buffer[0],sectorSize);
//printf("DATA:%d:",sectorSize);
//printf("%f:CHK:%02x EXP:%02x %s\n", when(), checksum, expchk, checksum!=expchk ? "BAD" : "");
//printf(" %d",atari_sector_buffer[0]); // and this... The wrong checksum is sent!!
//printf(":done\n");
if (checksum==expchk)
{
send_ACK();
49 markw
803 markw
DELAY_T2_MIN
//printf("%f:WACK data\n",when());
//printf("%d",location);
//printf("\n");
file_seek(file,location);
int written = 0;
file_write(file,&atari_sector_buffer[0], sectorSize, &written);
49 markw
803 markw
int ok = 0;
49 markw
803 markw
if (command.command == 0x57)
{
unsigned char buffer[256];
int read;
file_seek(file,location);
file_read(file,buffer,sectorSize,&read);
437 markw
803 markw
ok = 1;
for (i=0;i!=sectorSize;++i)
437 markw
{
803 markw
if (buffer[i] != atari_sector_buffer[i]) ok = 0;
437 markw
}
803 markw
}
else
ok = 1;
46 markw
803 markw
DELAY_T5_MIN;
46 markw
803 markw
if (ok)
{
//printf("%f:CMPL\n",when());
send_CMPL();
}
else
{
//printf("%f:NACK(verify failed)\n",when());
send_ERR();
}
}
else
{
//printf("%f:NACK(bad checksum)\n",when());
send_NACK();
}
}
46 markw
803 markw
void handleRead(struct command command, struct SimpleFile * file, struct sio_action * action)
{
int sector = ((int)command.aux1) + (((int)command.aux2)<<8);
46 markw
803 markw
int read = 0;
int location =0;
46 markw

803 markw
//printf("Sector:");
//printf("%d",sector);
//printf(":");
if(custom_loader==1) //n_sector>0 && //==0 se overuje hned na zacatku
{
//sektory xex bootloaderu, tj. 1 nebo 2
u08 i,b;
u08 *spt, *dpt;
int file_sectors;
46 markw
803 markw
//file_sectors se pouzije pro sektory $168 i $169 (optimalizace)
//zarovnano nahoru, tj. =(size+124)/125
file_sectors = ((xex_size+(u32)(XEX_SECTOR_SIZE-3-1))/((u32)XEX_SECTOR_SIZE-3));
46 markw
803 markw
//printf("XEX ");
46 markw
803 markw
if (sector<=2)
{
//printf("boot ");

spt= &boot_xex_loader[(u16)(sector-1)*((u16)XEX_SECTOR_SIZE)];
dpt= atari_sector_buffer;
i=XEX_SECTOR_SIZE;
do
46 markw
{
803 markw
b=*spt++;
//relokace bootloaderu z $0700 na jine misto
//TODO if (b==0x07) b+=bootloader_relocation;
*dpt++=b;
i--;
} while(i);
}
else
if(sector==0x168)
{
//printf("numtobuffer ");
//vrati pocet sektoru diskety
//byty 1,2
goto set_number_of_sectors_to_buffer_1_2;
}
else
if(sector==0x169)
{
//printf("name ");
//fatGetDirEntry(FileInfo.vDisk.file_index,5,0);
//fatGetDirEntry(FileInfo.vDisk.file_index,0); //ale musi to posunout o 5 bajtu doprava

{
u08 i,j;
for(i=j=0;i<8+3;i++)
46 markw
{
803 markw
/*if( ((xex_name[i]>='A' && xex_name[i]<='Z') ||
(xex_name[i]>='0' && xex_name[i]<='9')) )
{
//znak je pouzitelny na Atari
atari_sector_buffer[j]=xex_name[i];
j++;
}*/
if ( (i==7) || (i==8+2) )
{
for(;j<=i;j++) atari_sector_buffer[j]=' ';
}
46 markw
}
803 markw
//posune nazev z 0-10 na 5-15 (0-4 budou systemova adresarova data)
//musi pozpatku
for(i=15;i>=5;i--) atari_sector_buffer[i]=atari_sector_buffer[i-5];
//a pak uklidi cely zbytek tohoto sektoru
for(i=5+8+3;i<XEX_SECTOR_SIZE;i++)
atari_sector_buffer[i]=0x00;
46 markw
}

803 markw
//teprve ted muze pridat prvnich 5 bytu na zacatek nulte adresarove polozky (pred nazev)
//atari_sector_buffer[0]=0x42; //0
//jestlize soubor zasahuje do sektoru cislo 1024 a vic,
//status souboru je $46 misto standardniho $42
atari_sector_buffer[0]=(file_sectors>(0x400-0x171))? 0x46 : 0x42; //0
46 markw
803 markw
TWOBYTESTOWORD(atari_sector_buffer+3,0x0171); //3,4
set_number_of_sectors_to_buffer_1_2:
TWOBYTESTOWORD(atari_sector_buffer+1,file_sectors); //1,2
46 markw
}
803 markw
else
if(sector>=0x171)
{
//printf("data ");
file_seek(file,((u32)sector-0x171)*((u32)XEX_SECTOR_SIZE-3));
file_read(file,&atari_sector_buffer[0], XEX_SECTOR_SIZE-3, &read);
46 markw
803 markw
if(read<(XEX_SECTOR_SIZE-3))
sector=0; //je to posledni sektor
else
sector++; //ukazatel na dalsi
46 markw
803 markw
atari_sector_buffer[XEX_SECTOR_SIZE-3]=((sector)>>8); //nejdriv HB !!!
atari_sector_buffer[XEX_SECTOR_SIZE-2]=((sector)&0xff); //pak DB!!! (je to HB,DB)
atari_sector_buffer[XEX_SECTOR_SIZE-1]=read;
}
//printf(" sending\n");

action->bytes = XEX_SECTOR_SIZE;
46 markw
}
868 markw
#ifdef ATX
803 markw
else if (custom_loader==2)
{
gAtxFile = file;
unsigned short ss;
int res = loadAtxSector(0,sector, &ss, &atari_sector_status);

action->bytes = ss;
action->success = res;

// Are existing default delays workable or do they need removing?
// What if put into drive 3/4? Boom?
}
868 markw
#endif
46 markw
else
{
803 markw
location = offset;
if (sector>3)
{
sector-=4;
location += 128*3;
location += sector*atr_header.wSecSize;
action->bytes = atr_header.wSecSize;
}
else
{
location += 128*(sector-1);
action->bytes = 128;
}
//printf("%d",location);
//printf("\n");
//printf("%f:Read\n",when());
file_seek(file,location);
file_read(file,&atari_sector_buffer[0], action->bytes, &read);
//printf("%f:Read done\n",when());
46 markw
}
803 markw
//topofscreen();
//hexdump_pure(atari_sector_buffer,sectorSize);
//printf("Sending\n");

//pause_6502(1);
//hexdump_pure(0x10000+0x400,128);
//get_checksum(0x10000+0x400, sectorSize);
//printf(" receive:");
//printf("%d",chksumreceive);
//printf("\n");
//pause_6502(1);
//while(1);
46 markw
}
803 markw
CommandHandler getCommandHandler(struct command command)
{
CommandHandler res = 0;
int sector = ((int)command.aux1) + (((int)command.aux2)<<8);

switch (command.command)
{
case 0x3f:
res = &handleSpeed;
break;
case 0x21: // format single
case 0x22: // format enhanced
res = &handleFormat;
break;
case 0x4e: // read percom block
res = &handleReadPercomBlock;
break;
case 0x53: // get status
res = &handleGetStatus;
break;
case 0x50: // write
case 0x57: // write with verify
if (sector!=0)
res = &handleWrite;
break;
case 0x52: // read
if (sector!=0)
res = &handleRead;
break;
}

return res;
}
46 markw
49 markw
unsigned char get_checksum(unsigned char* buffer, int len)
46 markw
{
u16 i;
u08 sumo,sum;
sum=sumo=0;
for(i=0;i<len;i++)
{
sum+=buffer[i];
if(sum<sumo) sum++;
sumo = sum;
49 markw
//printf("c:%02x:",sumo);
46 markw
}
return sum;
}

void USART_Send_Buffer(unsigned char *buff, u16 len)
{
while(len>0) { USART_Transmit_Byte(*buff++); len--; }
}

803 markw
void USART_Send_cmpl_and_atari_sector_buffer_and_check_sum(unsigned short len, int success)
46 markw
{
u08 check_sum;
52 markw
//printf("(send:");
//printf("%d",len);
46 markw
DELAY_T5_MIN;
318 markw
//printf("%f:CMPL\n",when());
803 markw
if (success)
{
send_CMPL();
}
else
{
send_ERR();
}
46 markw
// Hias: changed to 100us so that Qmeg3 works again with the
// new bit-banging transmission code
DELAY_T3_PERIPH;

check_sum = 0;
318 markw
//printf("%f:SendBuffer\n",when());
46 markw
USART_Send_Buffer(atari_sector_buffer,len);
// tx_checksum is updated by bit-banging USART_Transmit_Byte,
// so we can skip separate calculation
check_sum = get_checksum(atari_sector_buffer,len);
USART_Transmit_Byte(check_sum);
318 markw
//printf("%f:Done\n",when());
46 markw
//hexdump_pure(atari_sector_buffer,len);
52 markw
/*printf(":chk:");
46 markw
printf("%d",check_sum);
52 markw
printf(")");*/
46 markw
}
62 markw
void describe_disk(int driveNumber, char * buffer)
{
if (drives[driveNumber]==0)
{
buffer[0] = 'N';
buffer[1] = 'O';
buffer[2] = 'N';
buffer[3] = 'E';
buffer[4] = '\0';
return;
}
//enum DriveInfo {DI_XD=0,DI_SD=1,DI_MD=2,DI_DD=3,DI_BITS=3,DI_RO=4};
unsigned char info = drive_info[driveNumber];
buffer[0] = 'R';
buffer[1] = info&DI_RO ? 'O' : 'W';
buffer[2] = ' ';
unsigned char density;
switch (info&3)
{
case DI_XD:
density = 'X';
break;
case DI_SD:
density = 'S';
break;
case DI_MD:
density = 'M';
break;
case DI_DD:
density = 'D';
break;
}
buffer[3] = density;
buffer[4] = 'D';
buffer[5] = '\0';
}
348 markw
803 markw
int get_turbo_div(int pos)
348 markw
{
803 markw
static char turbodivs[] =
348 markw
{
0x28,
0x6,
0x5,
0x4,
0x3,
0x2,
0x1,
0x0
};
803 markw
return (int)turbodivs[pos];
348 markw
}

char const * get_turbo_drive_str()
{
static char const * turbostr[] =
{
"Standard",
"Fast(6)",
"Fast(5)",
"Fast(4)",
"Fast(3)",
"Fast(2)",
"Fast(1)",
"Fast(0)"
};
803 markw
return turbostr[get_turbo_drive()];
348 markw
}