97b26985 |
1 | #include <stdlib.h> |
2 | #include <unistd.h> |
3 | #include <string.h> |
4 | |
5 | #include "tape_block.hh" |
6 | #include "data_block.hh" |
7 | |
8 | #include "silent_code.hh" |
9 | #include "hw_constants.hh" |
10 | |
11 | tape_block::tape_block() |
12 | { |
13 | } |
14 | |
15 | tape_block::tape_block(tape_block & org){ |
16 | block_type=org.block_type; |
17 | init_state=org.init_state; |
18 | data_read=org.data_read; |
19 | raw_data=0; |
20 | raw_size=org.raw_size; |
21 | word_data=0; |
22 | word_size=org.word_size; |
23 | if (raw_size){ |
24 | raw_data=(unsigned char *)malloc(raw_size); |
25 | memcpy(raw_data,org.raw_data,raw_size); |
26 | } |
27 | if (word_size){ |
28 | word_data=(unsigned short *)malloc(word_size*sizeof(unsigned short)); |
29 | memcpy(word_data,org.word_data,word_size*sizeof(unsigned short)); |
30 | } |
31 | } |
32 | |
33 | tape_block::tape_block (int fd, |
34 | void(*input_start)(void *), |
35 | void (*input_stop)(void *), |
36 | void * start_stop_arg |
37 | ) |
38 | { |
39 | unsigned char buffer; |
40 | int retval; |
41 | int eot_needed=EOT_LENGTH; |
42 | int eob_needed=EOB_LENGTH; |
43 | int block_complete=0; |
44 | |
45 | block_type= TBT_DISCARD; |
46 | init_state= TBS_DEFAULT; |
47 | data_read = 0; |
48 | raw_data = 0; |
49 | raw_size = 0; |
50 | word_data = 0; |
51 | word_size = 0; |
52 | |
53 | if (input_start) input_start (start_stop_arg); |
54 | |
55 | /* Look for block start in input stream */ |
56 | do { |
57 | retval=read(fd, &buffer, 1); |
58 | if (retval == 0){ // End of file |
59 | block_type=TBT_DISCARD; |
60 | init_state=TBS_EOF_LEGAL; |
61 | return; |
62 | } |
63 | if (retval == -1){ // Error reading from fd |
64 | block_type=TBT_DISCARD; |
65 | init_state=TBS_IOERR; |
66 | return; |
67 | } |
68 | data_read++; |
69 | |
70 | /* Look for end ot tape sequence */ |
71 | switch(eot_needed){ |
72 | case 3: |
73 | if (buffer==EOT_SEQ_1) eot_needed--; |
74 | else eot_needed=EOT_LENGTH; |
75 | break; |
76 | case 2: |
77 | if (buffer==EOT_SEQ_2) eot_needed--; |
78 | else eot_needed=EOT_LENGTH; |
79 | break; |
80 | case 1: |
81 | if (buffer==EOT_SEQ_3){ |
82 | raw_data=(unsigned char*)malloc(3); |
83 | raw_size=3; |
84 | raw_data[0]=EOT_SEQ_1; |
85 | raw_data[1]=EOT_SEQ_2; |
86 | raw_data[2]=EOT_SEQ_3; |
87 | block_type =TBT_EOT; |
88 | init_state =TBS_OK; |
89 | return; |
90 | } |
91 | else eot_needed=EOT_LENGTH; |
92 | break; |
93 | } |
94 | } while (buffer != (unsigned char) BLOCK_START_DELIMITER); |
95 | |
96 | |
97 | /* Now input the block data */ |
98 | block_complete = 0; |
99 | do { |
100 | retval = read (fd, &buffer, 1); |
101 | |
102 | if (retval == 0){ // End of file |
103 | block_type=TBT_DISCARD; |
104 | init_state=TBS_EOF_ILLEGAL; |
105 | return; |
106 | } |
107 | if (retval == -1){ // Error reading from fd |
108 | block_type=TBT_DISCARD; |
109 | init_state=TBS_IOERR; |
110 | return; |
111 | } |
112 | data_read++; // We have consumed a byte |
113 | |
114 | /* sort in the new byte */ |
115 | raw_size++; |
116 | raw_data=(unsigned char*)realloc(raw_data,raw_size); |
117 | raw_data[raw_size-1]=buffer; |
118 | |
119 | /* Look for end ot block sequence */ |
120 | switch(eob_needed){ |
121 | case 2: |
122 | if (buffer==BLOCK_END_DELIMITER_1) eob_needed--; |
123 | else eob_needed=EOB_LENGTH; |
124 | break; |
125 | case 1: |
126 | if (buffer==BLOCK_END_DELIMITER_2){ |
127 | raw_size-=EOB_LENGTH; // Don't want the delimiter(s) in the data! |
128 | raw_data=(unsigned char*)realloc(raw_data,raw_size); |
129 | block_complete=1; |
130 | } |
131 | else eob_needed=EOB_LENGTH; |
132 | break; |
133 | } |
134 | }while (!block_complete); |
135 | if (input_stop) input_stop (start_stop_arg); |
136 | |
137 | /* Now we have the data in. */ |
138 | |
139 | if (init_words()!=0){ |
140 | init_state=TBS_CHECKSUM; |
141 | return; |
142 | } |
143 | |
144 | if (test_checksum()!=0){ |
145 | init_state=TBS_CHECKSUM; |
146 | return; |
147 | } |
148 | |
149 | block_type=TBT_DATA; |
150 | init_state=TBS_OK; |
151 | } |
152 | |
153 | tape_block::~tape_block(){ |
154 | free(raw_data); |
155 | free(word_data); |
156 | } |
157 | |
158 | tape_block::tb_state_t tape_block::get_state(){ |
159 | return init_state; |
160 | } |
161 | |
162 | int tape_block::get_raw_size(){ |
163 | return raw_size; |
164 | } |
165 | |
166 | unsigned char * tape_block::get_raw_data(){ |
167 | return raw_data; |
168 | } |
169 | |
170 | int tape_block::get_type(){ |
171 | int result=block_type; |
172 | if (block_type==TBT_DATA){ |
173 | data_block * mb=new data_block(*this); |
174 | result=mb->get_type(); |
175 | } |
176 | return result; |
177 | } |
178 | |
179 | int tape_block::get_subtype(){ |
180 | int result=0; |
181 | if (block_type==TBT_DATA){ |
182 | data_block * mb=new data_block(*this); |
183 | result=mb->get_subtype(); |
184 | } |
185 | return result; |
186 | } |
187 | |
188 | int tape_block::init_words(){ |
189 | word_size=raw_size/3; |
190 | if (word_size<MINIMUM_DATA_BLOCK_WORDSIZE) return 1; // Block too short! |
191 | word_data=(unsigned short *)malloc(raw_size*sizeof(unsigned short)); |
192 | for (int pos=0; pos<word_size; pos++) |
193 | word_data[pos]=combine466(raw_data+3*pos); |
194 | return 0; |
195 | } |
196 | |
197 | int tape_block::test_checksum(){ |
198 | unsigned short sum=0; |
199 | for (int pos=0; pos<word_size-1;pos++) |
200 | // sum^=word_data[pos]; |
201 | sum+=word_data[pos]; |
202 | |
203 | // printf("cs:%04x\n",word_data[word_size-1]); |
204 | if (sum==word_data[word_size-1]) return 0; |
205 | else return 1; |
206 | } |