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