1 /*
2 * Turbo tape source
3 * in test / development behaviour
4 *
5 * Stefano Bodrato, 2013
6 *
7 * $Id: turbo.c,v 1.2 2013-02-13 09:08:27 stefano Exp $
8 */
9
10
11 #include <stdio.h>
12
13
main()14 main()
15 {
16 printf("Loading...\n");
17 turbo_screen();
18 }
19
turbo_screen()20 turbo_screen()
21 {
22 #asm
23 ld ix,16384
24 //ld de,6912
25 //ld de,6880
26 call ldr
27 ei
28 ret
29
30 ;------------------------ cut here ------------------------
31 ldr:
32 ; LD IX,screen loc
33 ; LD DE,screen len
34 ; call $ff37
35
36 ; LD IX,loc
37 ; LD DE,len
38 ; call $ff37
39 ; ei
40
41 ; jp <game entry>
42
43 ;...
44
45 ; The A register holds +00 for a header and +FF for a block of data
46 ; The carry flag is reset for VERIFYing and set for LOADing
47
48 ;000FF37:
49 ;LD A,FFh
50 ;SCF ; probably unnecessary
51
52 ;call ff3a
53 ;jp entry
54
55 ;INC D ; This resets the zero flag (D cannot hold +FF)
56 ;EX AF,AF ; A: 0=header, $ff=data block CF: 1=load, 0=verify
57 ;DEC D ; Restore D to its original value
58 DI
59
60 ;LD A,15 ; The border is made WHITE
61 ;OUT (254),A
62 ;LD HL,+053F ; Pre-load the machine stack with the
63 ;PUSH HL ; return address
64
65 IN A,(FEh) ; Make an initial read of port 254
66 RRA ; Rotate the byte obtained
67 AND 20h ; but keep only the EAR bit
68 ; OR 02h ; Signal RED border
69 LD C,A ; Store the value in the C register
70 ; (+22 for 'off' and +02 for 'on' - the present EAR state)
71 LD_BREAK:
72 CP A ; Set the zero flag
73 ; RET NZ ; Return if the BREAK key is being pressed
74
75 LD_START:
76 ; CALL LD_EDGE_1 ;
77 ; JR NC,LD_BREAK ; Return with the carry flag reset if there is no 'edge' within approx.
78 ; 14,000 T states. But if an 'edge' is found the border will go CYAN
79
80 ; The next stage involves waiting a while and then showing that the signal is still pulsing.
81
82 ; LD HL,0415h ; The length of this waiting period will
83 ;LD_WAIT:
84 ; DJNZ LD_WAIT ; be almost one second in duration.
85 ; DEC HL
86 ; LD A,H
87 ; OR L
88 ; JR NZ,LD_WAIT
89 ;
90 ; CALL LD_EDGE_2 ; Continue only if two edges are found
91 ; JR NC,LD_BREAK ; within the allowed time period
92
93
94 ; Now accept only a 'leader signal'.
95 LD_LEADER:
96 LD B,9Ch ; The timing constant
97 CALL LD_EDGE_2 ; Continue only if two edges are found
98 JR NC,LD_BREAK ; within the allowed time period
99
100 LD A,C6h ; However the edges must have been found
101 CP B ; within about 3,000 T states of each other
102 JR NC,LD_START
103 INC H ; Count the pair of edges in the H register
104 JR NZ,LD_LEADER ; until 256 pairs have been found
105
106
107 ; After the leader come the 'off' and 'on' parts of the sync pulse.
108 LD_SYNC:
109 LD B,C9h ; The timing constant
110 CALL LD_EDGE_1 ; Every edge is considered until two edges
111 JR NC,LD_BREAK ; are found close together -
112
113 LD A,B ; these will be the start and finishing edges of the
114 CP D4h ; 'off' sync pulse
115 JR NC,LD_SYNC
116
117 CALL LD_EDGE_1 ; The finishing edge of the 'on' pulse
118 RET NC ; must exist (Return carry flag reset)
119
120 LD A,C ; The border colours from now on will be
121 XOR 03h ; BLUE & YELLOW (in ROM)
122 LD C,A
123 ;LD H,00h ; Initialize the 'parity matching' byte to zero
124 LD B,D0h ; Set the timing constant for the flag byte (was B0 in the original ROM)
125 JR LD_MARKER ; Jump forward into the byte LOADing loop
126
127
128 ; The byte LOADing loop is used to fetch the bytes one at a time. The flag byte is
129 ; first. This is followed by the data bytes and the last byte is the 'parity' byte.
130
131 LD_LOOP:
132 ;EX AF,AF ; A: 0=header, $ff=data block CF: 1=load, 0=verify
133 ; JR NZ,LD_FLAG ; Jump forward only when handling the first byte
134
135 ;;;;;;;;; JR NC,LD_VERIFY ; Jump forward is VERIFYing a tape
136
137 LD (IX+00h),L
138 ; JR LD_NEXT
139
140
141 ; LD_FLAG is called only once when reading the first byte of the block
142 ;LD_FLAG:
143 ; RL C ; Keep the carry flag in a safe place temporarily
144 ; XOR L ; if the flag byte does not match the first byte on the tape...
145 ; RET NZ ; ...Return
146 ; LD A,C ; Restore the carry flag now
147 ; RRA
148 ; LD C,A
149 ; INC DE ; Increase the counter to compensate for
150 ; JR LD_DEC ; its decrease after the jump
151
152
153 ; If a data block is being verified then
154 ; the freshly loaded byte is tested against the original byte.
155 ;;
156 ;;05BD LD-VERIFY LD A,(IX+00) Fetch the original byte
157 ;; XOR L Match it against the new byte
158 ;; RET NZ Return if 'no match' (Carry flag reset)
159
160 LD_NEXT:
161 INC IX ; dst location
162 LD_DEC:
163 ;DEC DE ; size counter
164 ;EX AF,AF ; Save the flags
165
166 LD B,D1h ; Set the timing constant ($B2 in the ROM)
167 LD_MARKER:
168 LD L,01h ; Clear the 'object' register apart from a 'marker' bit
169
170 LD_8_BITS: ; The 'LD-8-BITS' loop is used to build up a byte in the L register.
171 CALL LD_EDGE_2 ; Find the length of the 'off' and 'on' pulses of the next bit
172 RET NC ; Return if the time period is exceeded (Carry flag reset)
173
174 ;LD A,E8h ; ($CB in ROM): Compare the length against approx. 35 increments of b;
175 ;LD A,D8h ; ($CB in ROM): Compare the length against approx. 35 increments of b;
176 ;CP B ; if so.. zero !
177 ld a,b
178
179 ;cp $E3 ; carry set if period is shorter
180 ;cp $E5 ; carry set if period is shorter
181
182 ;cp $e0 (max limit)
183 ;cp $DC (min limit)
184 cp $de
185 JP NC,escseq
186
187 ;LD A,D5h ; new timing
188 ;LD A,D8h ; ($CB in ROM): Compare the length against approx. 2,400 T states (19 increments of b);
189 ;CP B ; resetting the carry flag for a '0' and setting it for a '1'
190 cp $d5 ; carry set if period is shorter
191 ccf
192 RL L ; Include the new bit in the L register
193 ;LD B,D0h ; Set the timing constant for the next bit ($B0)
194 LD B,D0h ; Set the timing constant for the next bit ($B0)
195 JP NC,LD_8_BITS ; Jump back whilst there are still bits to be fetched
196 ; (GB-MAX was jumping in FFB3 to POP DE/RET ???)
197
198
199 ; The 'parity matching' byte has to be updated with each new byte.
200
201 ;LD A,H ; Fetch the 'parity matching' byte and
202 ;XOR L ; include the new byte
203 ;LD H,A ; Save it once again
204
205
206 ; Passes round the loop are made until the 'counter' reaches zero. At that point
207 ; the 'parity matching' byte should be holding zero.
208 nextbyte:
209 ;LD A,D ; Make a furter pass if DE
210 ;OR E ; does not hold zero
211 ;JR NZ,LD_LOOP
212 ;RET
213 JP LD_LOOP
214
215 ; LD A,H Fetch the 'parity matching' byte
216 ; CP +01 Return with the carry flag set if the
217 ; RET value is zero (Carry flag reset if in error)
218
219 ;escseq:
220 ; dec l
221 ; jp nextbyte
222
223 escseq:
224 dec l
225 ;LD B,E7h ; Set the timing constant ($B2 in the ROM)
226 ;LD B,D2h ; Set the timing constant ($B2 in the ROM)
227 LD B,D1h ; Set the timing constant ($B2 in the ROM)
228 CALL LD_EDGE_2 ; Find the length of the 'off' and 'on' pulses of the next bit
229 RET NC ; Return if the time period is exceeded (Carry flag reset)
230 ;LD A,E9h
231 ;LD A,EBh
232 ;LD A,EAh
233 ;LD A,D4h
234
235 ;LD A,D5h ; min limit
236 ;LD A,D7h
237 ;LD A,DAh ; max limit
238 ;LD A,D9h
239
240 LD A,D7h
241
242 ;LD a,b
243
244 CP B ; the 'long' bit stands for a whole byte set to 0
245
246 ;cp $d5 ; CF if short period
247 ;jp nc,nextbyte ; jp if longer
248 jp c,nextbyte ; jp if longer
249
250 ; ok, this is a longer period, look for a byte repeated sequence
251
252 ld l,(ix-1) ; load the last byte value
253
254 zbloop:
255 ;LD B,E7h ; (set up timing)
256 LD B,D1h ; Set the timing constant ($B2 in the ROM)
257 CALL LD_EDGE_2 ; Find the length of the 'off' and 'on' pulses of the next bit
258 RET NC ; Return if the time period is exceeded (Carry flag reset)
259
260 ;LD A,EBh
261 ;LD A,EAh
262 LD A,D5h
263 CP B
264 jp c,nextbyte ; jp if longer
265
266 ld (ix+0),l
267 inc ix
268 ;dec de
269
270 jp zbloop
271
272
273
274 ; THE 'LD-EDGE-2' and 'LD-EDGE-1' SUBROUTINES
275 ; These two subroutines form the most important part of the LOAD/VERIFY operation.
276 ; The subroutines are entered with a timing constant in the B register, and the
277 ; previous border colour and 'edge-type' in the C register.
278 ; The subroutines return with the carry flag set if the required number of 'edges'
279 ; have been found in the time allowed; and the change to the value in the B
280 ; register shows just how long it took to find the 'edge(s)'.
281 ; The carry flag will be reset if there is an error. The zero flag then signals
282 ; 'BREAK pressed' by being reset, or 'time-up' by being set.
283 ; The entry point LD-EDGE-2 is used when the length of a complete pulse is
284 ; required and LD-EDGE-1 is used to find the time before the next 'edge'.
285
286
287 LD_EDGE_2:
288 CALL LD_EDGE_1 ; In effect call LD-EDGE-1 twice;
289 RET NC ; returning in between in there is an error
290
291 LD_EDGE_1:
292 LD A,0Dh ; (was 16 in ROM) Wait 358 T states before entering the sampling loop
293 LD_DELAY:
294 DEC A
295 JR NZ,LD_DELAY
296 AND A
297
298 ; The sampling loop is now entered. The value in the B register is incremented for
299 ; each pass; 'time-up' is given when B reaches zero.
300
301 LD_SAMPLE:
302 INC B ; Count each pass
303 RET Z ; Return carry reset & zero set if 'time-up'.
304 LD A,7Fh ;
305 IN A,(FEh) ; Read from port +7FFE
306 RRA ; shift the byte
307 ; RET NC Return carry reset & zero reset if BREAK was pressed
308 XOR C ; Now test the byte against the 'last edge-type'
309 AND 20h ; Jump back unless it has changed
310 JR Z,LD_SAMPLE
311
312
313 ; A new 'edge' has been found within the time period allowed for the search.
314 ; So change the border colour and set the carry flag.
315
316 LD A,C ; Change the 'last edge-type'
317 CPL ; and border colour
318
319 LD C,A ; (ROM) ld a,c ... (in ROM: RED/CYAN or BLUE/YELLOW)
320 LD A,B ; (ROM) cpl
321 NOP ; (ROM) ld c,a
322 AND 7 ; Keep only the border colour
323 OR 8 ; Signal 'MIC off'
324 OUT (FEh),a ; Change the border colour
325 SCF ; Signal the successful search before returning
326 RET
327
328
329 ;Note: The LD-EDGE-1 subroutine takes 464 T states, plus an additional 59 T
330 ;states for each unsuccessful pass around the sampling loop.
331 ;For example, therefore, when awaiting the sync pulse (see LD-SYNC)
332 ;allowance is made for ten additional passes through the sampling loop.
333 ;The search is thereby for the next edge to be found within, roughly, 1,100 T
334 ;states (464 + 10 * 59 overhead).
335 ;This will prove successful for the sync 'off' pulse that comes after the long
336 ;'leader pulses'.
337 ;------------------------ cut here ------------------------
338
339 #endasm
340 }
341
342