summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--taptoser.c165
1 files changed, 57 insertions, 108 deletions
diff --git a/taptoser.c b/taptoser.c
index f85c81b..3e21f4d 100644
--- a/taptoser.c
+++ b/taptoser.c
@@ -37,23 +37,20 @@ int serial_fd;
size_t out_indx;
struct sigaction saterm; /* definition of signal action */
-
-
-// variables for progress bar
-unsigned int pos_progress;
-float width, progress_pos, progress_part;
+float width; // width of terminal
long pos = 0;
void usage(void) {
- printf ("Tap file serial port uploader/downloader. (c)2012 Pavel Vymetálek <pvymetalek@seznam.cz>\n");
+ printf ("Tap file over serial port uploader/downloader. (c)2012-2015 Pavel Vymetálek <pavel@vym.cz>\n");
+ printf ("Based on utility tapheader: http://zeroteam.sk/tapheader.html (c)2012 Michal Jurica <mike@zeroteam.sk>\n");
printf ("Usage:\ntaptoser [-v] [-h] [-o filename.tap] [-b|--baud baud_rate] -d /dev/serial tap_file\n");
- printf ("\t-v, --version\tShow version info (program and protocol)\n");
+ printf ("\t-v, --version\tShow version info\n");
printf ("\t-h, --help\tShow this text\n");
printf ("\t-d, --device\tCommunication device\n");
- printf ("\t-b, --baud\tSet the communication speed. 9600Bd or 19200Bd are supported by ZX Spectrum\n");
+ printf ("\t-b, --baud\tSet the communication speed. 4800Bd, 9600Bd, 19200Bd and 57600Bd (default) are supported\n");
printf ("\t-B, --binary\tBinary output - received tap from ZX Spectrum will save without all tap's specific mishmash\n");
- printf ("\t-o, --outfile\tOutput to file, instead of stdout. Without coloring ESC sequences\n");
+ printf ("\t-o, --outfile\tOutput file. Usualy *.tap or *.bin with in --binary mode\n");
}
void Set_DTR(unsigned short level) {
@@ -61,8 +58,7 @@ void Set_DTR(unsigned short level) {
ioctl(serial_fd, TIOCMGET, &status);
if (level) {
status |= TIOCM_DTR;
- }
- else {
+ } else {
status &= ~TIOCM_DTR;
}
ioctl(serial_fd, TIOCMSET, &status);
@@ -95,10 +91,10 @@ void TestArgs (int argc, char *argv[])
{0, 0, 0, 0}
};
c = getopt_long (argc, argv, "o:d:b:Bvh", long_options, &option_index);
- if (c == -1)
+ if (c == -1) {
// konec parametru
break;
-
+ }
switch (c) {
case 'h':
usage();
@@ -120,76 +116,65 @@ void TestArgs (int argc, char *argv[])
is_binary = 1;
break;
case 'v':
- printf ("Version 0.0.1\n");
+ printf ("Version 0.9.1 2015-07-22\n");
exit(1);
break;
default:
break;
}
}
-// if (baud_rate != 9600 && baud_rate != 19200) baud_rate = 19200;
-/* Done with options. OPTIND points to first nonoption argument. */
if (optind < argc) {
while (optind < argc){
- strncpy (&tap_file[0], argv[optind++], 63);
+ strncpy (&tap_file[0], argv[optind++], 63); // input tap file name - without option switch
}
}
}
-
-// TAP
-
-
-
+// from tapheader utility
unsigned int h_len;
-unsigned int getword(unsigned char* data)
-{
+unsigned int getword(unsigned char* data) {
return *data + 256 * (*(data + 1));
}
-void tooshort(FILE *fd)
-{
+void tooshort(FILE *fd) {
printf("Input file too short.\n\n");
fclose(fd);
exit(2);
}
// decode header1
-void decode(unsigned char *header)
-{
+void decode(unsigned char *header) {
char name[11];
unsigned int n;
-
+ printf("\n");
strncpy(name, (char*)(header+2), 10);
name[10] = '\0';
- printf("Filename: %s\n", name);
- printf("Flag: %u\n", (unsigned int)*header);
+ printf("Filename: %12s \n", name);
+ printf("Flag: %4u ", (unsigned int)*header);
n = getword(header+14);
h_len = getword(header+12);
- switch(*(header+1))
- {
+ switch(*(header+1)) {
case '\0':
- printf("Type: 0 => program\nProgram length: %u bytes\n", h_len);
- if (n < 32768) printf("Runs from line %u\n", n);
- printf("Length without variables: %u bytes\n",
- getword(header+16));
+ printf("Type: 0 => program\nProgram length: %6u bytes ", h_len);
+ if (n < 32768) printf("Runs from line %5u\t", n);
+ printf("Length without variables: %5u bytes ", getword(header+16));
break;
case '\1':
- printf("Type: 1 => number array\nLength: %u bytes\n", h_len);
+ printf("Type: 1 => number array\tLength: %6u bytes", h_len);
break;
case '\2':
- printf("Type: 2 => character array\nLength: %u bytes\n", h_len);
+ printf("Type: 2 => character array\tLength: %6u bytes", h_len);
break;
case '\3':
if (n == 16384 && h_len == 6912)
printf("Type: 3 => screen image\n");
else
- printf("Type: 3 => bytes\n"
- "Start address: %u\n"
- "Length: %u bytes\n3rd param: %u\n",
+ printf("Type: 3 => bytes "
+ "Start address: %5u\t"
+ "Length: %6u bytes\t3rd param: %4u",
n, h_len, getword(header+16));
break;
}
@@ -197,12 +182,8 @@ void decode(unsigned char *header)
}
void signal_handler_sigterm (int status) {
- is_continue = 0;
-// if (is_outfile) {
-// fclose (tapout_fd);
-// }
-// printf ("\n\nbye...\n");
-// exit (0);
+ // CTRL+C pressed
+ is_continue = 0; // do not continue
}
int GetTerminalWidth(void) {
@@ -228,8 +209,6 @@ void DoProgress(size_t pos, size_t max, unsigned char csum_ok) {
ipercent = percent / 100 * imax;
if (is_binary) progress_char = '#';
else progress_char = '=';
-
-// printf ("\npercent: %f, ipercent: %d\n", percent, ipercent);
printf ("Proceed bytes: %6d/%6d [", (int) pos, (int)max);
for (px = 0; px < imax; px++) {
if (px < ipercent) printf ("%c", progress_char);
@@ -244,6 +223,7 @@ void DoProgress(size_t pos, size_t max, unsigned char csum_ok) {
}
fflush (stdout);
}
+
#define HEADER_RAW_LEN 21
void RecvTap() {
@@ -262,11 +242,7 @@ void RecvTap() {
err = errno;
error (1, err, "can't open output file");
}
-// if (is_outfile) {
- printf("Output file is: %s\n", output_dump_file);
-// } else {
-// outfile = stdout;
-// }
+ printf("Output file is: %s\n", output_dump_file);
p_buff = in_buff;
p_write = in_buff;
while (is_continue) {
@@ -291,14 +267,12 @@ void RecvTap() {
last_block_pos = block_pos;
DoProgress(block_pos, block_len+2, PROGRESS_PERCENT);
}
-
if (block_pos >= HEADER_RAW_LEN && recv_status == 0) {
recv_status = 1; // hlavicka nactena
block_len = getword(in_buff);
block_type = *(in_buff + 2);
-// printf ("Block len: %d Header type: %d\n", block_len, block_type);
if (block_type == 0) {
-// printf ("\nHlavicka komplet\n");
+ // Hlavicka komplet
decode (in_buff + 2);
block_len = 0;
block_pos = 0;
@@ -322,10 +296,10 @@ void RecvTap() {
continue;
}
if (block_len + 2 == block_pos && recv_status > 2) {
-// printf ("\nBlok komplet nacten cekej novy\n");
+ // Blok komplet nacten cekej novy
block_len = getword(in_buff);
block_type = *(in_buff + 2);
- for (tap_pos = 0; tap_pos < block_len -1; tap_pos++){
+ for (tap_pos = 0; tap_pos < block_len -1; tap_pos++) {
xor_csum ^= *(in_buff + 2 + tap_pos);
}
xor_csum_ok = *(in_buff + 2 + block_len - 1);
@@ -337,14 +311,11 @@ void RecvTap() {
fputc(*(in_buff + 3 + tap_pos), tapout_fd); // uloz do souboru
}
DoProgress(tap_pos, block_len - 2, PROGRESS_COMPLETTE);
-
}
// printf ("Checksum OK\n");
} else {
DoProgress(block_pos, block_len+2, PROGRESS_ERROR_CSUM); // vypis error CSUM
-// printf ("Wrong checksum! 0%2.2X\n", xor_csum);
}
-
block_len = 0;
block_pos = 0;
xor_csum = 0;
@@ -353,25 +324,17 @@ void RecvTap() {
p_write = in_buff;
continue;
}
-
}
-
-
}
fclose (tapout_fd);
-
printf ("\n\nulozeno...\n");
}
void SendByte(unsigned char *p_dato) {
-// unsigned char dat;
TestCts();
- // write byte to serial port
-// dat = *p_dato;
-// printf ("%2.2X ", dat);
write (serial_fd, p_dato, 1);
-// // tcdrain(serial_fd);
- usleep (200);
+// tcdrain(serial_fd); // better solution, but usleep at the next line is
+ usleep (200); // faster solution, TODO change sleep time according to serial communication speed 200us is for 57600Bd
}
void SendTap() {
@@ -391,33 +354,28 @@ void SendTap() {
err = errno;
error(1, err, "can't open input file");
}
-
while (pos < st.st_size) {
if (is_continue == 0) break;
pos += no = fread(header, 1, 2, tap_fd);
if (no != 2)
tooshort(tap_fd);
for (out_indx = 0; out_indx < 2; out_indx++) {
- progress_pos = 0;
- printf("[");
SendByte(&header[out_indx]);
}
-
no = getword(header);
if (no == 19) /* HEADER */
{
pos += no = fread(header, 1, 19, tap_fd);
if (no != 19)
tooshort(tap_fd);
- printf ("NO header: %d\n", no);
+// printf ("Header len: %d\n", no);
decode(header);
for (out_indx = 0; out_indx < 19; out_indx++) {
SendByte(&header[out_indx]);
}
- usleep (10000);
+ usleep (400000);
} else {
- if (h_len != no - 2) /* zobrazuj iba bloky bez hl. */
- {
+ if (h_len != no - 2) { /* zobrazuj iba bloky bez hl. */
len = no;
printf ("NO datablock without header: %d\n", no);
printf("Type: datablock\nLength: %u\n", len - 2);
@@ -427,25 +385,15 @@ void SendTap() {
if (no != 1) tooshort(tap_fd);
printf("Flag: %u\n\n", (int)*header);
len--;
- }
- else {
+ } else {
len = no;
}
pos += len;
- // no = fseek(fd, pos, SEEK_SET);
- // if (no != 0)
- // {
- // err = errno;
- // error(1, err, "can't seek in input file");
- // }
- printf ("NO datablock: %d\n\n", len);
for (out_indx = 0; out_indx < len; out_indx++) {
fread(header, 1, 1, tap_fd);
SendByte(header);
DoProgress(out_indx+1, len, PROGRESS_PERCENT);
if (is_continue == 0) break;
- // printf ("len: %5d\r", out_indx);
- // usleep (621);
}
printf ("\n");
}
@@ -462,17 +410,15 @@ int main(int argc, char** argv, char** env)
sigaction (SIGINT, &saterm, NULL);
width = GetTerminalWidth();
+ // nastaveni serioveho portu
struct termios oldtio, newtio;
inp_indx = 0;
if (argc < 3) {
- printf("You must specify the Serial device and file\n");
- usage();
- exit(1);
+ printf("You must specify the Serial device and file\n");
+ usage();
+ exit(1);
}
- printf ("tu som... \n");
TestArgs (argc, argv);
-
- printf ("Serial device: %s, communication speed is: %d Bd\n", MODEMDEVICE, baud_rate);
/* open the device to be non-blocking (read will return immediatly) */
serial_fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (serial_fd < 0) {
@@ -482,6 +428,9 @@ int main(int argc, char** argv, char** env)
tcgetattr(serial_fd, &oldtio); /* save current port settings */
switch (baud_rate){
default:
+ baud_rate = 57600; // default speed
+ newtio.c_cflag = B57600 | CS8 | CLOCAL | CREAD | CSTOPB | CRTSCTS;
+ break;
case 57600:
newtio.c_cflag = B57600 | CS8 | CLOCAL | CREAD | CSTOPB | CRTSCTS;
break;
@@ -491,8 +440,12 @@ int main(int argc, char** argv, char** env)
case 9600:
newtio.c_cflag = B9600 | CS8 | CLOCAL | CREAD | CSTOPB | CRTSCTS;
break;
+ case 4800:
+ newtio.c_cflag = B4800 | CS8 | CLOCAL | CREAD | CSTOPB | CRTSCTS;
+ break;
}
- newtio.c_iflag &= ~(IXON | IXOFF | IXANY); // zrusit XON XOFF
+ printf ("Serial device: %s, communication speed is: %d Bd\n", MODEMDEVICE, baud_rate);
+ newtio.c_iflag &= ~(IXON | IXOFF | IXANY); // vypne XON/XOFF
newtio.c_iflag = IGNPAR | IXOFF;
newtio.c_oflag = 0;
newtio.c_oflag &= ~OPOST;
@@ -501,18 +454,14 @@ int main(int argc, char** argv, char** env)
newtio.c_cc[VTIME] = 10;
tcsetattr(serial_fd, TCSANOW, &newtio);
tcflush(serial_fd, TCIOFLUSH);
- spolfd_serial[0].fd = serial_fd; // nastaveni hlidaneho descriptoru
- spolfd_serial[0].events = POLLIN; // hlidaji se data na vstupu
+ spolfd_serial[0].fd = serial_fd; // nastaveni hlidaneho descriptoru
+ spolfd_serial[0].events = POLLIN; // hlidaji se data na vstupu
-
- Set_DTR(true);
-
+ Set_DTR(true); // PC can read data from speccy everytime
if (is_outfile) {
- // cteni souboru ze seriaku
- RecvTap();
+ RecvTap(); // cteni tap souboru ze seriaku a zapis na disk pocitace
} else {
- // poslat na seriak tap soubor
- SendTap();
+ SendTap(); // poslat na seriak tap soubor do spectra
}
close (serial_fd);
return 0;