2 * Copyright (C) 1996-1998 Szeredi Miklos
3 * Email: mszeredi@inf.bme.hu
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version. See the file COPYING.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 #define MAXLINELEN 256
37 int spt_auto_stop
= 1;
39 static int playing
= 0;
40 static int paused
= 0;
42 static char tapename
[MAXFILENAME
];
47 #define IMPBUFLEN 1024
56 static void stop_playing(void)
58 if(playing
) close_tapefile();
62 static void pause_playing(void)
70 static void unpause_playing(void)
79 #define MAXDESCLEN 256
81 static void put_seg_desc(void)
83 if(segtype
!= SEG_VIRTUAL
) {
84 if(segtype
> SEG_END
) {
93 rb
->snprintf(me
,MAXDESCLEN
, "%4d: ", currseg
);
94 me
= me
+rb
->strlen(me
);
95 if(segtype
>= SEG_DATA
&& len
) {
96 rb
->snprintf(me
,MAXDESCLEN
, "%5ld bytes, ", len
);
97 me
= me
+rb
->strlen(me
);
101 for(i
= 0; seg_desc
[i
]; i
++) {
102 if(seg_desc
[i
] == '\n') {
107 rb
->snprintf(me
,MAXDESCLEN
, " ");
108 me
= me
+rb
->strlen(me
);
112 if(ml
< MAXDESCLEN
) *me
++ = seg_desc
[i
];
120 rb
->snprintf(msgbuf
,MAXDESCLEN
, "%4d:", currseg
);
124 else put_msg(seg_desc
);
127 else fprintf(stderr
, "virtual segment\n");
131 static void get_next_segment(void)
138 segtype
= next_segment();
139 currseg
= segment_pos();
151 put_msg(" * Tape paused; Press Ctrl-o to restart * ");
176 static dbyte impbuf
[IMPBUFLEN
];
179 static dbyte
*impbufp
;
180 static int impbufrem
;
183 static int cleared_buffers
= 1;
195 tsp
= sp_tape_impinfo
;
200 if(cleared_buffers
) return;
212 imprem
= CHKTICK
* TMNUM
;
214 else if(!sp_playing_tape
) {
220 clevel
= get_level() ? ~(0) : 0;
227 if(((clevel
? 1 : 0) ^
228 (DANM(ula_inport
) & EARBIT
? 1 : 0) ^
229 (DANM(imp_change
) ? 1 : 0) ^
231 fprintf(stderr
, "Levels don't match %i %i\n", imprem
, impbufrem
);
239 if(cl
) ov
= CHKTICK
/2;
240 else ov
= -(CHKTICK
/2);
250 if(cl
) ov
= CHKTICK
/2;
251 else ov
= -(CHKTICK
/2);
266 ca
= (CHKTICK
/2) - ov
+ 1;
270 ca
= ov
+ (CHKTICK
/2) + 1;
285 ibr
= next_imps(impbuf
, IMPBUFLEN
, CHKTICK
* tsn
);
310 if(segtype
>= SEG_DATA
) {
313 datak
= (int) (get_segpos() / 1000);
314 if(datak
> lastdatak
) {
315 if(ingroup
) rb
->snprintf(msgbuf
,MAXDESCLEN
, "%4d: ", currseg
);
316 else rb
->snprintf(msgbuf
,MAXDESCLEN
, " ");
317 rb
->snprintf(msgbuf
+rb
->strlen(msgbuf
),MAXDESCLEN
, "%3dk", datak
);
357 #define LEADER_MAX 10
366 #define LEADER_MIN_COUNT 512
368 static int rec_segment
;
369 static int rec_state
= RC_NONE
;
370 static byte
*recbuf
= NULL
;
371 static const char *waitchars
= "-\\|/";
373 static int recording
= 0;
380 static byte lastmic
= 0;
381 static int lastlen
= 0;
383 static int leadercount
;
387 static int bytecount
;
388 static int recbufsize
;
389 static int firsthalf
;
390 static int frameswait
= 0;
397 if(!recording
) return;
399 for(fep
= sp_fe_outport_time
, tsl
= TMNUM
; tsl
; fep
++, tsl
--) {
401 if((*fep
& MICBIT
) == lastmic
) {
402 if(lastlen
< MAXLEN
) continue;
404 else lastmic
= ~lastmic
& MICBIT
;
408 if(lastlen
>= LEADER_MIN
&& lastlen
<= LEADER_MAX
) {
409 rec_state
= RC_LEADER
;
414 if((frameswait
++ & 15)) break;
416 sprintf(msgbuf
, " %s: WAITING %c",
417 tapename
, waitchars
[(frameswait
>> 4)]);
421 if(lastlen
>= LEADER_MIN
&& lastlen
<= LEADER_MAX
) {
423 if(leadercount
== LEADER_MIN_COUNT
) {
424 sprintf(msgbuf
, " %s: LEADER", tapename
);
429 if(leadercount
>= LEADER_MIN_COUNT
&&
430 lastlen
>= SYNC_MIN
&& lastlen
<= SYNC_MAX
) rec_state
= RC_SYNC
;
431 else rec_state
= RC_NONE
;
434 if(lastlen
>= SYNC_MIN
&& lastlen
<= SYNC_MAX
) {
444 sprintf(msgbuf
, " %s: DATA", tapename
);
447 else rec_state
= RC_NONE
;
451 if(lastlen
>= BIT0_MIN
&& lastlen
<= BIT0_MAX
) thishalf
= 0;
452 else if(lastlen
>= BIT1_MIN
&& lastlen
<= BIT1_MAX
) thishalf
= 1;
454 if(thishalf
< 0 || (whole
&& firsthalf
!= thishalf
)) {
459 sprintf(msgbuf
, "%s: %03d", tapename
, rec_segment
);
461 sprintf(msgbuf
+strlen(msgbuf
),
462 " %02X %5d %3s", recbuf
[0], bytecount
-2,
463 parity
== 0 ? "OK" : "ERR");
464 if(recbuf
[0] == 0 && bytecount
- 2 >= 17) {
465 filetype
= recbuf
[1];
466 strncpy(filename
, (char*) recbuf
+2, 10);
468 filesize
= recbuf
[12] + (recbuf
[13] << 8);
470 sprintf(msgbuf
+strlen(msgbuf
),
471 " %02X %10s %5i", filetype
, filename
, filesize
);
476 putc(bytecount
& 0xFF, tapefp
);
477 putc((bytecount
>> 8) & 0xFF, tapefp
);
479 fwrite(recbuf
, 1, (size_t) bytecount
, tapefp
);
491 firsthalf
= thishalf
;
500 if(recbufsize
<= bytecount
) {
502 recbuf
= realloc(recbuf
, (size_t) recbufsize
);
504 //fprintf(stderr, "Out of memory\n");
508 recbuf
[bytecount
] = data
;
509 parity
= parity
^ data
;
513 if(!(bytecount
& 1023)) {
514 sprintf(msgbuf
, " %s: DATA %i kB",
515 tapename
, bytecount
>> 10);
529 static void stop_recording(void)
542 static void restart_playing(void)
545 struct tape_options tapeopt
;
549 res
= open_tapefile(tapename
, tapetype
);
552 res
= open_tapefile(tapename
, tapetype
);
555 else res
= open_tapefile(tapename
, tapetype
);
562 INITTAPEOPT(tapeopt
);
564 tapeopt
.blanknoise
= 1;
566 set_tapefile_options(&tapeopt
);
569 res
= goto_segment(currseg
);
581 void pause_play(void)
585 put_msg(" * Tape paused * ");
586 goto_segment(currseg
);
588 else unpause_playing();
592 void start_play_file_type(char *name
, int seg
, int type
)
594 int filetype
= FT_TAPEFILE
;
596 rb
->strlcpy(tapename
, name
, MAXFILENAME
-10 + 1);
601 spcf_find_file_type(tapename
, &filetype
, &tapetype
);
602 if(currseg
< 0) currseg
= 0;
608 void start_play(void)
614 if(playing
|| paused
|| recording
) {
615 put_msg(" * Stop the tape first! * ");
619 put_msg("Enter tape file path:");
620 name
= spif_get_tape_fileinfo(&seg
, &t
);
621 if(name
== NULL
) return;
623 start_play_file_type(name
, seg
, -1);
630 if(playing
|| paused
) {
631 put_msg(" * Stopped playing * ");
633 if(playing
) stop_playing();
634 if(paused
) paused
= 0;
638 sprintf(msgbuf
, " * Stopped recording tape `%s' * ", tapename
);
650 if(playing
|| paused
|| recording
) return;
652 put_msg("Enter tape file to record (default: '.tap'):");
654 name
= spif_get_filename();
655 if(name
== NULL
) return;
657 strncpy(tapename
, name
, MAXFILENAME
-10);
658 tapename
[MAXFILENAME
-10] = '\0';
660 if(!check_ext(tapename
, "tap")) add_extension(tapename
, "tap");
662 tapefp
= fopen(tapename
, "ab");
664 sprintf(msgbuf
, "Could not open tape file `%s', %s",
665 tapename
, strerror(errno
));
675 "Recordind tape file `%s'. To stop press Ctrl-s", tapename
);
688 dbyte length
, dest
, dtmp
;
689 int verify
, success
, firstbyte
;
693 put_msg("Can't quick load tape, because recording");
699 if(paused
) unpause_playing();
705 put_msg("Not quick loading tape");
708 while(playing
&& (segtype
!= SEG_DATA
|| get_segpos() > 0))
720 firstbyte
= !(RF
& ZF
);
727 nextdata
= next_byte();
728 if(nextdata
< 0) break;
733 if(!parity
) success
= 1;
739 if(nextdata
!= type
) break;
743 if(dest
>= 0x4000) DANM(mem
)[dest
] = nextdata
;
746 if(DANM(mem
)[dest
] != nextdata
) break;
753 if(success
) RF
|= (CF
| ZF
);
754 else RF
&= ~(CF
| ZF
);
759 DANM(iff1
) = DANM(iff2
) = 1;
762 sp_init_screen_mark();
764 if(spt_auto_stop
) pause_playing();