|
#include "atari_drive_emulator.h"
|
|
#include "fileutils.h"
|
|
|
|
#include "uart.h"
|
|
#include "pause.h"
|
|
#include "simplefile.h"
|
|
#include "hexdump.h"
|
|
|
|
#include "printf.h"
|
|
#include "integer.h"
|
|
|
|
extern int debug_pos; // ARG!
|
|
|
|
#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
|
|
#define speedfast 0x6
|
|
#define XEX_SECTOR_SIZE 128
|
|
|
|
#define MAX_DRIVES 4
|
|
|
|
struct SimpleFile * drives[MAX_DRIVES];
|
|
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};
|
|
|
|
struct ATRHeader
|
|
{
|
|
u16 wMagic;
|
|
u16 wPars;
|
|
u16 wSecSize;
|
|
u08 btParsHigh;
|
|
u32 dwCRC;
|
|
u32 dwUNUSED;
|
|
u08 btFlags;
|
|
} __attribute__((packed));
|
|
struct ATRHeader atr_header;
|
|
int offset;
|
|
int xex_loader;
|
|
int xex_size;
|
|
|
|
int speed;
|
|
|
|
int badcommandcount;
|
|
int commandcount;
|
|
int opendrive;
|
|
|
|
int readonly;
|
|
|
|
unsigned char atari_sector_buffer[256];
|
|
|
|
unsigned char get_checksum(unsigned char* buffer, int len);
|
|
|
|
#define TWOBYTESTOWORD(ptr,val) (*((u08*)(ptr)) = val&0xff);(*(1+(u08*)(ptr)) = (val>>8)&0xff);
|
|
|
|
void processCommand();
|
|
void USART_Send_cmpl_and_atari_sector_buffer_and_check_sum(unsigned short len);
|
|
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));
|
|
void getCommand(struct command * cmd)
|
|
{
|
|
int expchk;
|
|
|
|
//printf("Waiting for command\n");
|
|
//USART_Data_Ready();
|
|
while (0 == USART_Command_Line());
|
|
//printf("Init:");
|
|
//printf("%d",*zpu_sio);
|
|
USART_Init(speed+6);
|
|
//printf("%d",speed);
|
|
//printf("\n");
|
|
while (1 == USART_Command_Line())
|
|
{
|
|
actions();
|
|
}
|
|
cmd->deviceId = USART_Receive_Byte();
|
|
cmd->command = USART_Receive_Byte();
|
|
cmd->aux1 = USART_Receive_Byte();
|
|
cmd->aux2 = USART_Receive_Byte();
|
|
cmd->chksum = USART_Receive_Byte();
|
|
while (0 == USART_Command_Line())
|
|
{
|
|
actions();
|
|
}
|
|
//printf("cmd:");
|
|
//printf("Gone high\n");
|
|
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);
|
|
|
|
//printf("Device id:");
|
|
//printf("%d",cmd->deviceId);
|
|
//printf("\n");
|
|
//printf("command:");
|
|
//printf("%d",cmd->command);
|
|
//printf("\n");
|
|
//printf("aux1:");
|
|
//printf("%d",cmd->aux1);
|
|
//printf("\n");
|
|
//printf("aux2:");
|
|
//printf("%d",cmd->aux2);
|
|
//printf("\n");
|
|
//printf("chksum:");
|
|
//printf("%x ",cmd->chksum);
|
|
//printf("%x ",expchk);
|
|
|
|
if (expchk!=cmd->chksum || USART_Framing_Error())
|
|
{
|
|
//printf("ERR ");
|
|
//wait_us(1000000);
|
|
if (speed == speedslow)
|
|
{
|
|
speed = speedfast;
|
|
//printf("SPDF");
|
|
//printf("%d",speed);
|
|
}
|
|
else
|
|
{
|
|
speed = speedslow;
|
|
//printf("SPDS");
|
|
//printf("%d",speed);
|
|
}
|
|
}
|
|
//printf("\n");
|
|
|
|
DELAY_T2_MIN;
|
|
}
|
|
|
|
// Called whenever file changed
|
|
void set_drive_status(int driveNumber, struct SimpleFile * file)
|
|
{
|
|
int read = 0;
|
|
int xfd = 0;
|
|
unsigned char info = 0;
|
|
|
|
drives[driveNumber] = 0;
|
|
drive_info[driveNumber] = 0;
|
|
|
|
if (!file) return;
|
|
|
|
//printf("WTF:%d %x\n",driveNumber, file);
|
|
|
|
// Read header
|
|
read = 0;
|
|
file_seek(file,0);
|
|
file_read(file,(unsigned char *)&atr_header, 16, &read);
|
|
if (read!=16)
|
|
{
|
|
//printf("Could not read header\n");
|
|
return; //while(1);
|
|
}
|
|
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");
|
|
*/
|
|
|
|
xex_loader = 0;
|
|
xfd = compare_ext(file_name(file),"XFD");
|
|
|
|
if (xfd == 1)
|
|
{
|
|
//printf("XFD ");
|
|
// build a fake atr header
|
|
offset = 0;
|
|
atr_header.wMagic = 0x296;
|
|
atr_header.wPars = file_size(file)/16;
|
|
atr_header.wSecSize = 0x80;
|
|
atr_header.btFlags |= file_readonly(file);
|
|
}
|
|
else if (atr_header.wMagic == 0xFFFF) // XEX
|
|
{
|
|
int i;
|
|
//printf("XEX ");
|
|
offset = -256;
|
|
xex_loader = 1;
|
|
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;
|
|
}
|
|
else if (atr_header.wMagic == 0x296) // ATR
|
|
{
|
|
//printf("ATR ");
|
|
offset = 16;
|
|
atr_header.btFlags |= file_readonly(file);
|
|
}
|
|
else
|
|
{
|
|
//printf("Unknown file type");
|
|
return;
|
|
}
|
|
|
|
if (atr_header.btFlags&1)
|
|
{
|
|
info |= DI_RO;
|
|
}
|
|
|
|
if (atr_header.wSecSize == 0x80)
|
|
{
|
|
if (atr_header.wPars>(720*128/16))
|
|
info |= DI_MD;
|
|
else
|
|
info |= DI_SD;
|
|
}
|
|
else if (atr_header.wSecSize == 0x100)
|
|
{
|
|
info |= DI_DD;
|
|
}
|
|
else if (atr_header.wSecSize < 0x100)
|
|
{
|
|
info |= DI_XD;
|
|
}
|
|
else
|
|
{
|
|
//printf("BAD sector size");
|
|
return;
|
|
}
|
|
//printf("%d",atr_header.wPars);
|
|
//printf("0\n");
|
|
|
|
drives[driveNumber] = file;
|
|
drive_info[driveNumber] = info;
|
|
//printf("appears valid\n");
|
|
}
|
|
|
|
struct SimpleFile * get_drive_status(int driveNumber)
|
|
{
|
|
return drives[driveNumber];
|
|
}
|
|
|
|
void init_drive_emulator()
|
|
{
|
|
int i;
|
|
|
|
commandcount = 0;
|
|
badcommandcount = 0;
|
|
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();
|
|
actions();
|
|
}
|
|
}
|
|
|
|
/////////////////////////
|
|
|
|
void processCommand()
|
|
{
|
|
struct command command;
|
|
|
|
getCommand(&command);
|
|
|
|
++commandcount;
|
|
/*FIXME if (commandcount==4 && (4==(4&(*zpu_switches))))
|
|
{
|
|
//printf("Paused\n");
|
|
pause_6502(1);
|
|
while(1);
|
|
}*/
|
|
/*if (badcommandcount==8)
|
|
{
|
|
//printf("Stuck?\n");
|
|
pause_6502(1);
|
|
while(1);
|
|
}*/
|
|
|
|
if (command.deviceId >= 0x31 && command.deviceId <= 0x34)
|
|
{
|
|
int sent = 0;
|
|
int drive = 0;
|
|
struct SimpleFile * file = 0;
|
|
|
|
drive = (command.deviceId&0xf) -1;
|
|
// printf("Drive:");
|
|
// printf("%x %d",command.deviceId,drive);
|
|
if (drive!=opendrive)
|
|
{
|
|
if (drive<MAX_DRIVES && drive>=0)
|
|
{
|
|
opendrive = drive;
|
|
set_drive_status(drive, drives[drive]);
|
|
//printf("HERE!:%d\n",drive);
|
|
}
|
|
}
|
|
|
|
if (drive<0 || !drives[drive])
|
|
{
|
|
//USART_Transmit_Mode();
|
|
//send_NACK();
|
|
//USART_Wait_Transmit_Complete();
|
|
//wait_us(100); // Wait for transmission to complete - Pokey bug, gets stuck active...
|
|
//USART_Receive_Mode();
|
|
|
|
//printf("Drive not present:%d %x", drive, drives[drive]);
|
|
return;
|
|
}
|
|
|
|
file = drives[opendrive];
|
|
|
|
switch (command.command)
|
|
{
|
|
case 0x3f:
|
|
{
|
|
//printf("Speed:");
|
|
int sector = ((int)command.aux1) + (((int)command.aux2&0x7f)<<8);
|
|
USART_Transmit_Mode();
|
|
send_ACK();
|
|
clearAtariSectorBuffer();
|
|
atari_sector_buffer[0] = speedfast;
|
|
hexdump_pure(atari_sector_buffer,1);
|
|
USART_Send_cmpl_and_atari_sector_buffer_and_check_sum(1);
|
|
sent = 1;
|
|
if (sector == 0)
|
|
{
|
|
speed = speedfast;
|
|
//printf("SPDF");
|
|
//printf("%d",speed);
|
|
}
|
|
else
|
|
{
|
|
speed = speedslow;
|
|
//printf("SPDS");
|
|
//printf("%d",speed);
|
|
}
|
|
}
|
|
case 0x53:
|
|
{
|
|
unsigned char status;
|
|
//printf("Stat:");
|
|
USART_Transmit_Mode();
|
|
send_ACK();
|
|
clearAtariSectorBuffer();
|
|
|
|
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] = 0xff;
|
|
atari_sector_buffer[2] = 0xe0;
|
|
atari_sector_buffer[3] = 0x0;
|
|
hexdump_pure(atari_sector_buffer,4); // Somehow with this...
|
|
USART_Send_cmpl_and_atari_sector_buffer_and_check_sum(4);
|
|
sent = 1;
|
|
//printf("%d",atari_sector_buffer[0]); // and this... The wrong checksum is sent!!
|
|
//printf(":done\n");
|
|
}
|
|
break;
|
|
default:
|
|
// TODO
|
|
//USART_Transmit_Mode();
|
|
//send_NACK();
|
|
//USART_Wait_Transmit_Complete();
|
|
//USART_Receive_Mode();
|
|
break;
|
|
case 0x50: // write
|
|
case 0x57: // write with verify
|
|
{
|
|
//debug_pos = 0;
|
|
|
|
int sector = ((int)command.aux1) + (((int)command.aux2&0x7f)<<8);
|
|
int sectorSize = 0;
|
|
int location =0;
|
|
|
|
//printf("WACK:");
|
|
USART_Transmit_Mode();
|
|
if (file_readonly(file))
|
|
{
|
|
send_NACK();
|
|
USART_Wait_Transmit_Complete();
|
|
USART_Receive_Mode();
|
|
return;
|
|
}
|
|
send_ACK();
|
|
USART_Wait_Transmit_Complete();
|
|
USART_Receive_Mode();
|
|
|
|
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;
|
|
}
|
|
|
|
// Receive the data
|
|
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("CHK:%02x EXP:%02x", checksum, expchk);
|
|
//printf(" %d",atari_sector_buffer[0]); // and this... The wrong checksum is sent!!
|
|
//printf(":done\n");
|
|
if (checksum==expchk)
|
|
{
|
|
USART_Transmit_Mode();
|
|
//printf(":WACK2:");
|
|
send_ACK();
|
|
USART_Wait_Transmit_Complete();
|
|
|
|
//printf("%d",location);
|
|
//printf("\n");
|
|
file_seek(file,location);
|
|
int written = 0;
|
|
file_write(file,&atari_sector_buffer[0], sectorSize, &written);
|
|
|
|
int ok = 0;
|
|
|
|
if (command.command == 0x57)
|
|
{
|
|
unsigned char buffer[256];
|
|
int read;
|
|
file_read(file,buffer,sectorSize,&read);
|
|
|
|
ok = 1;
|
|
for (i=0;i!=sectorSize;++i)
|
|
{
|
|
if (buffer[i] != atari_sector_buffer[i]) ok = 0;
|
|
}
|
|
}
|
|
else
|
|
ok = 1;
|
|
|
|
DELAY_T5_MIN;
|
|
if (ok)
|
|
{
|
|
//printf(":CMPL:");
|
|
send_CMPL();
|
|
}
|
|
else
|
|
{
|
|
//printf(":NACK:");
|
|
send_NACK();
|
|
}
|
|
|
|
USART_Wait_Transmit_Complete();
|
|
USART_Receive_Mode();
|
|
}
|
|
else
|
|
{
|
|
//printf(":NACK:");
|
|
send_NACK();
|
|
|
|
USART_Wait_Transmit_Complete();
|
|
USART_Receive_Mode();
|
|
}
|
|
|
|
//debug_pos = -1;
|
|
}
|
|
|
|
break;
|
|
case 0x52: // read
|
|
{
|
|
int sector = ((int)command.aux1) + (((int)command.aux2&0x7f)<<8);
|
|
int sectorSize = 0;
|
|
int read = 0;
|
|
int location =0;
|
|
|
|
USART_Transmit_Mode();
|
|
send_ACK();
|
|
//printf("Sector:");
|
|
//printf("%d",sector);
|
|
//printf(":");
|
|
if(xex_loader) //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;
|
|
|
|
//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));
|
|
|
|
//printf("XEX ");
|
|
|
|
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
|
|
{
|
|
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++)
|
|
{
|
|
/*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]=' ';
|
|
}
|
|
}
|
|
//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;
|
|
}
|
|
|
|
//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
|
|
|
|
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
|
|
}
|
|
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);
|
|
|
|
if(read<(XEX_SECTOR_SIZE-3))
|
|
sector=0; //je to posledni sektor
|
|
else
|
|
sector++; //ukazatel na dalsi
|
|
|
|
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");
|
|
|
|
sectorSize = XEX_SECTOR_SIZE;
|
|
}
|
|
else
|
|
{
|
|
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;
|
|
}
|
|
//printf("%d",location);
|
|
//printf("\n");
|
|
file_seek(file,location);
|
|
file_read(file,&atari_sector_buffer[0], sectorSize, &read);
|
|
}
|
|
|
|
//topofscreen();
|
|
//hexdump_pure(atari_sector_buffer,sectorSize);
|
|
//printf("Sending\n");
|
|
USART_Send_cmpl_and_atari_sector_buffer_and_check_sum(sectorSize);
|
|
sent = 1;
|
|
|
|
//pause_6502(1);
|
|
//hexdump_pure(0x10000+0x400,128);
|
|
unsigned char chksumreceive = 0; //get_checksum(0x10000+0x400, sectorSize);
|
|
//printf(" receive:");
|
|
//printf("%d",chksumreceive);
|
|
//printf("\n");
|
|
//pause_6502(1);
|
|
//while(1);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
//wait_us(100); // Wait for transmission to complete - Pokey bug, gets stuck active...
|
|
|
|
if (sent)
|
|
USART_Wait_Transmit_Complete();
|
|
USART_Receive_Mode();
|
|
}
|
|
else
|
|
{
|
|
++badcommandcount;
|
|
}
|
|
}
|
|
|
|
unsigned char get_checksum(unsigned char* buffer, int len)
|
|
{
|
|
u16 i;
|
|
u08 sumo,sum;
|
|
sum=sumo=0;
|
|
for(i=0;i<len;i++)
|
|
{
|
|
sum+=buffer[i];
|
|
if(sum<sumo) sum++;
|
|
sumo = sum;
|
|
|
|
//printf("c:%02x:",sumo);
|
|
}
|
|
return sum;
|
|
}
|
|
|
|
void USART_Send_Buffer(unsigned char *buff, u16 len)
|
|
{
|
|
while(len>0) { USART_Transmit_Byte(*buff++); len--; }
|
|
}
|
|
|
|
void USART_Send_cmpl_and_atari_sector_buffer_and_check_sum(unsigned short len)
|
|
{
|
|
u08 check_sum;
|
|
//printf("(send:");
|
|
//printf("%d",len);
|
|
|
|
DELAY_T5_MIN;
|
|
send_CMPL();
|
|
|
|
// Hias: changed to 100us so that Qmeg3 works again with the
|
|
// new bit-banging transmission code
|
|
DELAY_T3_PERIPH;
|
|
|
|
check_sum = 0;
|
|
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);
|
|
//hexdump_pure(atari_sector_buffer,len);
|
|
/*printf(":chk:");
|
|
printf("%d",check_sum);
|
|
printf(")");*/
|
|
}
|
|
|
|
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';
|
|
}
|