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.
34 #include <sys/types.h>
36 #define MAXLINELEN 256
38 int spt_auto_stop
= 1;
40 static int playing
= 0;
41 static int paused
= 0;
43 static char tapename
[MAXFILENAME
];
48 #define IMPBUFLEN 1024
57 static void stop_playing(void)
59 if(playing
) close_tapefile();
63 static void pause_playing(void)
71 static void unpause_playing(void)
80 #define MAXDESCLEN 256
82 static void put_seg_desc(void)
84 if(segtype
!= SEG_VIRTUAL
) {
85 if(segtype
> SEG_END
) {
94 rb
->snprintf(me
,MAXDESCLEN
, "%4d: ", currseg
);
95 me
= me
+rb
->strlen(me
);
96 if(segtype
>= SEG_DATA
&& len
) {
97 rb
->snprintf(me
,MAXDESCLEN
, "%5ld bytes, ", len
);
98 me
= me
+rb
->strlen(me
);
102 for(i
= 0; seg_desc
[i
]; i
++) {
103 if(seg_desc
[i
] == '\n') {
108 rb
->snprintf(me
,MAXDESCLEN
, " ");
109 me
= me
+rb
->strlen(me
);
113 if(ml
< MAXDESCLEN
) *me
++ = seg_desc
[i
];
121 rb
->snprintf(msgbuf
,MAXDESCLEN
, "%4d:", currseg
);
125 else put_msg(seg_desc
);
128 else fprintf(stderr
, "virtual segment\n");
132 static void get_next_segment(void)
139 segtype
= next_segment();
140 currseg
= segment_pos();
152 put_msg(" * Tape paused; Press Ctrl-o to restart * ");
177 static dbyte impbuf
[IMPBUFLEN
];
180 static dbyte
*impbufp
;
181 static int impbufrem
;
184 static int cleared_buffers
= 1;
196 tsp
= sp_tape_impinfo
;
201 if(cleared_buffers
) return;
213 imprem
= CHKTICK
* TMNUM
;
215 else if(!sp_playing_tape
) {
221 clevel
= get_level() ? ~(0) : 0;
228 if(((clevel
? 1 : 0) ^
229 (DANM(ula_inport
) & EARBIT
? 1 : 0) ^
230 (DANM(imp_change
) ? 1 : 0) ^
232 fprintf(stderr
, "Levels don't match %i %i\n", imprem
, impbufrem
);
240 if(cl
) ov
= CHKTICK
/2;
241 else ov
= -(CHKTICK
/2);
251 if(cl
) ov
= CHKTICK
/2;
252 else ov
= -(CHKTICK
/2);
267 ca
= (CHKTICK
/2) - ov
+ 1;
271 ca
= ov
+ (CHKTICK
/2) + 1;
286 ibr
= next_imps(impbuf
, IMPBUFLEN
, CHKTICK
* tsn
);
311 if(segtype
>= SEG_DATA
) {
314 datak
= (int) (get_segpos() / 1000);
315 if(datak
> lastdatak
) {
316 if(ingroup
) rb
->snprintf(msgbuf
,MAXDESCLEN
, "%4d: ", currseg
);
317 else rb
->snprintf(msgbuf
,MAXDESCLEN
, " ");
318 rb
->snprintf(msgbuf
+rb
->strlen(msgbuf
),MAXDESCLEN
, "%3dk", datak
);
358 #define LEADER_MAX 10
367 #define LEADER_MIN_COUNT 512
369 static int rec_segment
;
370 static int rec_state
= RC_NONE
;
371 static byte
*recbuf
= NULL
;
372 static const char *waitchars
= "-\\|/";
374 static int recording
= 0;
381 static byte lastmic
= 0;
382 static int lastlen
= 0;
384 static int leadercount
;
388 static int bytecount
;
389 static int recbufsize
;
390 static int firsthalf
;
391 static int frameswait
= 0;
398 if(!recording
) return;
400 for(fep
= sp_fe_outport_time
, tsl
= TMNUM
; tsl
; fep
++, tsl
--) {
402 if((*fep
& MICBIT
) == lastmic
) {
403 if(lastlen
< MAXLEN
) continue;
405 else lastmic
= ~lastmic
& MICBIT
;
409 if(lastlen
>= LEADER_MIN
&& lastlen
<= LEADER_MAX
) {
410 rec_state
= RC_LEADER
;
415 if((frameswait
++ & 15)) break;
417 sprintf(msgbuf
, " %s: WAITING %c",
418 tapename
, waitchars
[(frameswait
>> 4)]);
422 if(lastlen
>= LEADER_MIN
&& lastlen
<= LEADER_MAX
) {
424 if(leadercount
== LEADER_MIN_COUNT
) {
425 sprintf(msgbuf
, " %s: LEADER", tapename
);
430 if(leadercount
>= LEADER_MIN_COUNT
&&
431 lastlen
>= SYNC_MIN
&& lastlen
<= SYNC_MAX
) rec_state
= RC_SYNC
;
432 else rec_state
= RC_NONE
;
435 if(lastlen
>= SYNC_MIN
&& lastlen
<= SYNC_MAX
) {
445 sprintf(msgbuf
, " %s: DATA", tapename
);
448 else rec_state
= RC_NONE
;
452 if(lastlen
>= BIT0_MIN
&& lastlen
<= BIT0_MAX
) thishalf
= 0;
453 else if(lastlen
>= BIT1_MIN
&& lastlen
<= BIT1_MAX
) thishalf
= 1;
455 if(thishalf
< 0 || (whole
&& firsthalf
!= thishalf
)) {
460 sprintf(msgbuf
, "%s: %03d", tapename
, rec_segment
);
462 sprintf(msgbuf
+strlen(msgbuf
),
463 " %02X %5d %3s", recbuf
[0], bytecount
-2,
464 parity
== 0 ? "OK" : "ERR");
465 if(recbuf
[0] == 0 && bytecount
- 2 >= 17) {
466 filetype
= recbuf
[1];
467 strncpy(filename
, (char*) recbuf
+2, 10);
469 filesize
= recbuf
[12] + (recbuf
[13] << 8);
471 sprintf(msgbuf
+strlen(msgbuf
),
472 " %02X %10s %5i", filetype
, filename
, filesize
);
477 putc(bytecount
& 0xFF, tapefp
);
478 putc((bytecount
>> 8) & 0xFF, tapefp
);
480 fwrite(recbuf
, 1, (size_t) bytecount
, tapefp
);
492 firsthalf
= thishalf
;
501 if(recbufsize
<= bytecount
) {
503 recbuf
= realloc(recbuf
, (size_t) recbufsize
);
505 //fprintf(stderr, "Out of memory\n");
509 recbuf
[bytecount
] = data
;
510 parity
= parity
^ data
;
514 if(!(bytecount
& 1023)) {
515 sprintf(msgbuf
, " %s: DATA %i kB",
516 tapename
, bytecount
>> 10);
530 static void stop_recording(void)
543 static void restart_playing(void)
546 struct tape_options tapeopt
;
550 res
= open_tapefile(tapename
, tapetype
);
553 res
= open_tapefile(tapename
, tapetype
);
556 else res
= open_tapefile(tapename
, tapetype
);
563 INITTAPEOPT(tapeopt
);
565 tapeopt
.blanknoise
= 1;
567 set_tapefile_options(&tapeopt
);
570 res
= goto_segment(currseg
);
582 void pause_play(void)
586 put_msg(" * Tape paused * ");
587 goto_segment(currseg
);
589 else unpause_playing();
593 void start_play_file_type(char *name
, int seg
, int type
)
595 int filetype
= FT_TAPEFILE
;
597 rb
->strlcpy(tapename
, name
, MAXFILENAME
-10 + 1);
602 spcf_find_file_type(tapename
, &filetype
, &tapetype
);
603 if(currseg
< 0) currseg
= 0;
609 void start_play(void)
615 if(playing
|| paused
|| recording
) {
616 put_msg(" * Stop the tape first! * ");
620 put_msg("Enter tape file path:");
621 name
= spif_get_tape_fileinfo(&seg
, &t
);
622 if(name
== NULL
) return;
624 start_play_file_type(name
, seg
, -1);
631 if(playing
|| paused
) {
632 put_msg(" * Stopped playing * ");
634 if(playing
) stop_playing();
635 if(paused
) paused
= 0;
639 sprintf(msgbuf
, " * Stopped recording tape `%s' * ", tapename
);
651 if(playing
|| paused
|| recording
) return;
653 put_msg("Enter tape file to record (default: '.tap'):");
655 name
= spif_get_filename();
656 if(name
== NULL
) return;
658 strncpy(tapename
, name
, MAXFILENAME
-10);
659 tapename
[MAXFILENAME
-10] = '\0';
661 if(!check_ext(tapename
, "tap")) add_extension(tapename
, "tap");
663 tapefp
= fopen(tapename
, "ab");
665 sprintf(msgbuf
, "Could not open tape file `%s', %s",
666 tapename
, strerror(errno
));
676 "Recordind tape file `%s'. To stop press Ctrl-s", tapename
);
689 dbyte length
, dest
, dtmp
;
690 int verify
, success
, firstbyte
;
694 put_msg("Can't quick load tape, because recording");
700 if(paused
) unpause_playing();
706 put_msg("Not quick loading tape");
709 while(playing
&& (segtype
!= SEG_DATA
|| get_segpos() > 0))
721 firstbyte
= !(RF
& ZF
);
728 nextdata
= next_byte();
729 if(nextdata
< 0) break;
734 if(!parity
) success
= 1;
740 if(nextdata
!= type
) break;
744 if(dest
>= 0x4000) DANM(mem
)[dest
] = nextdata
;
747 if(DANM(mem
)[dest
] != nextdata
) break;
754 if(success
) RF
|= (CF
| ZF
);
755 else RF
&= ~(CF
| ZF
);
760 DANM(iff1
) = DANM(iff2
) = 1;
763 sp_init_screen_mark();
765 if(spt_auto_stop
) pause_playing();