1	SECTION code,code
2; This file can be translated with A68k or PhxAss and then linked with BLink
3; to produce an Amiga executable. Make sure it does not contain any
4; relocations, then run it through the filesys.sh script
5;
6; Patrick: It also works with SAS/C asm+slink, but I had to remove
7; the .l from jsr.l and jmp.l.
8; Toni Wilen: modified SECTION, compiles now with AsmOne and clones(?)
9; Removed absolute RT_AREA references
10; 2002.08.06 RDB automount/autoboot support (Toni Wilen)
11; 2002.09.11 KS1.3 RDB support (TW)
12; 200?.??.?? Picasso96 vblank hack (TW)
13; 2006.03.04 Mousehack code integrated (TW)
14; 2006.18.07 FileSystem.resource find routine access fault fixed (TW)
15; 2007.03.30 mousehack do not start multiple times anymore (TW)
16; 2007.06.15 uninitialized variable in memory type selection fixed (stupid me) (TW)
17; 2007.08.09 started implementing removable drive support (TW)
18; 2007.09.01 ACTION_EXAMINE_ALL (TW)
19; 2007.09.05 full filesystem device mounting on the fly (TW)
20; 2008.01.09 ACTION_EXAMINE_ALL does not anymore return eac_Entries = 0 with continue (fixes some broken programs)
21; 2008.12.11 mousehack -> tablet driver
22; 2008.12.25 mousehack cursor sync
23; 2009.01.20 clipboard sharing
24; 2009.12.27 console hook
25; 2010.05.27 Z3Chip
26; 2011.12.17 built-in CDFS support
27
28AllocMem = -198
29FreeMem = -210
30
31; don't forget filesys.c! */
32PP_MAXSIZE = 4 * 96
33PP_FSSIZE = 400
34PP_FSPTR = 404
35PP_ADDTOFSRES = 408
36PP_FSRES = 412
37PP_FSRES_CREATED = 416
38PP_EXPLIB = 420
39PP_FSHDSTART = 424
40PP_TOTAL = (PP_FSHDSTART+140)
41
42NOTIFY_CLASS = $40000000
43NOTIFY_CODE = $1234
44NRF_SEND_MESSAGE = 1
45NRF_SEND_SIGNAL = 2
46NRF_WAIT_REPLY = 8
47NRF_NOTIFY_INITIAL = 16
48NRF_MAGIC = $80000000
49
50	dc.l 16 								; 4
51our_seglist:
52	dc.l 0 									; 8 /* NextSeg */
53start:
54	bra.s startjmp
55	dc.w 9						;0 12
56startjmp:
57	bra.w filesys_mainloop		;1 16
58	dc.l make_dev-start			;2 20
59	dc.l filesys_init-start		;3 24
60	dc.l exter_server-start		;4 28
61	dc.l bootcode-start			;5 32
62	dc.l setup_exter-start		;6 36
63	dc.l 0      				;7 40
64	dc.l clipboard_init-start 	;8 44
65	;52
66
67bootcode:
68	lea.l doslibname(pc),a1
69	jsr -96(a6) ; FindResident
70	move.l d0,a0
71	move.l 22(a0),d0
72	move.l d0,a0
73	jsr (a0)
74	rts
75
76residenthack
77	movem.l d0-d2/a0-a2/a6,-(sp)
78
79	move.w #$FF38,d0
80	moveq #17,d1
81	bsr.w getrtbase
82	jsr (a0)
83	tst.l d0
84	beq.s .rsh
85
86	move.l 4.w,a6
87	cmp.w #37,20(a6)
88	bcs.s .rsh
89	moveq #residentcodeend-residentcodestart,d0
90	move.l d0,d2
91	moveq #1,d1
92	jsr AllocMem(a6)
93	tst.l d0
94	beq.s .rsh
95	move.l d0,a2
96
97	move.l a2,a0
98	lea residentcodestart(pc),a1
99.cp1
100	move.l (a1)+,(a0)+
101	subq.l #4,d2
102	bne.s .cp1
103
104	jsr -$0078(a6) ;Disable
105	move.l a6,a1
106	move.w #-$48,a0 ;InitCode
107	move.l a2,d0
108	jsr -$01a4(a6) ;SetFunction
109	move.l d0,residentcodejump2-residentcodestart+2(a2)
110	lea myafterdos(pc),a0
111	move.l a0,residentcodejump1-residentcodestart+2(a2)
112	jsr -$27C(a6) ;CacheClearU
113	jsr -$007e(a6) ;Enable
114.rsh
115	movem.l (sp)+,d0-d2/a0-a2/a6
116	rts
117
118myafterdos
119	move.l (sp),a0
120	move.l 2(a0),a0
121	move.l a0,-(sp)
122	jsr (a0) ;jump to original InitCode
123	move.l (sp)+,a0
124	addq.l #4,sp ;remove return address
125	movem.l d0-d7/a1-a6,-(sp)
126	move.l a6,a1
127	move.l a0,d0
128	move.w #-$48,a0 ;InitCode
129	jsr -$01a4(a6) ;SetFunction (restore original)
130	bsr.w clipboard_init
131	bsr.w consolehook
132	movem.l (sp)+,d0-d7/a1-a6
133	rts ;return directly to caller
134
135	cnop 0,4
136residentcodestart:
137	btst #2,d0 ;RTF_AFTERDOS?
138	beq.s resjump
139residentcodejump1
140	jsr $f00000
141resjump
142residentcodejump2
143	jmp $f00000
144	cnop 0,4
145residentcodeend:
146
147filesys_init:
148	movem.l d0-d7/a0-a6,-(sp)
149	move.l 4.w,a6
150	move.w #$FFEC,d0 ; filesys base
151	bsr getrtbase
152	move.l (a0),a5
153	lea.l explibname(pc),a1 ; expansion lib name
154	moveq #36,d0
155	moveq #1,d5
156	jsr  -552(a6) ; OpenLibrary
157	tst.l d0
158	bne.b FSIN_explibok
159	lea.l explibname(pc),a1 ; expansion lib name
160	moveq #0,d0
161	moveq #0,d5
162	jsr  -552(a6) ; OpenLibrary
163FSIN_explibok:
164	move.l d0,a4
165
166	tst.l $10c(a5)
167	beq.w FSIN_none
168
169	move.l #PP_TOTAL,d0
170	move.l #$10001,d1
171	jsr AllocMem(a6)
172	move.l d0,a3  ; param packet
173	move.l a4,PP_EXPLIB(a3)
174
175	moveq #0,d6
176FSIN_init_units:
177	cmp.w $10e(a5),d6
178	bcc.b FSIN_units_ok
179	move.l d6,-(sp)
180FSIN_nextsub:
181	moveq #1,d7
182	tst.w d5
183	beq.s .oldks
184	bset #2,d7
185.oldks	move.l a3,-(sp)
186	move.l a3,a0
187	bsr.w make_dev
188	move.l (sp)+,a3
189	cmp.l #-2,d0
190	beq.s FSIN_nomoresub
191	swap d6
192	addq.w #1,d6
193	swap d6
194	bra.s FSIN_nextsub
195FSIN_nomoresub:
196	move.l (sp)+,d6
197	addq.w #1,d6
198	bra.b FSIN_init_units
199FSIN_units_ok:
200
201	move.l 4.w,a6
202	move.l a3,a1
203	move.l #PP_TOTAL,d0
204	jsr FreeMem(a6)
205
206FSIN_none:
207	move.l 4.w,a6
208	move.l a4,a1
209	jsr -414(a6) ; CloseLibrary
210
211	; add MegaChipRAM
212	moveq #3,d4 ; MEMF_CHIP | MEMF_PUBLIC
213	cmp.w #36,20(a6)
214	bcs.s FSIN_ksold
215	or.w #256,d4 ; MEMF_LOCAL
216FSIN_ksold
217	move.w #$FF80,d0
218	bsr.w getrtbase
219	jsr (a0) ; d1 = size, a1 = start address
220	move.l a1,a0
221	move.l d1,d0
222	beq.s FSIN_fchip_done
223	move.l d4,d1
224	moveq #-5,d2
225	lea fchipname(pc),a1
226	jsr -618(a6) ; AddMemList
227FSIN_fchip_done
228
229	lea fstaskname(pc),a0
230	lea fsmounttask(pc),a1
231	moveq #10,d0
232	bsr createtask
233	move.l d0,a1
234	moveq #1,d1
235	move.w #$FF48,d0 ; store task pointer
236	bsr.w getrtbase
237	jsr (a0)
238
239	movem.l (sp)+,d0-d7/a0-a6
240general_ret:
241	rts
242
243	REM
244addextrachip:
245	move.w #$FF80,d0
246	bsr.w getrtbase
247	jsr (a0)
248	jsr -$0078(a6) ; Disable
249	lea 322(a6),a0 ; MemHeader
250FSIN_scanchip:
251	move.l (a0),a0	; first MemList
252	tst.l (a0)
253	beq.w FSIN_scannotfound
254	move.l 20(a0),d1 ; mh_Lower
255	clr.w d1
256	tst.l d1
257	bne.s FSIN_scanchip
258	move.w 14(a0),d1 ; attributes
259	bmi.s FSIN_scanchip
260	and #2,d1 ; MEMF_CHIP?
261	beq.s FSIN_scanchip
262	sub.l 24(a0),d0 ; did KS detect all chip?
263	bmi.s FSIN_scandone
264	beq.s FSIN_scandone
265	; add the missing piece
266	move.l 24(a0),d1
267	add.l d0,24(a0) ; mh_Upper
268	add.l d0,28(a0) ; mh_Free
269	add.l d0,62(a6) ; MaxLocMem
270	; we still need to update last node's free space
271	move.l 16(a0),a0 ; mh_First
272FSIN_chiploop2
273	tst.l (a0)
274	beq.s FSIN_chiploop
275	move.l (a0),a0
276	bra.s FSIN_chiploop2
277FSIN_chiploop:
278	move.l a0,d2
279	add.l 4(a0),d2
280	;Last block goes to end of chip?
281	cmp.l d2,d1
282	beq.s FSIN_chipadd1
283	;It didn't, add new MemChunk
284	move.l d1,(a0)
285	move.l d1,a1
286	clr.l (a1)+
287	move.l d0,(a1)
288	bra.s FSIN_scandone
289FSIN_chipadd1:
290	add.l d0,4(a0)
291FSIN_scandone:
292	jsr -$007e(a6) ; Enable
293	rts
294
295FSIN_scannotfound:
296	moveq #3,d4 ; MEMF_CHIP | MEMF_PUBLIC
297	cmp.w #36,20(a6)
298	bcs.s FSIN_ksold
299	or.w #256,d4 ; MEMF_LOCAL
300FSIN_ksold
301	; add >2MB-6MB chip RAM to memory list
302	lea $210000,a1
303	; do not add if RAM detected already
304	jsr -$216(a6) ; TypeOfMem
305	tst.l d0
306	bne.s FSIN_chip_done
307	move.w #$FF80,d0
308	bsr.w getrtbase
309	jsr (a0)
310	move.l d4,d1
311	moveq #-10,d2
312	move.l #$200000,a0
313	sub.l a0,d0
314	bcs.b FSIN_chip_done
315	beq.b FSIN_chip_done
316	sub.l a1,a1
317	jsr -618(a6) ; AddMemList
318FSIN_chip_done
319	rts
320	EREM
321
322createproc
323	movem.l d2-d4/a2/a6,-(sp)
324	move.l 4.w,a6
325	move.l d0,d2
326	move.l d1,d4
327	move.l a1,d3
328	move.l a0,a2
329	lea doslibname(pc),a1
330	moveq #0,d0
331	jsr -$0228(a6) ; OpenLibrary
332	tst.l d0
333	beq.s .noproc
334	move.l d0,a6
335	move.l a2,d1
336	lsr.l #2,d3
337	jsr -$08a(a6) ; CreateProc
338	move.l a6,a1
339	move.l 4.w,a6
340	jsr -$019e(a6); CloseLibrary
341.noproc
342	movem.l (sp)+,d2-d4/a2/a6
343	rts
344
345	; this is getting ridiculous but I don't see any other solutions..
346fsmounttask
347.fsm1	move.l 4.w,a6
348	moveq #0,d0
349	bset #13,d0 ; SIGBREAK_CTRL_D
350	jsr -$013e(a6) ;Wait
351	lea fsprocname(pc),a0
352	lea mountproc(pc),a1
353	moveq #15,d0
354	move.l #8000,d1
355	bsr.w createproc
356	bra.s .fsm1
357
358	; dummy process here because can't mount devices with ADNF_STARTPROC from task..
359	; (AddDosNode() internally calls GetDeviceProc() which accesses ExecBase->ThisTask->pr_GlobVec)
360	cnop 0,4
361	dc.l 16
362mountproc
363	dc.l 0
364	moveq #2,d1
365	move.w #$FF48,d0 ; get new unit number
366	bsr.w getrtbase
367	jsr (a0)
368	move.l d0,d1
369	bmi.s .out
370	bsr.w addfsonthefly
371.out	moveq #0,d0
372	rts
373
374exter_data:
375exter_server:
376	movem.l a2,-(sp)
377	move.w #$FF50,d0 ; exter_int_helper
378	bsr.w getrtbase
379	moveq.l #0,d0
380	jsr (a0)
381	tst.l d0
382	beq.w exter_server_exit
383	; This is the hard part - we have to send some messages.
384	move.l 4.w,a6
385EXTS_loop:
386	move.w #$FF50,d0 ; exter_int_helper
387	bsr.w getrtbase
388	moveq.l #2,d0
389	jsr (a0)
390	cmp.w #1,d0
391	blt.w EXTS_done
392	bgt.b EXTS_signal_reply
393	jsr -366(a6) ; PutMsg
394	bra.b EXTS_loop
395EXTS_signal_reply:
396	cmp.w #2,d0
397	bgt.b EXTS_reply
398	move.l d1,d0
399	jsr -$144(a6)	; Signal
400	bra.b EXTS_loop
401EXTS_reply:
402	cmp.w #3,d0
403	bgt.b EXTS_cause
404	jsr -$17a(a6)   ; ReplyMsg
405	bra.b EXTS_loop
406EXTS_cause:
407	cmp.w #4,d0
408	bgt.b EXTS_notificationhack
409	jsr -$b4(a6)	; Cause
410	bra.b EXTS_loop
411EXTS_notificationhack:
412	cmp.w #5,d0
413	bgt.b EXTS_done
414	movem.l a0-a1,-(sp)
415	moveq #38,d0
416	move.l #65536+1,d1
417	jsr AllocMem(a6)
418	movem.l (sp)+,a0-a1
419	move.l d0,a2
420	move.b #8,8(a2)
421	move.l a0,14(a2)
422	move.w #38,18(a2)
423	move.l #NOTIFY_CLASS,20(a2)
424	move.w #NOTIFY_CODE,24(a2)
425	move.l a1,26(a2)
426	move.l 16(a1),a0
427	move.l a2,a1
428	jsr -366(a6) ; PutMsg
429	bra.w EXTS_loop
430EXTS_done:
431	move.w #$FF50,d0 ;exter_int_helper
432	bsr.w getrtbase
433	moveq.l #4,d0
434	jsr (a0)
435	moveq.l #1,d0 ; clear Z - it was for us.
436exter_server_exit:
437	movem.l (sp)+,a2
438	rts
439
440heartbeatvblank:
441	movem.l d0-d1/a0-a2,-(sp)
442
443	move.w #$FF38,d0
444	moveq #18,d1
445	bsr.w getrtbase
446	jsr (a0)
447	move.l d0,a2
448
449	moveq #22,d0
450	move.l #65536+1,d1
451	jsr AllocMem(a6)
452	move.l d0,a1
453
454	move.b #2,8(a1) ;NT_INTERRUPT
455	move.b #-10,9(a1) ;priority
456	lea kaname(pc),a0
457	move.l a0,10(a1)
458	lea kaint(pc),a0
459	move.l a0,18(a1)
460	move.l a2,14(a1)
461	moveq #5,d0 ;INTB_VERTB
462	jsr -$00a8(a6)
463
464	movem.l (sp)+,d0-d1/a0-a2
465	rts
466
467kaint:
468	addq.l #1,(a1)
469	moveq #0,d0
470	rts
471
472setup_exter:
473	movem.l d0-d1/a0-a1,-(sp)
474	bsr.w residenthack
475	moveq.l #26,d0
476	move.l #$10001,d1
477	jsr AllocMem(a6)
478	move.l d0,a1
479	lea.l exter_name(pc),a0
480	move.l a0,10(a1)
481	lea.l exter_data(pc),a0
482	move.l a0,14(a1)
483	lea.l exter_server(pc),a0
484	move.l a0,18(a1)
485	move.w #$0214,8(a1)
486	moveq.l #3,d0
487	jsr -168(a6) ; AddIntServer
488
489	bsr.w heartbeatvblank
490
491	move.w #$FF38,d0
492	moveq #4,d1
493	bsr.w getrtbase
494	jsr (a0)
495	tst.l d0
496	beq.s .nomh
497	bsr.w mousehack_init
498.nomh
499	movem.l (sp)+,d0-d1/a0-a1
500	rts
501
502addfs: ; a0 = first hunk, a1 = parmpacket
503	movem.l d0-d1/a0-a3/a6,-(sp)
504	move.l 4.w,a6
505	move.l a0,a2
506	move.l a1,a3
507	move.l #62+128,d0 ; sizeof(FileSysEntry) + patchflags;
508	move.l #$10001,d1
509	jsr -198(a6)
510	move.l d0,a0
511	moveq #0,d0
512	lea PP_FSHDSTART(a3),a1
513af1	move.b 0(a1,d0.w),14(a0,d0.w)
514	addq.w #1,d0
515	cmp.w #140,d0
516	bne.s af1
517	move.l a2,d0
518	lsr.l #2,d0
519	move.l d0,54(a0) ;seglist
520	move.l a0,a1
521	lea exter_name(pc),a0
522	move.l a0,10(a1) ; name
523	move.l PP_FSRES(a3),a0 ; FileSystem.resource
524	lea 18(a0),a0 ; fsr_FileSysEntries
525	jsr -$f0(a6) ;AddHead
526	movem.l (sp)+,d0-d1/a0-a3/a6
527	rts
528
529relocate: ;a0=pointer to executable, returns first segment in A0
530	movem.l d1-d7/a1-a6,-(sp)
531	move.l 4.w,a6
532	move.l a0,a2
533	cmp.l #$3f3,(a2)+
534	bne.w ree
535	addq.l #8,a2 ; skip name end and skip total hunks + 1
536	move.l 4(a2),d7 ; last hunk
537	sub.l (a2),d7 ; first hunk
538	addq.l #8,a2 ; skip hunk to load first and hunk to load last
539	addq.l #1,d7
540	move.l a2,a3
541	move.l d7,d0
542	add.l d0,d0
543	add.l d0,d0
544	add.l d0,a3
545	move.l a2,a4
546
547	; allocate hunks
548	sub.l a5,a5 ;prev segment
549	moveq #0,d6
550r15	move.l (a2),d2 ; hunk size (header)
551	moveq #1,d1
552	btst #30,d2 ; chip mem?
553	beq.s r2
554	bset #1,d1
555r2	bset #16,d1
556	lsl.l #2,d2
557	bne.s r17
558	clr.l (a2)+ ; empty hunk
559	bra.s r18
560r17	addq.l #8,d2 ; size + pointer to next hunk + hunk size
561	move.l d2,d0
562	jsr AllocMem(a6)
563	tst.l d0
564	beq.w ree
565	move.l d0,a0
566	move.l d2,(a0)+ ; store size
567	move.l a0,(a2)+ ; store new pointer
568	move.l a5,d1
569	beq.s r10
570	move.l a0,d0
571	lsr.l #2,d0
572	move.l d0,(a5)
573r10	move.l a0,a5
574r18	addq.l #1,d6
575	cmp.l d6,d7
576	bne.s r15
577
578	moveq #0,d6
579r3	move.l d6,d1
580	add.l d1,d1
581	add.l d1,d1
582	move.l 0(a4,d1.l),a0
583	addq.l #4,a0
584	move.l (a3)+,d3 ; hunk type
585	move.l (a3)+,d4 ; hunk size
586	lsl.l #2,d4
587	cmp.l #$3e9,d3 ;code
588	beq.s r4
589	cmp.l #$3ea,d3 ;data
590	bne.s r5
591r4
592	; code and data
593	move.l d4,d0
594r6	tst.l d0
595	beq.s r7
596	move.b (a3)+,(a0)+
597	subq.l #1,d0
598	bra.s r6
599r5
600	cmp.l #$3eb,d3 ;bss
601	bne.s ree
602
603r7 ; scan for reloc32 or hunk_end
604	move.l (a3)+,d3
605	cmp.l #$3ec,d3 ;reloc32
606	bne.s r13
607
608	; relocate
609	move.l d6,d1
610	add.l d1,d1
611	add.l d1,d1
612	move.l 0(a4,d1.l),a0 ; current hunk
613	addq.l #4,a0
614r11	move.l (a3)+,d0 ;number of relocs
615	beq.s r7
616	move.l (a3)+,d1 ;hunk
617	add.l d1,d1
618	add.l d1,d1
619	move.l 0(a4,d1.l),d3 ;hunk start address
620	addq.l #4,d3
621r9	move.l (a3)+,d2 ;offset
622	add.l d3,0(a0,d2.l)
623	subq.l #1,d0
624	bne.s r9
625	bra.s r11
626r13
627	cmp.l #$3f2,d3 ;end
628	bne.s ree
629
630	addq.l #1,d6
631	cmp.l d6,d7
632	bne.w r3
633
634	moveq #1,d7
635	move.l (a4),a0
636r0	move.l d7,d0
637	movem.l (sp)+,d1-d7/a1-a6
638	rts
639ree	sub.l a0,a0
640	moveq #0,d7
641	bra.s r0
642
643fsres:
644	movem.l d1/a0-a3/a6,-(sp)
645	move.l a0,a3
646	move.l 4.w,a6
647	lea $150(a6),a0 ;ResourceList
648	move.l (a0),a0 ;lh_Head
649fsres3
650	tst.l (a0) ;end of list?
651	beq.s fsres1
652	move.l 10(a0),a1 ;name
653	lea fsresname(pc),a2
654fsres5
655	move.b (a1)+,d0
656	move.b (a2)+,d1
657	cmp.b d1,d0
658	bne.s fsres2
659	tst.b d0
660	beq.s fsres4
661	bra.s fsres5
662fsres2
663	move.l (a0),a0
664	bra.s fsres3
665	; FileSystem.resource does not exist -> create it
666fsres1
667	moveq #32,d0 ; sizeof(FileSysResource)
668	move.l #$10001,d1
669	jsr AllocMem(a6)
670	move.l d0,a2
671	move.b #8,8(a2) ; NT_RESOURCE
672	lea fsresname(pc),a0
673	move.l a0,10(a2) ; node name
674	lea exter_name(pc),a0
675	move.l a0,14(a2) ; fsr_Creator
676	lea 18(a2),a0
677	move.l a0,(a0) ; NewList() fsr_FileSysEntries
678	addq.l #4,(a0)
679	move.l a0,8(a0)
680	lea $150(a6),a0 ; ResourceList
681	move.l a2,a1
682	jsr -$f6(a6) ; AddTail
683	move.l a2,a0
684	move.l a0,PP_FSRES_CREATED(a3)
685fsres4
686	move.l a0,d0
687	movem.l (sp)+,d1/a0-a3/a6
688	rts
689
690addvolumenode
691	movem.l d7/a6,-(sp)
692	move.l d0,d7
693	tst.b 32+44(a3)
694	beq.s .end ;empty volume string = empty drive
695	move.l 160(a3),a6
696	cmp.w #37, 20(a6)
697	bcs.s .prev37
698	moveq #(1<<1)+(1<<3)+(1<<2),d1 ;LDF_WRITE | LDF_VOLUMES | LDF_DEVICES
699	jsr -$29A(a6) ;AttemptLockDosList
700	and.l #~1,d0
701	beq.s .end
702	btst #0,d7
703	beq.s .nvol
704	lea 32(a3),a0
705	move.l a0,d1
706	jsr -$2A6(a6) ;AddDosEntry (Volume)
707.nvol	btst #1,d7
708	beq.s .ndev
709	tst.b 158(a3)
710	bne.s .ndev
711	st 158(a3)
712	move.l 180(a3),d1
713	jsr -$2A6(a6) ;AddDosEntry (Device)
714.ndev	moveq #(1<<1)+(1<<3)+(1<<2),d1 ;LDF_WRITE | LDF_VOLUMES | LDF_DEVICES
715	jsr -$294(a6) ;UnLockDosList
716	bra.s .end
717.prev37	move.l 4.w,a6
718	jsr -$0084(a6) ; Forbid
719	btst #0,d7
720	beq.s .nvol13
721	lea 32(a3),a0
722	bsr.w adddosentry13
723.nvol13	btst #1,d7
724	beq.s .ndev13
725	tst.b 158(a3)
726	bne.s .ndev13
727	st 158(a3)
728	move.l 180(a3),a0
729	bsr.w adddosentry13
730.ndev13	jsr -$008a(a6) ;Permit
731.end	movem.l (sp)+,d7/a6
732	rts
733
734remvolumenode
735	movem.l d7/a2/a6,-(sp)
736	move.l d0,d7
737	move.l 160(a3),a6
738	cmp.w #37,20(a6)
739	bcs.s .prev37
740	moveq #(1<<1)+(1<<3)+(1<<2),d1 ;LDF_WRITE | LDF_VOLUMES | LDF_DEVICES
741	jsr -$29A(a6) ;AttemptLockDosList
742	and.l #~1,d0
743	beq.s .end
744	btst #0,d7
745	beq.s .nvol
746	lea 32(a3),a0
747	move.l a0,d1
748	jsr -$2A0(a6) ;RemDosEntry (Volume)
749.nvol	btst #1,d7
750	beq.s .ndev
751	tst.b 158(a3)
752	beq.s .ndev
753	clr.b 158(a3)
754	move.l 180(a3),d1
755	jsr -$2A0(a6) ;RemDosEntry (Device)
756.ndev	moveq #(1<<1)+(1<<3)+(1<<2),d1 ;LDF_WRITE | LDF_VOLUMES | LDF_DEVICES
757	jsr -$294(a6) ;UnLockDosList
758	bra.s .end
759.prev37	move.l 4.w,a6
760	jsr -$0084(a6) ; Forbid
761	btst #0,d7
762	beq.s .nvol13
763	lea 32(a3),a0
764	bsr.w remdosentry13
765.nvol13	btst #1,d7
766	beq.s .ndev13
767	tst.b 158(a3)
768	beq.s .ndev13
769	clr.b 158(a3)
770	move.l 180(a3),a0
771	bsr.w remdosentry13
772.ndev13	jsr -$008a(a6) ;Permit
773.end	movem.l (sp)+,d7/a2/a6
774	rts
775
776adddosentry13:
777	move.l a0,a1
778	move.l 160(a3),a0
779	move.l 34(a0),a0 ; RootNode
780	move.l 24(a0),a0 ; DosInfo
781	add.l a0,a0
782	add.l a0,a0
783	move.l 4(a0),(a1) ; myentry->dl_Next = di_DevInfo
784	move.l a1,d0
785	lsr.l #2,d0
786	move.l d0,4(a0) ; di_DevInfo = myentry
787	rts
788
789remdosentry13:
790	move.l a0,a2
791	move.l 160(a3),a0
792	move.l 34(a0),a0 ; RootNode
793	move.l 24(a0),a0 ; DosInfo
794	add.l a0,a0
795	add.l a0,a0
796	move.l 4(a0),a1 ; DosInfo->di_DevInfo
797	add.l a1,a1
798	add.l a1,a1
799	cmp.l a2,a1
800	bne.s .pr2
801	; was first entry
802	move.l (a2),4(a0) ; di_DevInfo = myentry->dl_Next
803	bra.s .pr1
804.pr2	move.l a1,d0
805	beq.s .pr3
806	move.l (a1),d0 ; prevEntry->dl_Next
807	add.l d0,d0
808	add.l d0,d0
809	cmp.l d0,a2 ; next is our entry?
810	beq.s .pr3
811	move.l d0,a1
812	bra.s .pr2
813.pr3	move.l a1,d0
814	beq.s .pr1
815	move.l (a2),(a1) ; prevEntry->dl_Next = myentry->dl_Next
816.pr1	rts
817
818diskinsertremove:
819	movem.l d2/a2/a6,-(sp)
820	moveq #22,d2
821	sub.l d2,sp
822	move.l sp,a2
823	move.w d2,d1
824.l1	clr.b -1(a2,d1.w)
825	subq.w #1,d1
826	bne.s .l1
827	move.l 4.w,a6
828	moveq #15,d1 ;IECLASS_DISKREMOVED
829	tst.l d0
830	beq.s .l2
831	moveq #16,d1 ;IECLASS_DISKINSERTED
832.l2	move.b d1,4(a2) ;ie_Class
833	move.w #$0800,8(a2); ie_Qualifier=IEQUALIFIER_MULTIBROADCAST
834
835	move.l 164(a3),a1
836	move.w #11,28(a1) ;IND_WRITEEVENT
837	move.l #22,36(a1) ;sizeof(struct InputEvent)
838	move.l a2,40(a1)
839	move.b #1,30(a1) ;IOF_QUICK
840
841	move.l 168(a3),a1
842	move.w #10,28(a1) ;TR_GETSYSTIME
843	move.b #1,30(a1) ;IOF_QUICK
844	jsr -$01c8(a6) ;DoIO
845
846	move.l 168(a3),a1
847	move.l 32(a1),14(a2)
848	move.l 36(a1),18(a2)
849
850	move.l 164(a3),a1
851	jsr -$01c8(a6) ;DoIO
852
853	add.l d2,sp
854	movem.l (sp)+,d2/a2/a6
855	rts
856
857dodiskchange
858	tst.b d0
859	beq.s .eject
860	tst.b 32+44(a3)
861	bne.s .end
862	moveq #0,d0
863.dc2
864	tst.b 32+45(a3,d0.w)
865	beq.s .dc1
866	addq.b #1,d0
867	bra.s .dc2
868.dc1
869	move.b d0,32+44(a3)
870	beq.s .end
871	move.l d1,d0
872	bsr.w addvolumenode
873	moveq #1,d0
874	bsr.w diskinsertremove
875	bra.s .end
876.eject
877	tst.b 32+44(a3)
878	beq.s .end
879	clr.b 32+44(a3)
880	move.l d1,d0
881	bsr.w remvolumenode
882	moveq #0,d0
883	bsr.w diskinsertremove
884.end
885	rts
886
887action_inhibit
888	tst.l 20(a4) ;dp_Arg1
889	beq.s .add
890	moveq #0,d0
891	moveq #1,d1
892	bsr dodiskchange
893	rts
894.add
895	moveq #1,d0
896	moveq #3,d1
897	bsr dodiskchange
898	rts
899
900diskchange
901	move.b 172(a3),d0
902	bmi.s .nodisk
903	moveq #1,d0
904	moveq #3,d1
905	bsr dodiskchange
906	rts
907.nodisk
908	moveq #1,d1
909	cmp.b #-2,d0 ;remove device node?
910	bne.s .nod1
911	moveq #3,d1
912.nod1	moveq #0,d0
913	bsr dodiskchange
914	rts
915
916	; exall is complex, need to emulate eac_MatchString and/or eac_MatchFunc
917action_exall
918	move.l 36(a4),a0 ; dp_Arg5, struct ExAllControl
919	tst.l (a0)
920	beq.s .ex0
921	tst.l 8(a0) ; eac_MatchString
922	bne.s .ex1
923	tst.l 12(a0) ; eac_MatchFunc
924	bne.s .ex1
925.ex0	moveq #1,d0 ; no need to get more entries
926	rts ;nothing to do here
927.ex1:	movem.l d2-d7/a2-a6,-(sp)
928	move.l a0,a5
929	move.l 24(a4),a2 ;dp_Arg2, ExAllData
930	move.l (a5),d7 ; eac_Entries
931	moveq #0,d5 ; previous entry
932.ex4	tst.l d7
933	beq.s .ex3
934	move.l a2,d0
935	beq.s .ex3
936	moveq #0,d6
937	move.l 8(a5),d1 ; MatchString
938	beq.s .ex5
939	move.l 4(a2),d2 ; dir/file name
940	move.l 160(a3),a6 ; dosbase
941	jsr -$03cc(a6) ; MatchPatternNoCase
942	tst.l d0
943	bne.s .ex5
944	st d6
945.ex5	move.l 12(a5),d1 ; MatchFunc
946	beq.s .ex6
947	move.l d1,a0
948	move.l a2,a1
949	move.l a2,-(sp)
950	lea 32(a4),a2 ; dp_Arg4, Type
951	pea .pop(pc)
952	move.l 8(a0),-(sp)
953	rts
954.pop	move.l (sp)+,a2
955	tst.l d0
956	bne.s .ex6
957	st d6
958.ex6	tst.b d6
959	beq.s .ex7
960	; need to delete current entry.. this is not really the proper way..
961	move.l 4(a2),d0 ; pointer to filename (which is first address after structure)
962	sub.l a2,d0 ; copy this much data
963	tst.l (a2) ; delete last? (eac_Next)
964	bne.s .ex10
965	; need to clear previous eac_Next
966	move.l d5,d0
967	beq.s .ex8
968	move.l d0,a0
969	clr.l (a0)
970	bra.s .ex8
971.ex10	move.l (a2),a0
972	move.l a2,a1
973.ex9	move.l (a0)+,(a1)+
974	subq.l #4,d0
975	bpl.s .ex9
976.ex8	subq.l #1,(a5) ; eac_Entries
977	subq.l #1,d7
978	bra.s .ex4
979.ex7	move.l a2,d5
980	move.l (a2),a2 ; eac_Next
981	subq.l #1,d7
982	bra.s .ex4
983.ex3	movem.l (sp)+,d2-d7/a2-a6
984	move.l 36(a4),a0 ; dp_Arg5, struct ExAllControl
985	tst.l (a0) ; eac_Entries == 0 -> get more
986	rts
987
988	; mount harddrives, virtual or hdf
989
990make_dev: ; IN: A0 param_packet, D6: unit_no, D7: b0=autoboot,b1=onthefly,b2=v36+
991	; A4: expansionbase
992
993	bsr.w fsres
994	move.l d0,PP_FSRES(a0) ; pointer to FileSystem.resource
995	move.l a0,-(sp)
996	move.w #$FFEC,d0 ; filesys base
997	bsr.w getrtbase
998	move.l (a0),a5
999	move.w #$FF28,d0 ; fill in unit-dependent info (filesys_dev_storeinfo)
1000	bsr.w getrtbase
1001	move.l a0,a1
1002	move.l (sp)+,a0
1003	clr.l PP_FSSIZE(a0) ; filesystem size
1004	clr.l PP_FSPTR(a0) ; filesystem memory
1005	jsr (a1)
1006	; ret:0=virtual,1=hardfile,2=rdbhardfile,-1=hardfile-donotmount,-2=no more subunits
1007	move.l d0,d3
1008	cmp.w #-2,d3
1009	beq.w general_ret
1010
1011	;cmp.w #1,d3
1012	;bne.s mountalways
1013	; KS < V36: init regular hardfiles only if filesystem is loaded
1014	;btst #2,d7
1015	;bne.s mountalways ; >= 36
1016	;btst #1,d7
1017	;bne.w mountalways
1018
1019mountalways
1020	; allocate memory for loaded filesystem
1021	move.l PP_FSSIZE(a0),d0
1022	beq.s .nordbfs1
1023	bmi.s .nordbfs1
1024	move.l a0,-(sp)
1025	moveq #1,d1
1026	move.l 4.w,a6
1027	jsr  AllocMem(a6)
1028	move.l (sp)+,a0
1029	move.l d0,PP_FSPTR(a0)
1030.nordbfs1:
1031
1032	tst.l d3
1033	bpl.s do_mount
1034
1035	; do not mount but we might need to load possible custom filesystem(s)
1036	move.l a0,a1
1037	move.w #$FF20,d0 ; record in ui.startup (filesys_dev_remember)
1038	bsr.w getrtbase
1039	jsr (a0)
1040	bra.s dont_mount
1041
1042do_mount:
1043	move.l a4,a6
1044	move.l a0,-(sp)
1045	jsr -144(a6) ; MakeDosNode()
1046	move.l (sp)+,a0 ; parmpacket
1047	move.l a0,a1
1048	move.l d0,a3 ; devicenode
1049	move.w #$FF20,d0 ; record in ui.startup (filesys_dev_remember)
1050	bsr.w getrtbase
1051	jsr (a0)
1052	moveq #0,d0
1053	move.l d0,8(a3)          ; dn_Task
1054	move.l d0,16(a3)         ; dn_Handler
1055	move.l d0,32(a3)         ; dn_SegList
1056
1057dont_mount:
1058	move.l PP_FSPTR(a1),a0
1059	tst.l PP_FSSIZE(a1)
1060	beq.s nordbfs3
1061	; filesystem needs relocation?
1062	move.l a0,d0
1063	beq.s nordbfs2
1064	bsr.w relocate
1065	movem.l d0/a0-a1,-(sp)
1066	move.l PP_FSSIZE(a1),d0
1067	move.l PP_FSPTR(a1),a1
1068	move.l 4.w,a6
1069	jsr FreeMem(a6)
1070	movem.l (sp)+,d0/a0-a1
1071	clr.l PP_FSSIZE(a1)
1072	move.l a0,PP_FSPTR(a1)
1073	tst.l d0
1074	beq.s nordbfs2
1075nordbfs3:
1076	tst.l PP_ADDTOFSRES(a1)
1077	beq.s nordbfs2
1078	bsr.w addfs
1079nordbfs2:
1080
1081	tst.l d3
1082	bmi.w general_ret
1083
1084	move.w #$FF18,d0 ; update dn_SegList if needed (filesys_dev_bootfilesys)
1085	bsr.w getrtbase
1086	jsr (a0)
1087
1088	move.l d3,d0
1089	move.b 79(a1),d3 ; bootpri
1090	tst.l d0
1091	bne.b MKDV_doboot ; not directory harddrive?
1092
1093MKDV_is_filesys:
1094	move.l #6000,20(a3)     ; dn_StackSize
1095	lea.l our_seglist(pc),a0
1096	move.l a0,d0
1097	lsr.l  #2,d0
1098	move.l d0,32(a3)        ; dn_SegList
1099	moveq #-1,d0
1100	move.l d0,36(a3)       ; dn_GlobalVec
1101
1102MKDV_doboot:
1103	btst #0,d7
1104	beq.b MKDV_noboot
1105	cmp.b #-128,d3
1106	beq.s MKDV_noboot
1107
1108	move.l 4.w,a6
1109	moveq #20,d0
1110	move.l #65536+1,d1
1111	jsr  AllocMem(a6)
1112	move.l d0,a1 ; bootnode
1113	move.w #$1000,d0
1114	or.b d3,d0
1115	move.w d0,8(a1)
1116	move.l $104(a5),10(a1) ; filesys_configdev
1117	move.l a3,16(a1) ; devicenode
1118	lea.l  74(a4),a0 ; MountList
1119	jsr -$0084(a6) ;Forbid
1120	jsr  -270(a6) ; Enqueue()
1121	jsr -$008a(a6) ;Permit
1122	moveq #0,d0
1123	rts
1124
1125MKDV_noboot:
1126	move.l a1,a2 ; bootnode
1127	move.l a3,a0 ; parmpacket
1128	moveq #0,d1
1129	move.l d1,a1
1130	btst #1,d7
1131	beq.s .nob
1132	btst #2,d7
1133	beq.s .nob
1134	moveq #1,d1 ; ADNF_STARTPROC (v36+)
1135.nob
1136	moveq #-128,d0
1137	move.l a4,a6 ; expansion base
1138	jsr  -150(a6) ; AddDosNode
1139	btst #1,d7
1140	beq.s .noproc
1141	btst #2,d7
1142	bne.s .noproc
1143
1144	; 1.3 and need to start immediately
1145	move.l (a2),a0 ; 'dh0' but need 'dh0:'
1146	moveq #2,d2
1147.devpr1	addq.l #1,d2
1148	tst.b -3(a0,d2.l)
1149	bne.s .devpr1
1150	move.l 4.w,a6
1151	move.l d2,d0
1152	moveq #1,d1
1153	jsr AllocMem(a6)
1154	tst.l d0
1155	beq.s .noproc
1156	move.l (a2),a0
1157	move.l d0,a2
1158	move.l a2,a1
1159.devpr2	move.b (a0)+,(a1)+
1160	bne.s .devpr2
1161	move.b #':',-1(a1)
1162	clr.b (a1)
1163	move.l 4.w,a6
1164	lea doslibname(pc),a1
1165	moveq #0,d0
1166	jsr -$0228(a6) ; OpenLibrary
1167	move.l d0,a6
1168	move.l a2,d1
1169	jsr -$0AE(a6) ; DeviceProc (start fs handler, ignore return code)
1170	move.l a6,a1
1171	move.l 4.w,a6
1172	jsr -$019e(a6); CloseLibrary
1173	move.l a2,a1
1174	move.l d2,d0
1175	jsr FreeMem(a6)
1176.noproc
1177	moveq #0,d0
1178	rts
1179
1180addfsonthefly ; d1 = fs index
1181	movem.l d2-d7/a2-a6,-(sp)
1182	move.l d1,d6
1183	moveq #2+4,d7
1184	move.l 4.w,a6
1185	lea.l explibname(pc),a1 ; expansion lib name
1186	moveq #36,d0
1187	jsr  -552(a6) ; OpenLibrary
1188	tst.l d0
1189	bne.s .newks
1190	bclr #2,d7
1191	lea.l explibname(pc),a1 ; expansion lib name
1192	moveq #0,d0
1193	jsr  -552(a6) ; OpenLibrary
1194.newks	move.l d0,a4
1195	move.l #PP_TOTAL,d0
1196	move.l #$10001,d1
1197	jsr AllocMem(a6)
1198	move.l d0,a0  ; param packet
1199	tst.l d0
1200	beq.s .nomem
1201	move.l a4,PP_EXPLIB(a0)
1202.next	movem.l a0/a4/a6,-(sp)
1203	bsr.w make_dev
1204	movem.l (sp)+,a0/a4/a6
1205	cmp.l #-2,d0
1206	beq.s .nomsub
1207	swap d6
1208	addq.w #1,d6
1209	swap d6
1210	bra.s .next
1211.nomsub	move.l a0,a1
1212	move.l #PP_TOTAL,d0
1213	jsr FreeMem(a6)
1214.nomem	move.l a4,a1
1215	jsr -414(a6) ; CloseLibrary
1216	movem.l (sp)+,d2-d7/a2-a6
1217	rts
1218
1219clockreset:
1220	move.w #$ff58,d0 ; fsmisc_helper
1221	bsr.w getrtbase
1222	moveq #3,d0 ; get time
1223	jsr (a0)
1224	move.l 168(a3),a1
1225	move.l d0,32(a1)
1226	beq.s .cr
1227	moveq #0,d0
1228	move.l d0,36(a1)
1229	move.w #11,28(a1) ;TR_SETSYSTIME
1230	move.b #1,30(a1) ;IOF_QUICK
1231	jsr -$01c8(a6) ;DoIO
1232.cr	rts
1233
1234filesys_mainloop:
1235	move.l 4.w,a6
1236	sub.l a1,a1
1237	jsr -294(a6) ; FindTask
1238	move.l d0,a0
1239	lea.l $5c(a0),a5 ; pr_MsgPort
1240
1241	; Open DOS library
1242	lea.l doslibname(pc),a1
1243	moveq.l #0,d0
1244	jsr -552(a6) ; OpenLibrary
1245	move.l d0,a2
1246
1247	; Allocate some memory. Usage:
1248	; 0: lock chain
1249	; 4: command chain
1250	; 8: second thread's lock chain
1251	; 12: dummy message
1252	; 32: the volume (44+80+1 bytes)
1253	; 157: mousehack started-flag
1254	; 158: device node on/off status
1255	; 160: dosbase
1256	; 164: input.device ioreq (disk inserted/removed input message)
1257	; 168: timer.device ioreq
1258	; 172: disk change from host
1259	; 173: clock reset
1260	; 176: my task
1261	; 180: device node
1262	move.l #12+20+(80+44+1)+(1+3)+4+4+4+(1+3)+4+4,d0
1263	move.l #$10001,d1 ; MEMF_PUBLIC | MEMF_CLEAR
1264	jsr AllocMem(a6)
1265	move.l d0,a3
1266	moveq.l #0,d6
1267	move.l d6,(a3)
1268	move.l d6,4(a3)
1269	move.l d6,8(a3)
1270	move.l a2,160(a3)
1271	st 158(a3)
1272
1273	sub.l a1,a1
1274	jsr -294(a6) ; FindTask
1275	move.l d0,176(a3)
1276
1277	lea inp_dev(pc),a0
1278	moveq #0,d0
1279	moveq #0,d1
1280	bsr.w allocdevice
1281	move.l d0,164(a3)
1282	lea tim_dev(pc),a0
1283	moveq #0,d0
1284	moveq #0,d1
1285	bsr.w allocdevice
1286	move.l d0,168(a3)
1287
1288	moveq.l #0,d5 ; No commands queued.
1289
1290	; Fetch our startup packet
1291	move.l a5,a0
1292	jsr -384(a6) ; WaitPort
1293	move.l a5,a0
1294	jsr -372(a6) ; GetMsg
1295	move.l d0,a4
1296	move.l 10(a4),d3 ; ln_Name
1297	move.w #$FF40,d0 ; startup_handler
1298	bsr.w getrtbase
1299	moveq.l #0,d0
1300	jsr (a0)
1301	move.l d0,d2
1302
1303	moveq #1,d0
1304	bsr.w addvolumenode
1305
1306	btst #1,d2
1307	beq.s .nonotif
1308	moveq #1,d0
1309	bsr.w diskinsertremove
1310.nonotif
1311
1312	bra.w FSML_Reply
1313
1314	; We abuse some of the fields of the message we get. Offset 0 is
1315	; used for chaining unprocessed commands, and offset 1 is used for
1316	; indicating the status of a command. 0 means the command was handed
1317	; off to some UAE thread and did not complete yet, 1 means we didn't
1318	; even hand it over yet because we were afraid that might blow some
1319	; pipe limit, and -1 means the command was handed over and has completed
1320	; processing by now, so it's safe to reply to it.
1321
1322FSML_loop:
1323
1324	move.l a5,a0
1325	jsr -372(a6) ; GetMsg
1326	move.l d0,a4
1327	tst.l d0
1328	bne.s .msg
1329
1330	moveq #0,d0
1331	move.b 15(a5),d1 ;mp_SigBit
1332	bset d1,d0
1333	bset #13,d0 ; SIGBREAK_CTRL_D
1334	jsr -$013e(a6) ;Wait
1335.msg
1336	; SIGBREAK_CTRL_D checks
1337	; clock reset
1338	tst.b 173(a3)
1339	beq.s .noclk
1340	bsr.w clockreset
1341	clr.b 173(a3)
1342.noclk
1343	; disk change notification from native code
1344	tst.b 172(a3)
1345	beq.s .nodc
1346	; call filesys_media_change_reply (pre)
1347	move.w #$ff58,d0 ; fsmisc_helper
1348	bsr.w getrtbase
1349	moveq #1,d0 ; filesys_media_change_reply
1350	jsr (a0)
1351	tst.l d0
1352	beq.s .nodc2
1353	bsr.w diskchange
1354.nodc2
1355	clr.b 172(a3)
1356	; call filesys_media_change_reply (post)
1357	move.w #$ff58,d0 ; fsmisc_helper
1358	bsr.w getrtbase
1359	moveq #2,d0 ; filesys_media_change_reply
1360	jsr (a0)
1361.nodc
1362	move.l a4,d0
1363	beq.s nonnotif
1364
1365	; notify reply?
1366	cmp.w #38, 18(a4)
1367	bne.s nonnotif
1368	cmp.l #NOTIFY_CLASS, 20(a4)
1369	bne.s nonnotif
1370	cmp.w #NOTIFY_CODE, 24(a4)
1371	bne.s nonnotif
1372	move.l 26(a4),a0 ; NotifyRequest
1373	move.l 12(a0),d0 ; flags
1374	and.l #NRF_WAIT_REPLY|NRF_MAGIC,d0
1375	cmp.l #NRF_WAIT_REPLY|NRF_MAGIC,d0
1376	bne.s nonoti
1377	and.l #~NRF_MAGIC,12(a0)
1378	move.l 16(a0),a0
1379	move.l a4,a1
1380	move.b #8,(a1)
1381	jsr -366(a6) ; PutMsg
1382	bra.w FSML_loop
1383nonoti
1384	move.l a4,a1
1385	moveq #38,d0
1386	jsr FreeMem(a6)
1387	bra.w FSML_loop
1388
1389nonnotif
1390	moveq #-2,d2 ; lock timeout "done" value
1391	move.l a4,d0
1392	beq.s FSML_check_queue_other
1393	move.l 10(a4),d3 ; ln_Name
1394	bne.b FSML_FromDOS
1395	moveq #-1,d2 ; normal "done" value
1396
1397	; It's a dummy packet indicating that some queued command finished.
1398	move.w #$FF50,d0 ; exter_int_helper
1399	bsr.w getrtbase
1400	moveq.l #1,d0
1401	jsr (a0)
1402FSML_check_queue_other:
1403	; Go through the queue and reply all those that finished.
1404	lea.l 4(a3),a2
1405	move.l (a2),a0
1406FSML_check_old:
1407	move.l a0,d0
1408	beq.w FSML_loop
1409	move.l (a0),a1
1410	move.l d0,a0
1411	; This field may be accessed concurrently by several UAE threads.
1412	; This _should_ be harmless on all reasonable machines.
1413	move.l 4(a0),d0
1414	cmp.l d0,d2
1415	bne.b FSML_check_next
1416	movem.l a0/a1,-(a7)
1417	move.l 10(a0),a4
1418	bsr.b ReplyOne
1419	subq.l #1,d5  ; One command less in the queue
1420	movem.l (a7)+,a0/a1
1421	move.l a1,(a2)
1422	move.l a1,a0
1423	bra.b FSML_check_old
1424FSML_check_next:
1425	move.l a0,a2
1426	move.l a1,a0
1427	bra.b FSML_check_old
1428
1429FSML_FromDOS:
1430	; Limit the number of outstanding started commands. We can handle an
1431	; unlimited number of unstarted commands.
1432	cmp.l #20,d5
1433	bcs  FSML_DoCommand
1434	; Too many commands queued.
1435	moveq.l #1,d0
1436	move.l d0,4(a4)
1437	bra.b FSML_Enqueue
1438
1439FSML_DoCommand:
1440	bsr.b LockCheck  ; Make sure there are enough locks for the C code to grab.
1441	move.w #$FF30,d0 ; filesys_handler
1442	bsr.w getrtbase
1443	jsr (a0)
1444	tst.l d0
1445	beq.b FSML_Reply
1446	; The command did not complete yet. Enqueue it and increase number of
1447	; queued commands
1448	; The C code already set 4(a4) to 0
1449	addq.l #1,d5
1450FSML_Enqueue:
1451	move.l 4(a3),(a4)
1452	move.l a4,4(a3)
1453	bra.w FSML_loop
1454
1455FSML_Reply:
1456	move.l d3,a4
1457	bsr.b ReplyOne
1458	bra.w FSML_loop
1459
1460ReplyOne:
1461	cmp.l #31,8(a4) ;ACTION_INHIBIT?
1462	bne.s FSML_ReplyOne2
1463	bsr.w action_inhibit
1464FSML_ReplyOne2:
1465	cmp.l #1033,8(a4) ;ACTION_EXAMINE_ALL
1466	bne.s FSML_ReplyOne3
1467.exaretry:
1468	bsr.w action_exall
1469	bne.s FSML_ReplyOne3
1470	; Arghh.. we need more entries. (some buggy programs fail if eac_Entries = 0 with continue enabled)
1471	move.w #$ff58,d0 ; fsmisc_helper
1472	bsr.w getrtbase
1473	moveq #0,d0 ; exall
1474	jsr (a0)
1475	bra.s .exaretry
1476
1477FSML_ReplyOne3:
1478	move.l (a4),a1  ; dp_Link
1479	move.l 4(a4),a0 ; dp_Port
1480	move.l a5,4(a4)
1481	jmp -366(a6) ; PutMsg
1482
1483; ugly code to avoid calling AllocMem / FreeMem from native C code.
1484; We keep a linked list of 3 locks. In theory, only one should ever
1485; be used. Before handling every packet, we check that the list has the
1486; right length.
1487
1488LockCheck:
1489	move.l d5,-(a7)
1490	moveq.l #-4,d5  ; Keep three locks
1491	move.l (a3),a2
1492	move.l a2,d7
1493LKCK_Loop:
1494	move.l a2,d1
1495	beq LKCK_ListEnd
1496	addq.l #1,d5
1497	beq.b LKCK_TooMany
1498	move.l a2,a1
1499	move.l (a2),a2
1500	bra.b LKCK_Loop
1501LKCK_ListEnd:
1502	addq.l #1,d5
1503	beq.b LKCK_ret
1504	move.l d7,a2
1505	moveq.l #24,d0 ; sizeof Lock is 20, 4 for chain
1506	moveq.l #1,d1 ; MEMF_PUBLIC
1507	jsr AllocMem(a6)
1508	addq.w #1,d6
1509	move.l d0,a2
1510	move.l d7,(a2)
1511	move.l a2,d7
1512	bra.b LKCK_ListEnd
1513LKCK_TooMany:
1514	move.l (a2),d0 ; We have too many, but we tolerate that to some extent.
1515	beq.b LKCK_ret
1516	move.l d0,a0
1517	move.l (a0),d0
1518	beq.b LKCK_ret
1519	move.l d0,a0
1520	move.l (a0),d0
1521	beq.b LKCK_ret
1522
1523	moveq.l #0,d0 ; Now we are sure that we really have too many. Delete some.
1524	move.l d0,(a1)
1525LKCK_TooManyLoop:
1526	move.l a2,a1
1527	move.l (a1),a2
1528	moveq.l #24,d0
1529	jsr FreeMem(a6)
1530	add.l #$10000,d6
1531	move.l a2,d0
1532	bne.b LKCK_TooManyLoop
1533LKCK_ret:
1534	move.l d7,(a3)
1535	move.l (a7)+,d5
1536	rts
1537
1538; mouse hack
1539
1540newlist:
1541	move.l a0,(a0)
1542	addq.l #4,(a0)
1543	clr.l 4(a0)
1544	move.l a0,8(a0)
1545	rts
1546
1547createport:
1548	movem.l d2/a2/a6,-(sp)
1549	move.l 4.w,a6
1550	moveq #-1,d0
1551	jsr -$014a(a6) ;AllocSignal
1552	sub.l a0,a0
1553	move.l d0,d2
1554	bmi.s .f
1555	moveq #34,d0
1556	move.l #65536+1,d1
1557	jsr AllocMem(a6)
1558	sub.l a0,a0
1559	move.l d0,a2
1560	tst.l d0
1561	beq.s .f
1562	move.b #4,8(a2) ;NT_MSGPORT
1563	move.b d2,15(a2)
1564	sub.l a1,a1
1565	jsr -$0126(a6) ;FindTask
1566	move.l d0,16(a2)
1567	lea 20(a2),a0
1568	bsr.w newlist
1569	move.l a2,a0
1570.f	move.l a0,d0
1571	movem.l (sp)+,d2/a2/a6
1572	rts
1573
1574createio:
1575	movem.l d2/a2/a6,-(sp)
1576	move.l 4.w,a6
1577	tst.l d0
1578	beq.s .f
1579	move.l d0,a2
1580	move.l d1,d2
1581	bne.s .ci
1582	moveq #48,d2
1583.ci
1584	move.l d2,d0
1585	move.l #65536+1,d1
1586	jsr AllocMem(a6)
1587	move.l d0,a0
1588	move.b #10,8(a0) ;NT_MESSAGE
1589	move.w d2,18(a0)
1590	move.l a2,14(a0)
1591.f	tst.l d0
1592	movem.l (sp)+,d2/a2/a6
1593	rts
1594
1595allocdevice
1596	movem.l d2-d3/a2/a6,-(sp)
1597	move.l a0,a2
1598	move.l d0,d2
1599	move.l d1,d3
1600	move.l 4.w,a6
1601	bsr.w createport
1602	move.l d3,d1
1603	bsr.w createio
1604	beq.s .f
1605	move.l a2,a0
1606	move.l d0,a1
1607	move.l d0,a2
1608	move.l d2,d0
1609	moveq #0,d1
1610	jsr -$01bc(a6) ;OpenDevice
1611	move.l d0,d1
1612	moveq #0,d0
1613	tst.l d1
1614	bne.s .f
1615	move.l a2,d0
1616.f	tst.l d0
1617	movem.l (sp)+,d2-d3/a2/a6
1618	rts
1619
1620createtask:
1621	movem.l d2/d3/d4/a2/a3/a6,-(sp)
1622	move.l 4.w,a6
1623	move.l d0,d4
1624	move.l a0,d2
1625	move.l a1,d3
1626	move.l #92+2048,d0
1627	move.l #65536+1,d1
1628	jsr AllocMem(a6)
1629	tst.l d0
1630	beq .f
1631	move.l d0,a2
1632	move.b #1,8(a2) ;NT_TASK
1633	move.b d4,9(a2) ; priority
1634	move.l d2,10(a2)
1635	lea 92(a2),a3
1636	move.l a3,58(a2)
1637	lea 2048(a3),a3
1638	move.l a3,62(a2)
1639	move.l a3,54(a2)
1640	move.l a2,a1
1641	move.l d3,a2
1642	sub.l a3,a3
1643	move.l a1,d2
1644	jsr -$011a(a6) ;AddTask
1645	move.l d2,d0
1646.f	movem.l (sp)+,d2/d3/d4/a2/a3/a6
1647	rts
1648
1649; mousehack/tablet
1650
1651mousehack_init:
1652	lea mhname(pc),a0
1653	lea mousehack_task(pc),a1
1654	moveq #19,d0
1655	bsr createtask
1656	rts
1657
1658mhdoiotimer:
1659	move.l MH_TM(a5),a1
1660	move.w #10,28(a1) ;TR_GETSYSTIME
1661	move.b #1,30(a1) ;IOF_QUICK
1662	jsr -$01c8(a6) ;DoIO
1663	move.l MH_TM(a5),a1
1664	move.l 32(a1),14(a2)
1665	move.l 36(a1),18(a2)
1666	move.l MH_IO(a5),a1
1667	move.b #1,30(a1) ;IOF_QUICK
1668	jsr -$01c8(a6) ;DoIO
1669	rts
1670mhdoio:
1671	clr.l 14(a2)
1672	clr.l 18(a2)
1673	move.l MH_IO(a5),a1
1674	move.b #1,30(a1) ;IOF_QUICK
1675	jsr -$01c8(a6) ;DoIO
1676	rts
1677
1678MH_E = 0
1679MH_CNT = 2
1680MH_MAXX = 4
1681MH_MAXY = 6
1682MH_MAXZ = 8
1683MH_X = 10
1684MH_Y = 12
1685MH_Z = 14
1686MH_RESX = 16
1687MH_RESY = 18
1688MH_MAXAX = 20
1689MH_MAXAY = 22
1690MH_MAXAZ = 24
1691MH_AX = 26
1692MH_AY = 28
1693MH_AZ = 30
1694MH_PRESSURE = 32
1695MH_BUTTONBITS = 34
1696MH_INPROXIMITY = 38
1697MH_ABSX = 40
1698MH_ABSY = 42
1699MH_DATA_SIZE = 44
1700
1701MH_INT = 0
1702MH_FOO = (MH_INT+22)
1703MH_FOO_CNT = 0
1704MH_FOO_BUTTONS = 4
1705MH_FOO_TASK = 8
1706MH_FOO_MASK = 12
1707MH_FOO_EXECBASE = 16
1708MH_FOO_INTBASE = 20
1709MH_FOO_GFXBASE = 24
1710MH_FOO_DELAY = 28
1711MH_FOO_DIMS_X = 32
1712MH_FOO_DIMS_Y = 36
1713MH_FOO_VPXY = 40
1714MH_FOO_MOFFSET = 44
1715MH_FOO_ALIVE = 48
1716MH_FOO_LIMITCNT = 52
1717MH_FOO_DIMS = 56
1718MH_FOO_DISP = (MH_FOO_DIMS+88)
1719MH_FOO_PREFS = (MH_FOO_DISP+48)
1720MH_FOO_SIZE = (MH_FOO_PREFS+102)
1721
1722PREFS_SIZE = 102
1723
1724MH_IEV = (MH_FOO+MH_FOO_SIZE) ;InputEvent
1725MH_IEH = (MH_IEV+22) ;InputHandler (Interrupt)
1726MH_IEPT = (MH_IEH+22) ;IEPointerTable/IENewTablet
1727MH_IENTTAGS = (MH_IEPT+32) ;space for ient_TagList
1728MH_IO = (MH_IENTTAGS+16*4*2)
1729MH_TM = (MH_IO+4)
1730MH_DATA = (MH_TM+4)
1731MH_END = (MH_DATA+MH_DATA_SIZE)
1732
1733MH_MOUSEHACK = 0
1734MH_TABLET = 1
1735MH_ACTIVE = 7
1736
1737TAG_USER   equ $80000000
1738TABLETA_Dummy		EQU	TAG_USER+$3A000
1739TABLETA_TabletZ		EQU	TABLETA_Dummy+$01
1740TABLETA_RangeZ		EQU	TABLETA_Dummy+$02
1741TABLETA_AngleX		EQU	TABLETA_Dummy+$03
1742TABLETA_AngleY		EQU	TABLETA_Dummy+$04
1743TABLETA_AngleZ		EQU	TABLETA_Dummy+$05
1744TABLETA_Pressure	EQU	TABLETA_Dummy+$06
1745TABLETA_ButtonBits	EQU	TABLETA_Dummy+$07
1746TABLETA_InProximity	EQU	TABLETA_Dummy+$08
1747TABLETA_ResolutionX	EQU	TABLETA_Dummy+$09
1748TABLETA_ResolutionY	EQU	TABLETA_Dummy+$0A
1749
1750
1751DTAG_DISP EQU $80000000
1752DTAG_DIMS EQU $80001000
1753DTAG_MNTR EQU $80002000
1754DTAG_NAME EQU $80003000
1755
1756getgfxlimits:
1757	movem.l d0-d4/a0-a6,-(sp)
1758	move.l a0,a5
1759	sub.l a2,a2
1760	sub.l a3,a3
1761	sub.l a4,a4
1762	moveq #0,d4
1763
1764	move.l MH_FOO_GFXBASE(a5),a6
1765	move.l MH_FOO_INTBASE(a5),a0
1766	move.l 60(a0),d0 ;FirstScreen
1767	beq.s .end
1768
1769	move.l d0,a0
1770	lea 44(a0),a0 ;ViewPort
1771	move.l a0,a4
1772	jsr -$318(a6) ;GetVPModeID
1773	moveq #-1,d1
1774	moveq #-1,d2
1775	cmp.l d0,d1
1776	beq.s .end
1777	move.l d0,d3
1778
1779	; mouse offset
1780	move.l MH_FOO_INTBASE(a5),a6
1781	lea MH_FOO_PREFS(a5),a0
1782	moveq #PREFS_SIZE,d0
1783	jsr -$84(a6) ;GetPrefs
1784	lea MH_FOO_PREFS(a5),a0
1785	move.w 100(a0),d4
1786	move.l MH_FOO_GFXBASE(a5),a6
1787
1788  ; Text Overscan area needed
1789	sub.l a0,a0
1790	lea MH_FOO_DIMS(a5),a1
1791	moveq #0,d0
1792	move.w #88,d0
1793	move.l #DTAG_DIMS,d1
1794	move.l d3,d2
1795	jsr -$2f4(a6) ;GetDisplayInfoData
1796	moveq #-1,d1
1797	moveq #-1,d2
1798	tst.l d0
1799	bmi.s .end
1800	lea MH_FOO_DIMS(a5),a2
1801	move.l 50(a2),d1
1802	move.l 54(a2),d2
1803.end
1804
1805	move.l 28(a4),d0
1806	cmp.w MH_FOO_MOFFSET(a5),d4
1807	bne.s .dosend
1808	cmp.l MH_FOO_VPXY(a5),d0
1809	bne.s .dosend
1810	cmp.l MH_FOO_DIMS_X(a5),d1
1811	bne.s .dosend
1812	cmp.l MH_FOO_DIMS_Y(a5),d2
1813	beq.s .nosend
1814.dosend
1815	move.l d0,MH_FOO_VPXY(a5)
1816	move.l d1,MH_FOO_DIMS_X(a5)
1817	move.l d2,MH_FOO_DIMS_Y(a5)
1818	move.w d4,MH_FOO_MOFFSET(a5)
1819
1820	; This only for doublescan properties bit..
1821	sub.l a0,a0
1822	lea MH_FOO_DISP(a5),a1
1823	moveq #0,d0
1824	move.w #88,d0
1825	move.l #DTAG_DISP,d1
1826	move.l d3,d2
1827	jsr -$2f4(a6) ;GetDisplayInfoData
1828	tst.l d0
1829	bmi.s .nomntr
1830	lea MH_FOO_DISP(a5),a3
1831.nomntr
1832
1833	;send updated data to native side
1834	move.w MH_FOO_MOFFSET(a5),d2
1835	move.w #$FF38,d0
1836	moveq #1,d1
1837	bsr.w getrtbase
1838	jsr (a0)
1839
1840.nosend
1841	movem.l (sp)+,d0-d4/a0-a6
1842	rts
1843
1844mousehack_task:
1845	move.l 4.w,a6
1846
1847	move.w 20(a6),d7 ; KS version
1848
1849	moveq #-1,d0
1850	jsr -$014a(a6) ;AllocSignal
1851	moveq #0,d6
1852	bset d0,d6
1853
1854	sub.l a1,a1
1855	jsr -$0126(a6) ;FindTask
1856	move.l d0,a4
1857
1858	moveq #20,d0
1859	move.l a4,a1
1860	jsr -$012c(a6) ;SetTaskPri
1861
1862	moveq #0,d0
1863	move.w #MH_END,d0
1864	move.l #65536+1,d1
1865	jsr AllocMem(a6)
1866	move.l d0,a5
1867
1868	lea MH_FOO(a5),a3
1869	move.l a6,MH_FOO_EXECBASE(a3)
1870	move.l a4,MH_FOO_TASK(a3)
1871	move.l d6,MH_FOO_MASK(a3)
1872	moveq #-1,d0
1873	move.w d0,MH_FOO_CNT(a3)
1874
1875    ; send data structure address
1876	move.w #$FF38,d0
1877	moveq #5,d1
1878	bsr.w getrtbase
1879	move.l a5,d0
1880	add.l #MH_DATA,d0
1881	jsr (a0)
1882
1883	lea MH_INT(a5),a1
1884	move.b #2,8(a1) ;NT_INTERRUPT
1885	move.b #5,9(a1) ;priority
1886	lea mhname(pc),a0
1887	move.l a0,10(a1)
1888	lea mousehackint(pc),a0
1889	move.l a0,18(a1)
1890	move.l a5,14(a1)
1891	moveq #5,d0 ;INTB_VERTB
1892	jsr -$00a8(a6)
1893
1894mhloop
1895	move.l d6,d0
1896	jsr -$013e(a6) ;Wait
1897
1898	moveq #0,d0
1899	subq.l #1,MH_FOO_DELAY(a3)
1900	bpl.s .delay1
1901	moveq #10,d0
1902	move.l d0,MH_FOO_DELAY(a3)
1903.delay1
1904
1905	tst.l MH_FOO_INTBASE(a3)
1906	bne.s .intyes
1907	tst.l MH_FOO_DELAY(a3)
1908	bne.s mhloop
1909	lea intlibname(pc),a1
1910	moveq #0,d0
1911	jsr -$0228(a6) ;OpenLibrary
1912	move.l d0,MH_FOO_INTBASE(a3)
1913	beq.s mhloop
1914.intyes
1915	tst.l MH_FOO_GFXBASE(a3)
1916	bne.s .gfxyes
1917	tst.l MH_FOO_DELAY(a3)
1918	bne.s mhloop
1919	lea gfxlibname(pc),a1
1920	moveq #0,d0
1921	jsr -$0228(a6) ;OpenLibrary
1922	move.l d0,MH_FOO_GFXBASE(a3)
1923	beq.w mhloop
1924.gfxyes
1925
1926	tst.l MH_IO(a5)
1927	bne.s .yesio
1928	tst.l MH_FOO_DELAY(a3)
1929	bne.s mhloop
1930	jsr -$0084(a6) ;Forbid
1931	lea 350(a6),a0 ;DeviceList
1932	lea inp_dev(pc),a1
1933	jsr -$114(a6) ;FindName
1934	move.l d0,d2
1935	jsr -$008a(a6) ;Permit
1936	tst.l d2
1937	beq.s mhloop
1938	lea inp_dev(pc),a0
1939	moveq #0,d0
1940	moveq #0,d1
1941	bsr.w allocdevice
1942	move.l d0,MH_IO(a5)
1943	beq.w mhend
1944	bra.w mhloop
1945.yesio
1946	tst.l MH_TM(a5)
1947	bne.s .yestim
1948	tst.l MH_FOO_DELAY(a3)
1949	bne.w mhloop
1950	jsr -$0084(a6) ;Forbid
1951	lea 350(a6),a0 ;DeviceList
1952	lea tim_dev(pc),a1
1953	jsr -$114(a6) ;FindName
1954	move.l d0,d2
1955	jsr -$008a(a6) ;Permit
1956	tst.l d2
1957	beq.w mhloop
1958	lea tim_dev(pc),a0
1959	moveq #0,d0
1960	moveq #0,d1
1961	bsr.w allocdevice
1962	move.l d0,MH_TM(a5)
1963	beq.w mhend
1964
1965	;tell native side that mousehack is now active
1966	move.w #$FF38,d0
1967	moveq #0,d1
1968	bsr.w getrtbase
1969	jsr (a0)
1970	bra.w mhloop
1971.yestim
1972
1973	cmp.w #36,d7
1974	bcs.s .nodims
1975	subq.l #1,MH_FOO_LIMITCNT(a3)
1976	bpl.s .nodims
1977	move.l a3,a0
1978	bsr.w getgfxlimits
1979	moveq #50,d0
1980	move.l d0,MH_FOO_LIMITCNT(a3)
1981.nodims
1982
1983	move.l MH_IO(a5),a1
1984	lea MH_IEV(a5),a2
1985	move.w #11,28(a1) ;IND_WRITEEVENT
1986	move.l #22,36(a1) ;sizeof(struct InputEvent)
1987	move.l a2,40(a1)
1988
1989	move.b MH_E+MH_DATA(a5),d0
1990	cmp.w #39,d7
1991	bcs.w .notablet
1992	btst #MH_TABLET,d0
1993	beq.w .notablet
1994
1995	;IENewTablet
1996
1997	lea MH_IEPT(a5),a0
1998	move.l a0,10(a2) ;ie_Addr
1999
2000	move.b #$13,4(a2) ;ie_Class=IECLASS_NEWPOINTERPOS
2001	move.b #3,5(a2) ;ie_SubClass = IESUBCLASS_NEWTABLET
2002	clr.l (a0) ;ient_CallBack
2003	clr.l 4(a0)
2004	clr.l 8(a0)
2005	clr.w 12(a0)
2006
2007	clr.w 6(a2) ;ie_Code
2008	bsr.w buttonstoqual
2009
2010	move.w MH_X+MH_DATA(a5),12+2(a0) ;ient_TabletX
2011	clr.w 16(a0)
2012	move.w MH_Y++MH_DATA(a5),16+2(a0) ;ient_TabletY
2013	clr.w 20(a0)
2014	move.w MH_MAXX+MH_DATA(a5),20+2(a0) ;ient_RangeX
2015	clr.w 24(a0)
2016	move.w MH_MAXY+MH_DATA(a5),24+2(a0) ;ient_RangeY
2017	lea MH_IENTTAGS(a5),a1
2018	move.l a1,28(a0) ;ient_TagList
2019	move.l #TABLETA_Pressure,(a1)+
2020	move.w MH_PRESSURE+MH_DATA(a5),d0
2021	ext.l d0
2022	asl.l #8,d0
2023	move.l d0,(a1)+
2024	move.l #TABLETA_ButtonBits,(a1)+
2025	move.l MH_BUTTONBITS+MH_DATA(a5),(a1)+
2026
2027	moveq #0,d0
2028
2029	move.w MH_RESX+MH_DATA(a5),d0
2030	bmi.s .noresx
2031	move.l #TABLETA_ResolutionX,(a1)+
2032	move.l d0,(a1)+
2033.noresx
2034	move.w MH_RESY+MH_DATA(a5),d0
2035	bmi.s .noresy
2036	move.l #TABLETA_ResolutionY,(a1)+
2037	move.l d0,(a1)+
2038.noresy
2039
2040	move.w MH_MAXZ+MH_DATA(a5),d0
2041	bmi.s .noz
2042	move.l #TABLETA_RangeZ,(a1)+
2043	move.l d0,(a1)+
2044	move.w MH_Z+MH_DATA(a5),d0
2045	move.l #TABLETA_TabletZ,(a1)+
2046	move.l d0,(a1)+
2047.noz
2048
2049	move.w MH_MAXAX+MH_DATA(a5),d0
2050	bmi.s .noax
2051	move.l #TABLETA_AngleX,(a1)+
2052	move.w MH_AX+MH_DATA(a5),d0
2053	ext.l d0
2054	asl.l #8,d0
2055	move.l d0,(a1)+
2056.noax
2057	move.w MH_MAXAY++MH_DATA(a5),d0
2058	bmi.s .noay
2059	move.l #TABLETA_AngleY,(a1)+
2060	move.w MH_AY+MH_DATA(a5),d0
2061	ext.l d0
2062	asl.l #8,d0
2063	move.l d0,(a1)+
2064.noay
2065	move.w MH_MAXAZ++MH_DATA(a5),d0
2066	bmi.s .noaz
2067	move.l #TABLETA_AngleZ,(a1)+
2068	move.w MH_AZ+MH_DATA(a5),d0
2069	ext.l d0
2070	asl.l #8,d0
2071	move.l d0,(a1)+
2072.noaz
2073
2074	moveq #0,d0
2075	move.w MH_INPROXIMITY+MH_DATA(a5),d0
2076	bmi.s .noproxi
2077	move.l #TABLETA_InProximity,(a1)+
2078	move.l d0,(a1)+
2079.noproxi
2080	clr.l (a1) ;TAG_DONE
2081
2082	bsr.w mhdoio
2083
2084	;create mouse button events if button state changed
2085	move.w #$68,d3 ;IECODE_LBUTTON->IECODE_RBUTTON->IECODE_MBUTTON
2086	moveq #1,d2
2087	move.l MH_BUTTONBITS+MH_DATA(a5),d4
2088.nextbut
2089	move.l d4,d0
2090	and.l d2,d0
2091	move.l MH_FOO_BUTTONS(a3),d1
2092	and.l d2,d1
2093	cmp.l d0,d1
2094	beq.s .nobut
2095
2096	clr.l (a2)
2097	move.w #$0200,4(a2) ;ie_Class=IECLASS_RAWMOUSE,ie_SubClass=0
2098	clr.l 10(a2)	;ie_Addr/X+Y
2099	move.w d3,d1
2100	tst.b d0
2101	bne.s .butdown
2102	bset #7,d1 ;IECODE_UP_PREFIX
2103.butdown
2104	move.w d1,6(a2) ;ie_Code
2105	clr.w 8(a2) ;ie_Qualifier
2106
2107	bsr.w mhdoio
2108
2109.nobut
2110	addq.w #1,d3
2111	add.w d2,d2
2112	cmp.w #8,d2
2113	bne.s .nextbut
2114	move.l d4,MH_FOO_BUTTONS(a3)
2115
2116.notablet
2117
2118	move.b MH_E+MH_DATA(a5),d0
2119	btst #MH_MOUSEHACK,d0
2120	beq.w mhloop
2121
2122	clr.l (a2)
2123	move.w #$0400,4(a2) ;IECLASS_POINTERPOS
2124	clr.w 6(a2) ;ie_Code
2125	bsr.w buttonstoqual
2126
2127	move.l MH_FOO_INTBASE(a3),a0
2128
2129	move.w MH_ABSX+MH_DATA(a5),d0
2130	move.w 34+14(a0),d1
2131	add.w d1,d1
2132	sub.w d1,d0
2133	bpl.s .xn
2134	moveq #0,d0
2135.xn
2136	move.w d0,10(a2)
2137
2138	move.w MH_ABSY+MH_DATA(a5),d0
2139	move.w 34+12(a0),d1
2140	add.w d1,d1
2141	sub.w d1,d0
2142	bpl.s .yn
2143	moveq #0,d0
2144.yn
2145	move.w d0,12(a2)
2146
2147	bsr.w mhdoiotimer
2148
2149	bra.w mhloop
2150
2151mhend
2152	rts
2153
2154buttonstoqual:
2155	;IEQUALIFIER_MIDBUTTON=0x1000/IEQUALIFIER_RBUTTON=0x2000/IEQUALIFIER_LEFTBUTTON=0x4000
2156	move.l MH_BUTTONBITS+MH_DATA(a5),d1
2157	moveq #0,d0
2158	btst #0,d1
2159	beq.s .btq1
2160	bset #14,d0
2161.btq1:
2162	btst #1,d1
2163	beq.s .btq2
2164	bset #13,d0
2165.btq2:
2166	btst #2,d1
2167	beq.s .btq3
2168	bset #12,d0
2169.btq3:
2170	move.w d0,8(a2) ;ie_Qualifier
2171	rts
2172
2173mousehackint:
2174	tst.l MH_IO(a1)
2175	beq.s .l1
2176	tst.l MH_TM(a1)
2177	beq.s .l1
2178	move.w MH_CNT+MH_DATA(a1),d0
2179	cmp.w MH_FOO+MH_FOO_CNT(a1),d0
2180	beq.s .l2
2181	move.w d0,MH_FOO+MH_FOO_CNT(a1)
2182.l1
2183	move.l MH_FOO+MH_FOO_EXECBASE(a1),a6
2184	move.l MH_FOO+MH_FOO_MASK(a1),d0
2185	move.l MH_FOO+MH_FOO_TASK(a1),a1
2186	jsr -$0144(a6) ; Signal
2187.l2
2188	subq.w #1,MH_FOO+MH_FOO_ALIVE(a1)
2189	bpl.s .l3
2190	move.w #50,MH_FOO+MH_FOO_ALIVE(a1)
2191	move.w #$FF38,d0
2192	moveq #2,d1
2193	bsr.w getrtbase
2194	jsr (a0)
2195.l3
2196	lea $dff000,a0
2197	moveq #0,d0
2198	rts
2199
2200; clipboard sharing
2201
2202CLIP_WRITE_SIZE = 0
2203CLIP_WRITE_ALLOC = (CLIP_WRITE_SIZE+4)
2204CLIP_TASK = (CLIP_WRITE_ALLOC+4)
2205CLIP_UNIT = (CLIP_TASK+4)
2206CLIP_ID = (CLIP_UNIT+4)
2207CLIP_EXEC = (CLIP_ID+4)
2208CLIP_DOS = (CLIP_EXEC+4)
2209CLIP_HOOK = (CLIP_DOS+4)
2210CLIP_BUF = (CLIP_HOOK+20)
2211CLIP_BUF_SIZE = 8
2212CLIP_POINTER_NOTIFY = (CLIP_BUF+CLIP_BUF_SIZE)
2213CLIP_POINTER_PREFS = (CLIP_POINTER_NOTIFY+48)
2214CLIP_END = (CLIP_POINTER_PREFS+32)
2215
2216clipboard_init:
2217	movem.l a5/a6,-(sp)
2218
2219	move.w #$FF38,d0
2220	moveq #17,d1
2221	bsr.w getrtbase
2222	jsr (a0)
2223	btst #0,d0
2224	beq.s .noclip
2225
2226	move.l 4.w,a6
2227	move.l #CLIP_END,d0
2228	move.l #$10001,d1
2229	jsr AllocMem(a6)
2230	tst.l d0
2231	beq.w clipdie
2232	move.l d0,a5
2233	move.l a6,CLIP_EXEC(a5)
2234
2235	move.w #$FF38,d0
2236	moveq #14,d1
2237	bsr.w getrtbase
2238	move.l a5,d0
2239	jsr (a0)
2240
2241	; we need to be a process, LoadLibrary() needs to call dos
2242	lea clname(pc),a0
2243	lea clipboard_proc(pc),a1
2244	moveq #-10,d0
2245	move.l #10000,d1
2246	bsr.w createproc
2247.noclip
2248	moveq #0,d0
2249	movem.l (sp)+,a5/a6
2250	rts
2251
2252clipkill
2253	move.w #$FF38,d0
2254	moveq #10,d1
2255	bsr.w getrtbase
2256	jsr (a0)
2257	rts
2258
2259clipdie:
2260	bsr.s clipkill
2261	move.l a5,d0
2262	beq.s .cd1
2263	move.l CLIP_EXEC(a5),a6
2264	move.l CLIP_DOS(a5),d0
2265	beq.s .cd2
2266	move.l d0,a1
2267	jsr -414(a6) ; CloseLibrary
2268.cd2
2269	move.l a5,a1
2270	move.l #CLIP_END,d0
2271	jsr FreeMem(a6)
2272.cd1
2273	moveq #0,d0
2274	rts
2275
2276prefsread:
2277	movem.l d2-d4/a2-a6,-(sp)
2278	move.l CLIP_DOS(a5),a6
2279	lea pointer_prefs(pc),a0
2280	move.l a0,d1
2281	move.l #1005,d2
2282	jsr -$001e(a6) ;Open
2283	move.l d0,d4
2284	beq.s .pr1
2285	lea CLIP_POINTER_PREFS(a5),a2
2286.pr4
2287	clr.l (a2)
2288.pr3
2289	move.w 2(a2),(a2)
2290	move.l a2,d2
2291	addq.l #2,d2
2292	moveq	#2,d3
2293	move.l d4,d1
2294	jsr -$002a(a6) ;Read
2295	cmp.l d0,d3
2296	bne.s .pr1
2297	cmp.l #'PNTR',(a2)
2298	bne.s .pr3
2299	move.l a2,d2
2300	moveq #4,d3
2301	move.l d4,d1
2302	jsr -$002a(a6) ;Read
2303	move.l a2,d2
2304	moveq #32,d3
2305	move.l d4,d1
2306	jsr -$002a(a6) ;Read
2307	cmp.l d0,d3
2308	bne.s .pr1
2309	tst.w 16(a2) ;pp_Which
2310	bne.s .pr4
2311	move.w #$FF38,d0
2312	moveq #16,d1
2313	bsr.w getrtbase
2314	jsr (a0)
2315.pr1
2316	move.l d4,d1
2317	beq.s .pr2
2318	jsr -$0024(a6) ;Close
2319.pr2
2320	movem.l (sp)+,d2-d4/a2-a6
2321	rts
2322
2323prefshook:
2324	move.l CLIP_DOS(a5),a6
2325	lea ram_name(pc),a0
2326	move.l a0,d1
2327	moveq #-2,d2
2328	jsr -$0054(a6) ;Lock
2329	move.l d0,d1
2330	beq.s .ph1
2331	jsr -$005a(a6) ;Unlock
2332	move.l CLIP_EXEC(a5),a6
2333	lea CLIP_POINTER_NOTIFY(a5),a2
2334	moveq #-1,d0
2335	jsr -$014a(a6) ;AllocSignal
2336	move.b d0,20(a2) ;nr_SignalNum
2337	lea pointer_prefs(pc),a0
2338	move.l a0,(a2) ;nr_Name
2339	move.l #NRF_SEND_SIGNAL|NRF_NOTIFY_INITIAL,12(a2) ;nr_Flags
2340	move.l CLIP_TASK(a5),16(a2) ;nr_Task
2341	move.l CLIP_DOS(a5),a6
2342	move.l a2,d1
2343	jsr -$378(a6) ;StartNotify
2344.ph1
2345	move.l CLIP_EXEC(a5),a6
2346	rts
2347
2348	cnop 0,4
2349	dc.l 16
2350clipboard_proc:
2351	dc.l 0
2352
2353	move.w #$FF38,d0
2354	moveq #13,d1
2355	bsr.w getrtbase
2356	jsr (a0)
2357	tst.l d0
2358	beq.w clipdie
2359	move.l d0,a5
2360	move.l CLIP_EXEC(a5),a6
2361
2362	sub.l a1,a1
2363	jsr -294(a6) ; FindTask
2364	move.l d0,CLIP_TASK(a5)
2365
2366	lea doslibname(pc),a1
2367	moveq #0,d0
2368	jsr -$0228(a6) ; OpenLibrary
2369	move.l d0,CLIP_DOS(a5)
2370	beq.w clipdie
2371	move.l d0,a6
2372
2373.devsloop
2374	moveq #50,d1
2375	jsr -$00c6(a6) ;Delay
2376	lea devs_name(pc),a0
2377	move.l a0,d1
2378	moveq #-2,d2
2379	jsr -$0054(a6) ;Lock
2380	tst.l d0
2381	beq.s .devsloop
2382	move.l d0,d1
2383	jsr -$005a(a6) ;Unlock
2384	moveq #50,d1
2385	jsr -$00c6(a6) ;Delay
2386	lea clip_name(pc),a0
2387	move.l a0,d1
2388	moveq #-2,d2
2389	jsr -$0054(a6) ;Lock
2390	tst.l d0
2391	beq.w clipdie
2392	move.l d0,d1
2393	jsr -$005a(a6) ;Unlock
2394
2395	move.l CLIP_EXEC(a5),a6
2396
2397	bsr.w createport
2398	moveq #0,d1
2399	move.w #52,d1
2400	bsr.w createio
2401	move.l d0,a4
2402	tst.l d0
2403	beq.w clipdie
2404
2405cfloop2
2406	moveq #0,d0
2407	bset #13,d0
2408	jsr -$013e(a6) ;Wait
2409
2410	moveq #0,d1
2411	move.l CLIP_UNIT(a5),d0
2412	lea clip_dev(pc),a0
2413	move.l a4,a1
2414	jsr -$01bc(a6) ;OpenDevice
2415	tst.l d0
2416	bne.s cfloop2
2417	move.l 20(a4),a0 ;device node
2418	cmp.w #37,20(a0) ;must be at least v37
2419	bcc.s cfversion
2420	;too lazy to free everything..
2421	bsr.w clipkill
2422cfloop3
2423	moveq #0,d0
2424	jsr -$013e(a6) ;Wait
2425	bra.s cfloop3
2426
2427cfversion
2428	bsr.w prefshook
2429
2430	lea CLIP_HOOK(a5),a0
2431	move.l a0,40(a4)
2432	moveq #1,d0
2433	move.l d0,36(a4)
2434	move.w #12,28(a4) ;CBD_CHANGEHOOK
2435	move.l a5,CLIP_HOOK+16(a5)
2436	lea cliphook(pc),a0
2437	move.l a0,CLIP_HOOK+8(a5)
2438	move.l a4,a1
2439	jsr -$01c8(a6) ;DoIO
2440
2441	move.w #$FF38,d0
2442	moveq #15,d1
2443	bsr.w getrtbase
2444	jsr (a0)
2445	tst.l CLIP_WRITE_SIZE(a5)
2446	bne.s clipsignal
2447
2448cfloop
2449	moveq #0,d0
2450	moveq #0,d2
2451	move.b CLIP_POINTER_NOTIFY+20(a5),d2
2452	bset d2,d0
2453	bset #13,d0
2454	jsr -$013e(a6) ;Wait
2455	btst d2,d0
2456	beq.s clipsignal
2457	bsr.w prefsread
2458	bra.s cfloop
2459
2460clipsignal
2461	move.l CLIP_WRITE_SIZE(a5),d0
2462	beq.w clipread
2463	;allocate amiga-side space
2464	moveq #1,d1
2465	jsr AllocMem(a6)
2466	move.l d0,CLIP_WRITE_ALLOC(a5)
2467	;and notify host-side
2468	move.w #$FF38,d0
2469	moveq #12,d1
2470	bsr.w getrtbase
2471	jsr (a0)
2472	tst.l d0
2473	beq.s .nowrite
2474	; and now we should have the data in CLIP_WRITE_ALLOC
2475	tst.l CLIP_WRITE_ALLOC(a5)
2476	beq.s .nowrite
2477
2478	move.w #3,28(a4) ;CMD_WRITE
2479	clr.b 31(a4)
2480	clr.l 32(a4)
2481	move.l CLIP_WRITE_SIZE(a5),36(a4)
2482	move.l CLIP_WRITE_ALLOC(a5),40(a4)
2483	clr.l 44(a4)
2484	clr.l 48(a4)
2485	move.l a4,a1
2486	jsr -$01c8(a6) ;DoIO
2487	move.l 48(a4),CLIP_ID(a5)
2488	move.w #4,28(a4) ;CMD_UPDATE
2489	move.l a4,a1
2490	jsr -$01c8(a6) ;DoIO
2491
2492.nowrite
2493	move.l CLIP_WRITE_SIZE(a5),d0
2494	clr.l CLIP_WRITE_SIZE(a5)
2495	move.l CLIP_WRITE_ALLOC(a5),d1
2496	beq.w cfloop
2497	move.l d1,a1
2498	jsr FreeMem(a6)
2499	bra.w cfloop
2500
2501clipread:
2502  ; read first 8 bytes
2503	move.w #2,28(a4) ;CMD_READ
2504	lea CLIP_BUF(a5),a0
2505	clr.l (a0)
2506	clr.l 4(a0)
2507	clr.b 31(a4)
2508	clr.l 44(a4)
2509	clr.l 48(a4)
2510	move.l a0,40(a4)
2511	moveq #8,d0
2512	move.l d0,36(a4)
2513	move.l a4,a1
2514	jsr -$01c8(a6) ;DoIO
2515	cmp.l #'FORM',CLIP_BUF(a5)
2516	bne.s .cf1
2517	move.l CLIP_BUF+4(a5),d0
2518	beq.s .cf1
2519	bmi.s .cf1
2520	move.l 48(a4),CLIP_ID(a5)
2521	addq.l #8,d0
2522	move.l d0,d2
2523	moveq #1,d1
2524	jsr AllocMem(a6)
2525	tst.l d0
2526	beq.s .cf1
2527	move.l d0,a2
2528	; read the rest
2529	move.l a2,a0
2530	move.l CLIP_BUF(a5),(a0)+
2531	move.l CLIP_BUF+4(a5),(a0)+
2532	move.l a0,40(a4)
2533	move.l d2,d0
2534	subq.l #8,d0
2535	move.l d0,36(a4)
2536	move.l a4,a1
2537	jsr -$01c8(a6) ;DoIO
2538	move.w #$FF38,d0
2539	moveq #11,d1
2540	bsr.w getrtbase
2541	move.l 32(a4),d0
2542	jsr (a0)
2543	move.l a2,a1
2544	move.l d2,d0
2545	jsr FreeMem(a6)
2546.cf1
2547	; tell clipboard.device that we are done (read until io_Actual==0)
2548	tst.l 32(a4)
2549	beq.w cfloop
2550	lea CLIP_BUF(a5),a0
2551	move.l a0,40(a4)
2552	moveq #1,d0
2553	move.l d0,36(a4)
2554	clr.l 32(a4)
2555	move.l a4,a1
2556	jsr -$01c8(a6) ;DoIO
2557	bra.s .cf1
2558
2559cliphook:
2560	lea -CLIP_HOOK(a0),a0
2561	move.l 8(a1),d0
2562	cmp.l CLIP_ID(a0),d0 ;ClipHookMsg->chm_ClipID
2563	beq.s .same
2564	move.l d0,CLIP_ID(a0)
2565	move.l a6,-(sp)
2566	move.l CLIP_EXEC(a0),a6
2567	move.l CLIP_TASK(a0),a1
2568	moveq #0,d0
2569	bset #13,d0 ;SIG_D
2570	jsr -$0144(a6) ;Signal
2571	move.l (sp)+,a6
2572.same
2573	moveq #0,d0
2574	rts
2575
2576consolehook:
2577	move.l 4.w,a6
2578
2579	moveq #-1,d2
2580	move.w #$FF38,d0
2581	moveq #17,d1
2582	bsr.w getrtbase
2583	jsr (a0)
2584	btst #1,d0
2585	beq.s .ch2
2586
2587	moveq #0,d2
2588	jsr -$0084(a6) ;Forbid
2589	lea 350(a6),a0 ;DeviceList
2590	lea con_dev(pc),a1
2591	jsr -$114(a6) ;FindName
2592	tst.l d0
2593	beq.s .ch1
2594	move.l d0,a0
2595	lea chook(pc),a1
2596	move.l -$1e+2(a0),a2 ; BeginIO
2597	move.l a1,-$1e+2(a0)
2598	move.l a0,a1
2599	move.w #$FF38,d0
2600	moveq #101,d1
2601	bsr.w getrtbase
2602	jsr (a0)
2603	moveq #1,d2
2604.ch1
2605	jsr -$008a(a6) ;Permit
2606.ch2
2607	move.l d2,d0
2608	rts
2609
2610chook:
2611	subq.l #4,sp ; native code fills with original return address
2612	movem.l d0-d1/a0,-(sp)
2613	move.w #$FF38,d0
2614	moveq #102,d1
2615	bsr.w getrtbase
2616	jsr (a0)
2617	movem.l (sp)+,d0-d1/a0
2618	rts
2619
2620getrtbase:
2621	lea start-8-4(pc),a0
2622	and.l #$FFFF,d0
2623	add.l d0,a0
2624	rts
2625
2626inp_dev: dc.b 'input.device',0
2627tim_dev: dc.b 'timer.device',0
2628con_dev: dc.b 'console.device',0
2629devsn_name: dc.b 'DEVS',0
2630devs_name: dc.b 'DEVS:',0
2631clip_name: dc.b 'DEVS:clipboard.device',0
2632ram_name: dc.b 'RAM:',0
2633clip_dev: dc.b 'clipboard.device',0
2634 ;argghh but StartNotify()ing non-existing ENV: causes "Insert disk ENV: in any drive" dialog..
2635pointer_prefs: dc.b 'RAM:Env/Sys/Pointer.prefs',0
2636clname: dc.b 'UAE clipboard sharing',0
2637mhname: dc.b 'UAE mouse driver',0
2638kaname: dc.b 'UAE heart beat',0
2639exter_name: dc.b 'UAE filesystem',0
2640fstaskname: dc.b 'UAE fs automounter',0
2641fsprocname: dc.b 'UAE fs automount process',0
2642doslibname: dc.b 'dos.library',0
2643intlibname: dc.b 'intuition.library',0
2644gfxlibname: dc.b 'graphics.library',0
2645explibname: dc.b 'expansion.library',0
2646fsresname: dc.b 'FileSystem.resource',0
2647fchipname: dc.b 'megachip memory',0
2648	END
2649