|
#include "types.h"
|
|
#include "regs.h"
|
|
#include "pause.h"
|
|
#include "debug.h"
|
|
#include "pff.h"
|
|
#include "diskio.h"
|
|
|
|
#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);
|
|
|
|
int opendrive;
|
|
char filename_d1[15];
|
|
char filename_d2[15];
|
|
char filename_d3[15];
|
|
char filename_d4[15];
|
|
|
|
FATFS fatfs;
|
|
DIR dir;
|
|
FILINFO filinfo;
|
|
struct ATRHeader atr_header;
|
|
int selfileno;
|
|
int debugmode;
|
|
int validfile;
|
|
int speed;
|
|
#define speedslow 0x28
|
|
#define speedfast 0x6
|
|
#define XEX_SECTOR_SIZE 128
|
|
|
|
void
|
|
wait_us(int unsigned num)
|
|
{
|
|
// 57.5MHz
|
|
int unsigned cycles = num*57 + num/2;
|
|
*zpu_pause = cycles;
|
|
}
|
|
|
|
void openfile(const char * filename);
|
|
void sdcard();
|
|
void mmcReadCached(u32 sector);
|
|
u32 n_actual_mmc_sector;
|
|
unsigned char * mmc_sector_buffer;
|
|
unsigned char atari_sector_buffer[256];
|
|
unsigned char get_checksum(unsigned char* buffer, u16 len);
|
|
|
|
#define TWOBYTESTOWORD(ptr,val) (*((u08*)(ptr)) = val&0xff);(*(1+(u08*)(ptr)) = (val>>8)&0xff);
|
|
|
|
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;
|
|
}
|
|
|
|
int
|
|
filesize(char const * filename)
|
|
{
|
|
char const * tmp;
|
|
char const * tmp2;
|
|
if (FR_OK != pf_opendir(&dir,"/"))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
while (FR_OK == pf_readdir(&dir,&filinfo) && filinfo.fname[0]!='\0')
|
|
{
|
|
if (filinfo.fattrib & AM_SYS)
|
|
{
|
|
continue;
|
|
}
|
|
if (filinfo.fattrib & AM_HID)
|
|
{
|
|
continue;
|
|
}
|
|
if (filinfo.fattrib & AM_DIR)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
tmp = filename;
|
|
tmp2 = filinfo.fname;
|
|
while (1)
|
|
{
|
|
if (*tmp == *tmp2)
|
|
{
|
|
if (*tmp == '\0')
|
|
{
|
|
return filinfo.fsize;
|
|
}
|
|
++tmp;
|
|
++tmp2;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
selectfile(char * filename)
|
|
{
|
|
int fileno;
|
|
int skip;
|
|
int plotted = 0;
|
|
wait_us(200000);
|
|
for(;;)
|
|
{
|
|
int i = 0;
|
|
int go = 0;
|
|
fileno = 0;
|
|
topofscreen();
|
|
for (i=0; i!=(24*40); ++i)
|
|
{
|
|
*(unsigned char volatile *)(i+0x10000+40000) = 0x00;
|
|
}
|
|
if (FR_OK != pf_opendir(&dir,"/"))
|
|
{
|
|
debug("opendir failed\n");
|
|
mmcReadCached(0);
|
|
hexdump_pure(mmc_sector_buffer,512);
|
|
|
|
while(1);
|
|
}
|
|
|
|
plotted = 0;
|
|
skip = 0;
|
|
if (selfileno>20)
|
|
{
|
|
skip = selfileno-20;
|
|
skip&=0xfffffffe;
|
|
}
|
|
if (selfileno<0)
|
|
{
|
|
selfileno = 0;
|
|
}
|
|
while (FR_OK == pf_readdir(&dir,&filinfo) && filinfo.fname[0]!='\0')
|
|
{
|
|
if (filinfo.fattrib & AM_SYS)
|
|
{
|
|
continue;
|
|
}
|
|
if (filinfo.fattrib & AM_HID)
|
|
{
|
|
continue;
|
|
}
|
|
if (filinfo.fattrib & AM_DIR)
|
|
{
|
|
debug("DIR ");
|
|
}
|
|
if (selfileno == fileno)
|
|
{
|
|
for (i=0;i!=15;++i)
|
|
{
|
|
filename[i] = filinfo.fname[i];
|
|
if (0==filinfo.fname[i]) break;
|
|
filinfo.fname[i]+=128;
|
|
}
|
|
}
|
|
if (--skip<0)
|
|
{
|
|
debug(filinfo.fname);
|
|
++plotted;
|
|
if (plotted&1)
|
|
{
|
|
setxpos(20);
|
|
}
|
|
else
|
|
{
|
|
debug("\n");
|
|
}
|
|
if (plotted==40)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
fileno++;
|
|
}
|
|
debug("\n");
|
|
setypos(21);
|
|
opendrive = 0;
|
|
openfile(filename);
|
|
for (;;)
|
|
{
|
|
unsigned char porta = *atari_porta;
|
|
if (0==(porta&0x2)) // down
|
|
{
|
|
selfileno+=2;
|
|
break;
|
|
}
|
|
else if (0==(porta&0x1)) // up
|
|
{
|
|
selfileno-=2;
|
|
break;
|
|
}
|
|
else if (0==(porta&0x8)) // right
|
|
{
|
|
selfileno|=1;
|
|
break;
|
|
}
|
|
else if (0==(porta&0x4)) // left
|
|
{
|
|
selfileno&=0xfffffffe;
|
|
break;
|
|
}
|
|
else if (0==(*atari_trig0)) // fire
|
|
{
|
|
go = 1;
|
|
while(0==(*atari_trig0));
|
|
break;
|
|
}
|
|
topofscreen();
|
|
//plotnextnumber(porta);
|
|
*atari_colbk = *atari_random;
|
|
//wait_us(200);
|
|
}
|
|
if (go == 1)
|
|
{
|
|
wait_us(200000);
|
|
return validfile; // TODO, another way to quit without selecting...
|
|
}
|
|
wait_us(80000);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void clear_ram()
|
|
{
|
|
int i=0;
|
|
// sdram from 8MB to 16MB
|
|
// sram from 0x200000
|
|
*zpu_ledr = 0xffffffff;
|
|
*zpu_ledg = 0x0;
|
|
wait_us(600);
|
|
|
|
for (i=0x200000; i!=0x280000; i+=1)
|
|
{
|
|
// TODO - use short!
|
|
*(unsigned char volatile *)(i) = 0x0000;
|
|
}
|
|
|
|
*zpu_ledr = 0x55555555;
|
|
*zpu_ledg = 0x55555555;
|
|
|
|
for (i=0x800000; i!=0x1000000; i+=4)
|
|
{
|
|
*(unsigned int volatile *)(i) = 0x00000000;
|
|
}
|
|
|
|
*zpu_ledr = 0;
|
|
*zpu_ledg = 0xffffffff;
|
|
wait_us(600);
|
|
return;
|
|
}
|
|
|
|
void clear_64k_ram()
|
|
{
|
|
int i=0;
|
|
// sdram from 8MB to 16MB
|
|
// sram from 0x200000
|
|
|
|
*zpu_ledr = 0xf0f0f0f0;
|
|
*zpu_ledg = 0x0;
|
|
wait_us(200000);
|
|
|
|
for (i=0x200000; i!=0x210000; i+=1)
|
|
{
|
|
// TODO - use short!
|
|
*(unsigned char volatile *)(i) = 0x0000;
|
|
}
|
|
|
|
*zpu_ledr = 0x55555555;
|
|
*zpu_ledg = 0x55555555;
|
|
|
|
for (i=0x800000; i!=0x810000; i+=4)
|
|
{
|
|
*(unsigned int volatile *)(i) = 0x00000000;
|
|
}
|
|
|
|
*zpu_ledr = 0;
|
|
*zpu_ledg = 0xf0f0f0f0;
|
|
wait_us(200000);
|
|
return;
|
|
}
|
|
|
|
void reset_6502(unsigned int reset_n)
|
|
{
|
|
int prev = *zpu_config;
|
|
if (reset_n == 1)
|
|
*zpu_config = prev&~(1<<7);
|
|
else
|
|
*zpu_config = prev|(1<<7);
|
|
// USES ASHIFTLEFT even with it disabled!! *reset_6502 = reset_n<<7;
|
|
}
|
|
|
|
void pause_6502(unsigned int pause)
|
|
{
|
|
int prev = *zpu_config;
|
|
if (pause == 0)
|
|
*zpu_config = prev&~(1<<6);
|
|
else
|
|
*zpu_config = prev|(1<<6);
|
|
// USES ASHIFTLEFT even with it disabled!! *reset_6502 = reset_n<<7;
|
|
}
|
|
|
|
void actions()
|
|
{
|
|
unsigned int i = 0;
|
|
//unsigned volatile char * store = 0xf00000; // SDRAM - fails!!
|
|
unsigned volatile char * store = 0xf80000; // SRAM...
|
|
unsigned volatile char * store2 = 0xfc0000; // custom chips...
|
|
|
|
if ((1&*zpu_key) == 1)
|
|
{
|
|
unsigned char volatile * mem;
|
|
unsigned char volatile * mem2;
|
|
unsigned char volatile * mem3;
|
|
unsigned char store_portb;
|
|
int reboot = 0;
|
|
int temp;
|
|
int row = 0;
|
|
int next = 0;
|
|
int go = 0;
|
|
|
|
// stop 6502
|
|
pause_6502(1);
|
|
|
|
// TODO -
|
|
// menu for 64k/128k/320K Compy/320K Rambo
|
|
// menu for ROM bank
|
|
// menu for GPIO on/off
|
|
|
|
initdebug(1);
|
|
|
|
mem = 0x9c00 + 0x10000;
|
|
// Copy 1k from 0x$9c00 to sdram
|
|
// 0x200000; sram
|
|
// 0x800000; sdram (always use...)
|
|
for (i=0x0; i!=1024; i++)
|
|
{
|
|
store[i] = mem[i];
|
|
}
|
|
for (i=0x40; i!=1024; i++)
|
|
{
|
|
mem[i] = 0;
|
|
}
|
|
|
|
{
|
|
//gtia
|
|
mem2 = 0x20000;
|
|
mem3 = 0x10000;
|
|
for (i=0xd000; i!=0xd01f; i++)
|
|
{
|
|
store2[i] = mem2[i];
|
|
mem3[i] = 0;
|
|
}
|
|
//pokey1/2
|
|
for (i=0xd200; i!=0xd21f; i++)
|
|
{
|
|
store2[i] = mem2[i];
|
|
mem3[i] = 0;
|
|
}
|
|
//antic
|
|
for (i=0xd400; i!=0xd40f; i++)
|
|
{
|
|
store2[i] = mem2[i];
|
|
mem3[i] = 0;
|
|
}
|
|
}
|
|
|
|
store_portb = *atari_portb;
|
|
|
|
// write a display list at 9c00
|
|
char dl[] = {
|
|
0x70,0x70,0x70,
|
|
0x42,0x40,0x9c,
|
|
0x2,0x2,0x2,0x2,0x2,
|
|
0x2,0x2,0x2,0x2,0x2,
|
|
0x2,0x2,0x2,0x2,0x2,
|
|
0x2,0x2,0x2,0x2,0x2,
|
|
0x2,0x2,0x2,
|
|
0x70,
|
|
0x41,0x00,0x9c
|
|
};
|
|
for (i=0; i!=sizeof(dl); ++i)
|
|
{
|
|
mem[i] = dl[i];
|
|
}
|
|
|
|
// point antic at my display list
|
|
*atari_dlistl = 0x00;
|
|
*atari_dlisth = 0x9c;
|
|
*atari_colbk = 0x00;
|
|
*atari_colpf1 = 0x0f;
|
|
*atari_colpf2 = 0x00;
|
|
*atari_prior = 0x00;
|
|
*atari_chbase = 0xe0;
|
|
*atari_dmactl = 0x22;
|
|
*atari_portb = 0xff;
|
|
*atari_skctl = 0x3;
|
|
*atari_chactl = 0x2;
|
|
|
|
for (;;)
|
|
{
|
|
wait_us(120000);
|
|
topofscreen();
|
|
for (i=0; i!=(24*40); ++i)
|
|
{
|
|
*(unsigned char volatile *)(i+0x10000+40000) = 0x00;
|
|
}
|
|
// 0-5 speed
|
|
// 6-pause
|
|
// 7-reset
|
|
// 8-9-ram
|
|
// 12-13-rom
|
|
// 16-gpio_enable
|
|
debug("System settings\n");
|
|
debug("---------------\n");
|
|
debug("Memory:");
|
|
temp = 0xf&((*zpu_config)>>8);
|
|
if (row == 0)
|
|
{
|
|
if (next != 0)
|
|
{
|
|
temp = temp+next;
|
|
*zpu_config = (*zpu_config&0xfffff0ff)|((temp)<<8);
|
|
next = 0;
|
|
go = 0;
|
|
continue;
|
|
}
|
|
debugoffset(128);
|
|
}
|
|
switch (temp)
|
|
{
|
|
case 0:
|
|
debug("64KiB");
|
|
break;
|
|
case 1:
|
|
debug("128KiB");
|
|
break;
|
|
case 2:
|
|
debug("320KiB Compy Shop");
|
|
break;
|
|
case 3:
|
|
debug("320KiB Rambo");
|
|
break;
|
|
case 4:
|
|
debug("576KiB Compy Shop");
|
|
break;
|
|
case 5:
|
|
debug("576KiB Rambo");
|
|
break;
|
|
case 6:
|
|
debug("1088KiB Rambo");
|
|
break;
|
|
case 7:
|
|
debug("4MB!");
|
|
break;
|
|
}
|
|
debug("\n");
|
|
debug("ROM bank:");
|
|
temp = 0xf&((*zpu_config)>>12);
|
|
if (row == 1)
|
|
{
|
|
if (next != 0)
|
|
{
|
|
temp = temp+next;
|
|
*zpu_config = (*zpu_config&0xffff0fff)|((temp&0xf)<<12);
|
|
next = 0;
|
|
go = 0;
|
|
continue;
|
|
}
|
|
debugoffset(128);
|
|
}
|
|
switch (temp)
|
|
{
|
|
case 1:
|
|
debug("1 (default:XL)");
|
|
break;
|
|
case 2:
|
|
debug("2 (default:XL + hi speed)");
|
|
break;
|
|
case 3:
|
|
debug("3 (default:Ultimon)");
|
|
break;
|
|
case 4:
|
|
debug("4 (default:OS B + hi speed)");
|
|
break;
|
|
default:
|
|
debug("Unknown");
|
|
break;
|
|
}
|
|
debug("\n");
|
|
debug("Speed:");
|
|
temp = 0x3f&((*zpu_config)>>0);
|
|
if (row == 2)
|
|
{
|
|
if (next != 0)
|
|
{
|
|
temp = temp+next;
|
|
if (temp < 0) temp =0;
|
|
*zpu_config = (*zpu_config&0xffffffc0)|(temp&0x3f);
|
|
next = 0;
|
|
go = 0;
|
|
continue;
|
|
}
|
|
debugoffset(128);
|
|
}
|
|
plotnextnumber(57500/(temp+1));
|
|
debug(" KHz\nD1:"); // Bring up selector, instead of booting changes disk image
|
|
if (row == 3)
|
|
{
|
|
debugoffset(128);
|
|
}
|
|
debug(filename_d1);
|
|
debug("\nD2:");
|
|
if (row == 4)
|
|
{
|
|
debugoffset(128);
|
|
}
|
|
debug(filename_d2);
|
|
debug("\nD3:");
|
|
if (row == 5)
|
|
{
|
|
debugoffset(128);
|
|
}
|
|
debug(filename_d3);
|
|
debug("\nD4:");
|
|
if (row == 6)
|
|
{
|
|
debugoffset(128);
|
|
}
|
|
debug(filename_d4);
|
|
if (row>=3 && row<7)
|
|
{
|
|
if (go==1)
|
|
{
|
|
switch (row)
|
|
{
|
|
case 3:
|
|
selectfile(filename_d1);
|
|
break;
|
|
case 4:
|
|
selectfile(filename_d2);
|
|
break;
|
|
case 5:
|
|
selectfile(filename_d3);
|
|
break;
|
|
case 6:
|
|
selectfile(filename_d4);
|
|
break;
|
|
}
|
|
opendrive = row-2;
|
|
next = 0;
|
|
go = 0;
|
|
continue;
|
|
}
|
|
if (next==1)
|
|
{
|
|
for (i=0;i!=15;++i)
|
|
{
|
|
char temp = filename_d4[i];
|
|
filename_d4[i] = filename_d3[i];
|
|
filename_d3[i] = filename_d2[i];
|
|
filename_d2[i] = filename_d1[i];
|
|
filename_d1[i] = temp;
|
|
}
|
|
next = 0;
|
|
go = 0;
|
|
continue;
|
|
}
|
|
if (next==-1)
|
|
{
|
|
for (i=0;i!=15;++i)
|
|
{
|
|
char temp = filename_d1[i];
|
|
filename_d1[i] = filename_d2[i];
|
|
filename_d2[i] = filename_d3[i];
|
|
filename_d3[i] = filename_d4[i];
|
|
filename_d4[i] = temp;
|
|
}
|
|
next = 0;
|
|
go = 0;
|
|
continue;
|
|
}
|
|
}
|
|
if (row == 7)
|
|
{
|
|
debugoffset(128);
|
|
}
|
|
debug("\nReboot");
|
|
if (row == 7)
|
|
{
|
|
if (go==1)
|
|
{
|
|
reboot = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (row == 8)
|
|
{
|
|
debugoffset(128);
|
|
}
|
|
debug("\nExit");
|
|
if (row == 8)
|
|
{
|
|
if (go==1)
|
|
break;
|
|
}
|
|
|
|
next = 0;
|
|
go = 0;
|
|
|
|
for (;;)
|
|
{
|
|
unsigned char porta = *atari_porta;
|
|
if (0==(porta&0x2)) // down
|
|
{
|
|
row+=1;
|
|
if (row>8) row = 8;
|
|
break;
|
|
}
|
|
else if (0==(porta&0x1)) // up
|
|
{
|
|
row-=1;
|
|
if (row<0) row = 0;
|
|
break;
|
|
}
|
|
else if (0==(porta&0x8)) // right
|
|
{
|
|
next = 1;
|
|
break;
|
|
}
|
|
else if (0==(porta&0x4)) // left
|
|
{
|
|
next = -1;
|
|
break;
|
|
}
|
|
else if (0==(*atari_trig0)) // fire
|
|
{
|
|
go = 1;
|
|
while(0==(*atari_trig0));
|
|
break;
|
|
}
|
|
topofscreen();
|
|
//plotnextnumber(porta);
|
|
*atari_colbk = *atari_random;
|
|
//wait_us(200);
|
|
}
|
|
}
|
|
|
|
// wait 2 seconds
|
|
//for (i=0; i!=2000; ++i)
|
|
//{
|
|
// *atari_colbk = *atari_random;
|
|
// wait_us(1000);
|
|
//}
|
|
|
|
for (i=0x040; i!=1024; i++)
|
|
{
|
|
mem[i] = store[i];
|
|
}
|
|
|
|
{
|
|
//gtia
|
|
mem3 = 0x10000;
|
|
for (i=0xd000; i!=0xd01f; i++)
|
|
{
|
|
mem3[i] = store2[i];
|
|
}
|
|
//pokey1/2
|
|
for (i=0xd200; i!=0xd21f; i++)
|
|
{
|
|
mem3[i] = store2[i];
|
|
}
|
|
//antic
|
|
for (i=0xd400; i!=0xd40f; i++)
|
|
{
|
|
mem3[i] = store2[i];
|
|
}
|
|
}
|
|
*atari_portb = store_portb;
|
|
initdebug(debugmode);
|
|
|
|
|
|
if (reboot)
|
|
{
|
|
debug("Booting...");
|
|
wait_us(500000);
|
|
|
|
// reset process
|
|
reset_6502(0);
|
|
*atari_nmien = 0x00;
|
|
clear_64k_ram();
|
|
reset_6502(1);
|
|
}
|
|
|
|
// start 6502
|
|
pause_6502(0);
|
|
}
|
|
|
|
if ((2&*zpu_key) == 2)
|
|
{
|
|
unsigned char volatile * mem;
|
|
unsigned char volatile * mem2;
|
|
unsigned char volatile * mem3;
|
|
unsigned char store_portb;
|
|
int reboot = 0;
|
|
int temp;
|
|
int row = 0;
|
|
int next = 0;
|
|
int go = 0;
|
|
|
|
// stop 6502
|
|
pause_6502(1);
|
|
|
|
// TODO -
|
|
// menu for 64k/128k/320K Compy/320K Rambo
|
|
// menu for ROM bank
|
|
// menu for GPIO on/off
|
|
|
|
initdebug(1);
|
|
|
|
mem = 0x9c00 + 0x10000;
|
|
// Copy 1k from 0x$9c00 to sdram
|
|
// 0x200000; sram
|
|
// 0x800000; sdram (always use...)
|
|
for (i=0x0; i!=1024; i++)
|
|
{
|
|
store[i] = mem[i];
|
|
}
|
|
for (i=0x40; i!=1024; i++)
|
|
{
|
|
mem[i] = 0;
|
|
}
|
|
|
|
{
|
|
//gtia
|
|
mem2 = 0x20000;
|
|
mem3 = 0x10000;
|
|
for (i=0xd000; i!=0xd01f; i++)
|
|
{
|
|
store2[i] = mem2[i];
|
|
mem3[i] = 0;
|
|
}
|
|
//pokey1/2
|
|
for (i=0xd200; i!=0xd21f; i++)
|
|
{
|
|
store2[i] = mem2[i];
|
|
mem3[i] = 0;
|
|
}
|
|
//antic
|
|
for (i=0xd400; i!=0xd40f; i++)
|
|
{
|
|
store2[i] = mem2[i];
|
|
mem3[i] = 0;
|
|
}
|
|
}
|
|
|
|
store_portb = *atari_portb;
|
|
|
|
// write a display list at 9c00
|
|
char dl[] = {
|
|
0x70,0x70,0x70,
|
|
0x42,0x40,0x9c,
|
|
0x2,0x2,0x2,0x2,0x2,
|
|
0x2,0x2,0x2,0x2,0x2,
|
|
0x2,0x2,0x2,0x2,0x2,
|
|
0x2,0x2,0x2,0x2,0x2,
|
|
0x2,0x2,0x2,
|
|
0x70,
|
|
0x41,0x00,0x9c
|
|
};
|
|
for (i=0; i!=sizeof(dl); ++i)
|
|
{
|
|
mem[i] = dl[i];
|
|
}
|
|
|
|
// point antic at my display list
|
|
*atari_dlistl = 0x00;
|
|
*atari_dlisth = 0x9c;
|
|
*atari_colbk = 0x00;
|
|
*atari_colpf1 = 0x0f;
|
|
*atari_colpf2 = 0x00;
|
|
*atari_prior = 0x00;
|
|
*atari_chbase = 0xe0;
|
|
*atari_dmactl = 0x22;
|
|
*atari_portb = 0xff;
|
|
*atari_skctl = 0x3;
|
|
*atari_chactl = 0x2;
|
|
|
|
initdebug(1);
|
|
|
|
if (selectfile(filename_d1))
|
|
{
|
|
opendrive = 1;
|
|
debug("Booting...");
|
|
wait_us(500000);
|
|
|
|
// reset process
|
|
reset_6502(0);
|
|
*atari_nmien = 0x00;
|
|
clear_64k_ram();
|
|
reset_6502(1);
|
|
}
|
|
|
|
initdebug(debugmode);
|
|
pause_6502(0);
|
|
}
|
|
if ((4&*zpu_key) == 4)
|
|
{
|
|
// reset process
|
|
reset_6502(0);
|
|
reset_6502(1);
|
|
}
|
|
if ((8&*zpu_key) == 8)
|
|
{
|
|
// reset process
|
|
reset_6502(0);
|
|
*atari_nmien = 0x00;
|
|
clear_64k_ram();
|
|
reset_6502(1);
|
|
}
|
|
}
|
|
|
|
int sdrive_main();
|
|
int main(void)
|
|
{
|
|
unsigned int i=0;
|
|
debugmode = 0;
|
|
selfileno = 0;
|
|
opendrive = 0;
|
|
pause_6502(1);
|
|
|
|
|
|
/* //wait_us(5000000);
|
|
reset_6502(0);
|
|
*atari_nmien = 0x00;
|
|
clear_64k_ram();
|
|
reset_6502(1);
|
|
pause_6502(0);
|
|
for(;;)
|
|
{
|
|
int j;
|
|
for (j=0; j!=1000; ++j)
|
|
{
|
|
mmcReadCached(j);
|
|
}
|
|
}
|
|
*/
|
|
|
|
speed = speedslow;
|
|
//FIXME if (2==(2&(*zpu_switches)))
|
|
if (0)
|
|
{
|
|
debugmode = 1;
|
|
}
|
|
|
|
initdebug(debugmode);
|
|
|
|
if (debugmode)
|
|
{
|
|
reset_6502(0);
|
|
*atari_nmien = 0x00;
|
|
clear_64k_ram();
|
|
reset_6502(1);
|
|
pause_6502(0);
|
|
|
|
wait_us(2000000);
|
|
}
|
|
|
|
//FIXME if (1==(1&(*zpu_switches)))
|
|
{
|
|
sdcard();
|
|
}
|
|
|
|
pause_6502(1);
|
|
reset_6502(0);
|
|
*atari_nmien = 0x00;
|
|
clear_64k_ram();
|
|
reset_6502(1);
|
|
pause_6502(0);
|
|
|
|
while (1)
|
|
{
|
|
actions();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/* Low level disk I/O module skeleton for Petit FatFs (C)ChaN, 2009 */
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
#include "diskio.h"
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/* Initialize Disk Drive */
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
DSTATUS disk_initialize (void)
|
|
{
|
|
DSTATUS stat;
|
|
|
|
n_actual_mmc_sector = 0xffffffff;
|
|
//do
|
|
//{
|
|
// mmcInit();
|
|
//}
|
|
//while(mmcReset()); //dokud nenulove, tak smycka (return 0 => ok!)
|
|
|
|
//set_spi_clock_freq();
|
|
|
|
// no longer in ram (yet!), misuse will break us...
|
|
mmc_sector_buffer = (unsigned char *)0x4000;
|
|
|
|
stat = RES_OK;
|
|
|
|
return stat;
|
|
}
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/* Read Partial Sector */
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
DRESULT disk_readp (
|
|
BYTE* dest, /* Pointer to the destination object */
|
|
DWORD sector, /* Sector number (LBA) */
|
|
WORD sofs, /* Offset in the sector */
|
|
WORD count /* Byte count (bit15:destination) */
|
|
)
|
|
{
|
|
DRESULT res;
|
|
|
|
/*debug("readp:");
|
|
plotnextnumber(sector);
|
|
debug(" ");
|
|
plotnextnumber((int)dest);
|
|
debug(" ");
|
|
plotnextnumber(sofs);
|
|
debug(" ");
|
|
plotnextnumber(count);
|
|
debug(" ");
|
|
plotnextnumber(atari_sector_buffer);
|
|
debug(" ");
|
|
plotnextnumber(mmc_sector_buffer);
|
|
debug("\n");
|
|
*/
|
|
// Put your code here
|
|
mmcReadCached(sector);
|
|
for(;count>0;++sofs,--count)
|
|
{
|
|
unsigned char x = mmc_sector_buffer[sofs];
|
|
//printf("char:%02x loc:%d", x,sofs);
|
|
*dest++ = x;
|
|
}
|
|
|
|
res = RES_OK;
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/* Write Partial Sector */
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
DRESULT disk_writep (const BYTE* buff, DWORD sc)
|
|
{
|
|
DRESULT res;
|
|
|
|
|
|
if (!buff) {
|
|
if (sc) {
|
|
|
|
// Initiate write process
|
|
|
|
} else {
|
|
|
|
// Finalize write process
|
|
|
|
}
|
|
} else {
|
|
|
|
// Send data to the disk
|
|
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
struct ATRHeader
|
|
{
|
|
u16 wMagic;
|
|
u16 wPars;
|
|
u16 wSecSize;
|
|
u08 btParsHigh;
|
|
u32 dwCRC;
|
|
} __attribute__((packed));
|
|
int offset;
|
|
int xex_loader;
|
|
int xex_size;
|
|
uint8_t xex_name[12];
|
|
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)
|
|
{
|
|
unsigned char * in = (unsigned char *)inw;
|
|
unsigned char temp = in[0];
|
|
in[0] = in[1];
|
|
in[1] = temp;
|
|
}
|
|
|
|
struct command
|
|
{
|
|
u08 deviceId;
|
|
u08 command;
|
|
u08 aux1;
|
|
u08 aux2;
|
|
u08 chksum;
|
|
} __attribute__((packed));
|
|
void getCommand(struct command * cmd)
|
|
{
|
|
int expchk;
|
|
|
|
//debug("Waiting for command\n");
|
|
//USART_Data_Ready();
|
|
while (0 == (1&(*zpu_sio)));
|
|
//debug("Init:");
|
|
//plotnextnumber(*zpu_sio);
|
|
USART_Init(speed+6);
|
|
//plotnextnumber(speed);
|
|
//debug("\n");
|
|
while (1 == (1&(*zpu_sio)))
|
|
{
|
|
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 == (1&(*zpu_sio)));
|
|
debug("cmd:");
|
|
//debug("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);
|
|
|
|
//debug("Device id:");
|
|
plotnextnumber(cmd->deviceId);
|
|
//debug("\n");
|
|
//debug("command:");
|
|
plotnextnumber(cmd->command);
|
|
//debug("\n");
|
|
//debug("aux1:");
|
|
plotnextnumber(cmd->aux1);
|
|
//debug("\n");
|
|
//debug("aux2:");
|
|
plotnextnumber(cmd->aux2);
|
|
//debug("\n");
|
|
//debug("chksum:");
|
|
plotnextnumber(cmd->chksum);
|
|
plotnextnumber(expchk);
|
|
|
|
if (expchk!=cmd->chksum || USART_Framing_Error())
|
|
{
|
|
debug("ERR ");
|
|
//wait_us(1000000);
|
|
if (speed == speedslow)
|
|
{
|
|
speed = speedfast;
|
|
debug("SPDF");
|
|
plotnextnumber(speed);
|
|
}
|
|
else
|
|
{
|
|
speed = speedslow;
|
|
debug("SPDS");
|
|
plotnextnumber(speed);
|
|
}
|
|
}
|
|
debug("\n");
|
|
|
|
DELAY_T2_MIN;
|
|
}
|
|
|
|
void openfile(const char * filename)
|
|
{
|
|
WORD read = 0;
|
|
int dot = 0;
|
|
int xfd = 0;
|
|
validfile = 0;
|
|
debug("Opening:");
|
|
debug(filename);
|
|
debug(":");
|
|
if (FR_OK!=pf_open(filename))
|
|
{
|
|
debug("fail\n");
|
|
return; //while(1);
|
|
//while(1);
|
|
}
|
|
debug("ok\n");
|
|
|
|
while (1)
|
|
{
|
|
if (filename[dot] == '\0')
|
|
break;
|
|
if (filename[dot] != '.')
|
|
{
|
|
++dot;
|
|
continue;
|
|
}
|
|
if (filename[dot+1] == 'X' || filename[dot+1] == 'x')
|
|
if (filename[dot+2] == 'F' || filename[dot+2] == 'f')
|
|
if (filename[dot+3] == 'D' || filename[dot+3] == 'd')
|
|
{
|
|
xfd = 1;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Read header
|
|
read = 0;
|
|
pf_read(&atr_header, 16, &read);
|
|
if (read!=16)
|
|
{
|
|
debug("Could not read header\n");
|
|
return; //while(1);
|
|
}
|
|
byteswap(&atr_header.wMagic);
|
|
byteswap(&atr_header.wPars);
|
|
byteswap(&atr_header.wSecSize);
|
|
/*debug("\nHeader:");
|
|
plotnextnumber(atr_header.wMagic);
|
|
plotnext(toatarichar(' '));
|
|
plotnextnumber(atr_header.wPars);
|
|
plotnext(toatarichar(' '));
|
|
plotnextnumber(atr_header.wSecSize);
|
|
plotnext(toatarichar(' '));
|
|
plotnextnumber(atr_header.btParsHigh);
|
|
plotnext(toatarichar(' '));
|
|
plotnextnumber(atr_header.dwCRC);
|
|
debug("\n");
|
|
*/
|
|
|
|
xex_loader = 0;
|
|
if (xfd == 1)
|
|
{
|
|
debug("XFD ");
|
|
// build a fake atr header
|
|
offset = 0;
|
|
atr_header.wMagic = 0x296;
|
|
atr_header.wPars = filesize(filename)/16;
|
|
atr_header.wSecSize = 0x80;
|
|
}
|
|
else if (atr_header.wMagic == 0xFFFF) // XEX
|
|
{
|
|
int i;
|
|
debug("XEX ");
|
|
offset = -256;
|
|
xex_loader = 1;
|
|
atr_header.wMagic = 0xffff;
|
|
xex_size = filesize(filename);
|
|
atr_header.wPars = xex_size/16;
|
|
atr_header.wSecSize = XEX_SECTOR_SIZE;
|
|
for (i=0;i!=12;++i)
|
|
xex_name[i] = filename[i];
|
|
}
|
|
else if (atr_header.wMagic == 0x296) // ATR
|
|
{
|
|
debug("ATR ");
|
|
offset = 16;
|
|
}
|
|
else
|
|
{
|
|
debug("Unknown file type");
|
|
return;
|
|
}
|
|
|
|
if (atr_header.wSecSize == 0x80)
|
|
{
|
|
if (atr_header.wPars>(720*128/16))
|
|
debug("MD ");
|
|
else
|
|
debug("SD ");
|
|
}
|
|
else if (atr_header.wSecSize == 0x100)
|
|
{
|
|
debug("DD ");
|
|
}
|
|
else if (atr_header.wSecSize < 0x100)
|
|
{
|
|
debug("XD ");
|
|
}
|
|
else
|
|
{
|
|
debug("BAD sector size");
|
|
return;
|
|
}
|
|
plotnextnumber(atr_header.wPars);
|
|
debug("0\n");
|
|
validfile = 1;
|
|
}
|
|
|
|
void sdcard()
|
|
{
|
|
int i;
|
|
int commandcount = 0;
|
|
int badcommandcount = 0;
|
|
WORD read;
|
|
struct command command;
|
|
int location;
|
|
char const * default_filename = "BOOT.ATR";
|
|
|
|
debug("sdcard\n");
|
|
|
|
debug("disk_init:");
|
|
if(disk_initialize()!=RES_OK)
|
|
{
|
|
debug("fail\n");
|
|
return;
|
|
}
|
|
debug("ok\n");
|
|
|
|
debug("mount:");
|
|
if(pf_mount(&fatfs)!=FR_OK)
|
|
{
|
|
debug("fail\n");
|
|
return;
|
|
}
|
|
debug("ok\n");
|
|
|
|
debug("opendir:");
|
|
if (FR_OK != pf_opendir(&dir,"/"))
|
|
{
|
|
debug("fail\n");
|
|
return;
|
|
}
|
|
debug("ok\n");
|
|
|
|
while (FR_OK == pf_readdir(&dir,&filinfo) && filinfo.fname[0]!='\0')
|
|
{
|
|
debug(filinfo.fname);
|
|
}
|
|
|
|
for (i=0;i!=15;++i)
|
|
{
|
|
filename_d1[i] = default_filename[i];
|
|
filename_d2[i] = default_filename[i];
|
|
filename_d3[i] = default_filename[i];
|
|
filename_d4[i] = default_filename[i];
|
|
if (default_filename[i] == 0) break;
|
|
}
|
|
|
|
if (FR_OK!=pf_open("atarirom.bin"))
|
|
{
|
|
debug("fail\n");
|
|
*atari_skctl = 0;
|
|
*atari_skctl = 0x3;
|
|
for (i=0;i<1000;++i)
|
|
{
|
|
wait_us(5000);
|
|
*atari_colbk = *atari_random;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
char volatile * addr = (char volatile *)0xf04000;
|
|
while (1)
|
|
{
|
|
int i=0;
|
|
read = 0;
|
|
pf_read(&mmc_sector_buffer[0],512,&read);
|
|
|
|
for (i=0;i!=read;++i)
|
|
{
|
|
*addr++ = mmc_sector_buffer[i];
|
|
}
|
|
|
|
if (read!=512) break;
|
|
}
|
|
|
|
// Old file format is:
|
|
// 0000 - ROM
|
|
// 4000 - ROM
|
|
// 8000 - ROM
|
|
// c000 - BASIC
|
|
//10000 - ROM
|
|
|
|
{
|
|
// Copy basic to the beginning
|
|
char * from = 0xf10000;
|
|
char * to = 0xf00000;
|
|
int len = 16384;
|
|
while (len--)
|
|
{
|
|
*to++ = *from++;
|
|
}
|
|
}
|
|
|
|
{
|
|
// Copy 4th rom over where basic was
|
|
char * from = 0xf14000;
|
|
char * to = 0xf10000;
|
|
int len = 16384;
|
|
while (len--)
|
|
{
|
|
*to++ = *from++;
|
|
}
|
|
}
|
|
}
|
|
|
|
opendrive = 1;
|
|
openfile(filename_d1);
|
|
|
|
reset_6502(0);
|
|
*atari_nmien = 0x00;
|
|
clear_64k_ram();
|
|
reset_6502(1);
|
|
pause_6502(0);
|
|
|
|
USART_Init(speed+6);
|
|
while (1)
|
|
{
|
|
getCommand(&command);
|
|
++commandcount;
|
|
/*FIXME if (commandcount==4 && (4==(4&(*zpu_switches))))
|
|
{
|
|
debug("Paused\n");
|
|
pause_6502(1);
|
|
while(1);
|
|
}*/
|
|
/*if (badcommandcount==8)
|
|
{
|
|
debug("Stuck?\n");
|
|
pause_6502(1);
|
|
while(1);
|
|
}*/
|
|
|
|
if (command.deviceId >= 0x31 && command.deviceId < 0x34)
|
|
{
|
|
int sent = 0;
|
|
int drive = 0;
|
|
|
|
drive = command.deviceId&0xf;
|
|
if (drive!=opendrive)
|
|
{
|
|
opendrive = drive;
|
|
switch(drive)
|
|
{
|
|
case 1:
|
|
openfile(filename_d1);
|
|
break;
|
|
case 2:
|
|
openfile(filename_d2);
|
|
break;
|
|
case 3:
|
|
openfile(filename_d3);
|
|
break;
|
|
case 4:
|
|
openfile(filename_d4);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!validfile)
|
|
{
|
|
//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();
|
|
continue;
|
|
}
|
|
|
|
switch (command.command)
|
|
{
|
|
case 0x3f:
|
|
{
|
|
debug("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;
|
|
debug("SPDF");
|
|
plotnextnumber(speed);
|
|
}
|
|
else
|
|
{
|
|
speed = speedslow;
|
|
debug("SPDS");
|
|
plotnextnumber(speed);
|
|
}
|
|
}
|
|
case 0x53:
|
|
{
|
|
unsigned char status;
|
|
debug("Stat:");
|
|
USART_Transmit_Mode();
|
|
send_ACK();
|
|
clearAtariSectorBuffer();
|
|
|
|
status = 0x10; // Motor on;
|
|
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;
|
|
plotnextnumber(atari_sector_buffer[0]); // and this... The wrong checksum is sent!!
|
|
debug(":done\n");
|
|
}
|
|
break;
|
|
case 0x50: // write
|
|
case 0x57: // write with verify
|
|
default:
|
|
// TODO
|
|
//USART_Transmit_Mode();
|
|
//send_NACK();
|
|
//USART_Wait_Transmit_Complete();
|
|
//USART_Receive_Mode();
|
|
break;
|
|
case 0x52: // read
|
|
{
|
|
int sector = ((int)command.aux1) + (((int)command.aux2&0x7f)<<8);
|
|
int sectorSize = 0;
|
|
|
|
USART_Transmit_Mode();
|
|
send_ACK();
|
|
read = 0;
|
|
debug("Sector:");
|
|
plotnextnumber(sector);
|
|
debug(":");
|
|
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));
|
|
|
|
debug("XEX ");
|
|
|
|
if (sector<=2)
|
|
{
|
|
debug("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)
|
|
{
|
|
debug("numtobuffer ");
|
|
//vrati pocet sektoru diskety
|
|
//byty 1,2
|
|
goto set_number_of_sectors_to_buffer_1_2;
|
|
}
|
|
else
|
|
if(sector==0x169)
|
|
{
|
|
debug("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)
|
|
{
|
|
debug("data ");
|
|
pf_lseek(((u32)sector-0x171)*((u32)XEX_SECTOR_SIZE-3));
|
|
pf_read(&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;
|
|
}
|
|
debug(" 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;
|
|
}
|
|
plotnextnumber(location);
|
|
debug("\n");
|
|
pf_lseek(location);
|
|
pf_read(&atari_sector_buffer[0], sectorSize, &read);
|
|
}
|
|
|
|
//topofscreen();
|
|
//hexdump_pure(atari_sector_buffer,sectorSize);
|
|
//debug("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);
|
|
debug(" receive:");
|
|
plotnextnumber(chksumreceive);
|
|
debug("\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;
|
|
}
|
|
}
|
|
}
|
|
|
|
void mmcReadCached(u32 sector)
|
|
{
|
|
//debug("mmcReadCached");
|
|
//plotnext(toatarichar(' '));
|
|
//plotnextnumber(sector);
|
|
//debug("\n");
|
|
if(sector==n_actual_mmc_sector) return;
|
|
//debug("mmcReadREAL");
|
|
//plotnext(toatarichar(' '));
|
|
//plotnextnumber(sector);
|
|
//debug("\n");
|
|
|
|
//u08 ret,retry;
|
|
//predtim nez nacte jiny, musi ulozit soucasny
|
|
// TODO mmcWriteCachedFlush();
|
|
//az ted nacte novy
|
|
//retry=0; //zkusi to maximalne 256x
|
|
/*do
|
|
{
|
|
ret = mmcRead(sector); //vraci 0 kdyz ok
|
|
retry--;
|
|
} while (ret && retry);
|
|
while(ret); //a pokud se vubec nepovedlo, tady zustane zablokovany cely SDrive!
|
|
*/
|
|
|
|
*zpu_sector = sector;
|
|
while ((1&*zpu_sector)==1)
|
|
{
|
|
// Wait until ready
|
|
}
|
|
|
|
n_actual_mmc_sector=sector;
|
|
}
|
|
|
|
unsigned char get_checksum(unsigned char* buffer, u16 len)
|
|
{
|
|
u16 i;
|
|
u08 sumo,sum;
|
|
sum=sumo=0;
|
|
for(i=0;i<len;i++)
|
|
{
|
|
sum+=buffer[i];
|
|
if(sum<sumo) sum++;
|
|
sumo = sum;
|
|
}
|
|
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;
|
|
debug("(send:");
|
|
plotnextnumber(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);
|
|
debug(":chk:");
|
|
plotnextnumber(check_sum);
|
|
debug(")");
|
|
}
|