Home » Archimedes archive » Zipped Apps » BBC Tape » !BBCTape/!RunImage
!BBCTape/!RunImage
This website contains an archive of files for the Acorn Electron, BBC Micro, Acorn Archimedes, Commodore 16 and Commodore 64 computers, which Dominic Ford has rescued from his private collection of floppy disks and cassettes.
Some of these files were originally commercial releases in the 1980s and 1990s, but they are now widely available online. I assume that copyright over them is no longer being asserted. If you own the copyright and would like files to be removed, please contact me.
| Tape/disk: | Home » Archimedes archive » Zipped Apps » BBC Tape |
| Filename: | !BBCTape/!RunImage |
| Read OK: | ✔ |
| File size: | 941E bytes |
| Load address: | 0000 |
| Exec address: | 0000 |
File contents
10REM > <BBCTape$Dir>.!RunImage
20
30ON ERROR END
40
50app_name$ = "BBCTape"
60
70DIM task% 4:$task% = "TASK"
80SYS "Wimp_Initialise",200,!task%,app_name$ TO ,task_handle%
90
100ON ERROR PROCerror(TRUE)
110
120PROCwimp_init
130PROCprog_init
140
150ON ERROR PROCerror(FALSE)
160
170REM Minimise memory consumption (current end + 1 page)
180END = END + 8*1024
190
200SYS "OS_ReadMonotonicTime" TO idle_time%
210idle_time% += poll_time%
220
230REPEAT
240 SYS "Wimp_PollIdle",poll_mask%,wimp_block%,idle_time% TO code%
250 CASE code% OF
260 WHEN 0 :IF putting% THEN PROCnull_putting ELSE PROCnull_getting
270 SYS "OS_ReadMonotonicTime" TO idle_time%
280 idle_time% += poll_time%
290 WHEN 2 :SYS "Wimp_OpenWindow",,wimp_block%
300 WHEN 3 :SYS "Wimp_CloseWindow",,wimp_block%
310 WHEN 6 :PROCmouse_click
320 WHEN 7 :PROCuser_drag_box
330 WHEN 8 :SYS "Wimp_ProcessKey",wimp_block%!24
340 WHEN 9 :PROCmenu_selection
350 WHEN 17,18 :PROCuser_message
360 WHEN 19 :IF wimp_block%!16=3 THEN
370 SYS "OS_File",6,saved_file$
380 PROCmessage("Data transfer failed: Receiver died")
390 ENDIF
400 ENDCASE
410UNTIL pigs_can_fly%
420
430PROCexit(TRUE)
440
450END
460
470------------------------------------------------------------------------
480
490DEF PROCexit(must%)
500
510REM If must% is TRUE we must exit, even with unsaved files
520
530IF hourglass% SYS "Hourglass_Off":hourglass% = FALSE
540
550IF modified% AND NOT must% IF NOT FNconfirm("Unsaved data: are you sure you want to Quit?") ENDPROC
560
570REM Clear out the RS423 buffers
580*FX 2
590*FX 21 1
600*FX 21 2
610
620SYS "Wimp_CloseDown",task_handle%,!task%
630
640END
650
660------------------------------------------------------------------------
670
680DEF PROCerror(quit%)
690
700LOCAL report$
710
720LOCAL ERROR:ON ERROR PROCexit(TRUE)
730
740REM Disk not found/not present - filer provides error box
750IF ERR=&108D4 OR ERR=&108D5 ENDPROC
760
770!string_buffer% = ERR
780report$ = REPORT$ + " (internal error code " + STR$(ERL) + ")"
790$(string_buffer%+4) = LEFT$(report$,250) + CHR$0
800
810SYS "Wimp_ReportError",string_buffer%,1,app_name$
820
830IF quit% PROCexit(TRUE)
840
850PROCreset_state
860
870ENDPROC
880
890------------------------------------------------------------------------
900
910DEF FNconfirm(message$)
920
930LOCAL mask%,code%,end%,yes%
940
950LOCAL ERROR
960ON ERROR RESTORE ERROR:MOUSE RECTANGLE 0,0,screen_x%,screen_y%:PROCclose_window(error_window%):ERROR ERR,REPORT$
970
980IF hourglass% SYS "Hourglass_Off"
990
1000$error_ptr% = LEFT$(message$,255)
1010
1020PROCopen_window(error_window%)
1030
1040SYS "Wimp_GetWindowOutline",,wimp_block%
1050MOUSE RECTANGLE wimp_block%!4,wimp_block%!8,wimp_block%!12-wimp_block%!4-1,wimp_block%!16-wimp_block%!8-1
1060
1070mask% = 1 + (%11<<4) + (%11<<11) + (%111<<17)
1080end% = FALSE
1090
1100REPEAT
1110 SYS "Wimp_Poll",mask%,wimp_block% TO code%
1120 CASE code% OF
1130 WHEN 6 :end% = FNyes_or_no(yes%)
1140 WHEN 8 :IF wimp_block%!24=&1B end% = TRUE:yes% = FALSE
1150 ENDCASE
1160UNTIL end%
1170
1180MOUSE RECTANGLE 0,0,screen_x%,screen_y%
1190PROCclose_window(error_window%)
1200
1210IF hourglass% SYS "Hourglass_On"
1220
1230= yes%
1240
1250------------------------------------------------------------------------
1260
1270DEF FNyes_or_no(RETURN yes%)
1280
1290yes% = FALSE
1300
1310IF wimp_block%!12<>error_window% = FALSE
1320IF wimp_block%!16=1 yes% = TRUE: = TRUE
1330IF wimp_block%!16=4 = TRUE
1340
1350= FALSE
1360
1370------------------------------------------------------------------------
1380
1390DEF PROCmessage(message$)
1400
1410IF hourglass% SYS "Hourglass_Off"
1420
1430SYS "Wimp_ReportError"," "+message$+CHR$0,%10001,app_name$
1440
1450IF hourglass% SYS "Hourglass_On"
1460
1470ENDPROC
1480
1490************************************************************************
1500
1510Initialisation
1520
1530************************************************************************
1540
1550DEF PROCwimp_init
1560
1570DIM wimp_block% 1023,string_buffer% 255
1580DIM saveas_block% 88 + 3*32
1590DIM fileinfo_block% 88 + 17*32
1600
1610REM Initialise various flags
1620hourglass% = FALSE:saving% = FALSE
1630modified% = FALSE:pigs_can_fly% = FALSE
1640using_scrap% = -1 :saved_file$ = "<BBCTape$Dir>.xxxxxxxxxx"
1650version$ = "19 Mar"
1660
1670REM Get the screen size
1680!wimp_block% = 4:wimp_block%!4 = 5
1690wimp_block%!8 = 11:wimp_block%!12 = 12
1700wimp_block%!16 = -1
1710SYS "OS_ReadVduVariables",wimp_block%,wimp_block%+20
1720screen_x% = (1 << wimp_block%!20)*(wimp_block%!28 + 1)
1730screen_y% = (1 << wimp_block%!24)*(wimp_block%!32 + 1)
1740
1750REM Mask out null, pointer leaving/entering window, lose/gain caret
1760poll_mask% = 1 + (%11<<4) + (%11<<11):poll_time% = 10
1780
1790PROCicon_bar
1800
1810PROCload_templates
1820
1830PROCcreate_menu
1840
1850PROCinfo
1860
1870ENDPROC
1880
1890------------------------------------------------------------------------
1900
1910DEF PROCicon_bar
1920
1930!wimp_block% = -2
1940wimp_block%!4 = 0:wimp_block%!8 = 0
1950wimp_block%!12 = 68:wimp_block%!16 = 68
1960REM Sprite, click notifies once
1970wimp_block%!20 = (1<<1) + (3<<12)
1980$(wimp_block%+24) = "!" + app_name$
1990
2000SYS "Wimp_CreateIcon",,wimp_block%
2010
2020ENDPROC
2030
2040------------------------------------------------------------------------
2050
2060DEF PROCload_templates
2070
2080LOCAL name%,ptr%,ind_buffer%,i%
2090
2100DIM name% 12,ind_buffer% 1023
2110
2120SYS "Wimp_OpenTemplate",,"<" + app_name$ + "$Dir>.Templates"
2130
2140REM Save dialogue box
2150$name% = "saveas"
2160SYS "Wimp_LoadTemplate",,wimp_block%,ind_buffer%,ind_buffer%+1023,-1,name%,0 TO ,,ptr%
2170FOR i%=0 TO 88+3*32-1
2180 saveas_block%!i% = wimp_block%!i%
2190NEXT
2200save_ptr% = saveas_block%!140
2210SYS "Wimp_CreateWindow",,saveas_block% TO saveas%
2220
2230REM File information
2240$name% = "fileInfo"
2250SYS "Wimp_LoadTemplate",,wimp_block%,ptr%,ind_buffer%+1023,-1,name%,0 TO ,,ptr%
2260FOR i%=0 TO 88+17*32-1
2270 fileinfo_block%!i% = wimp_block%!i%
2280NEXT
2290fileinfo_block%!(108+4*32) = save_ptr%
2300fileinfo_block%!(108+4*32+8) = saveas_block%!148
2310type_buffer% = fileinfo_block%!(108+3*32)
2320SYS "Wimp_CreateWindow",,fileinfo_block% TO fileinfo%
2330
2340REM yes/no error box
2350$name% = "error"
2360SYS "Wimp_LoadTemplate",,wimp_block%,ptr%,ind_buffer%+1023,-1,name%,0 TO ,,ptr%
2370error_ptr% = wimp_block%!108
2380SYS "Wimp_CreateWindow",,wimp_block% TO error_window%
2390
2400REM Program info box
2410$name% = "proginfo"
2420SYS "Wimp_LoadTemplate",,wimp_block%,ptr%,ind_buffer%+1023,-1,name%,0 TO ,,ptr%
2430$(wimp_block%!236) = LEFT$("1.00 (25-Feb-1991)",wimp_block%!244)
2440SYS "Wimp_CreateWindow",,wimp_block% TO proginfo%
2450
2460REM Status window
2470$name% = "status"
2480SYS "Wimp_LoadTemplate",,wimp_block%,ptr%,ind_buffer%+1023,-1,name%,0
2490status_length% = wimp_block%!(108+2*32)
2500status_bytes% = wimp_block%!(108+3*32)
2510status_rate% = wimp_block%!(108+4*32)
2520status_crc% = wimp_block%!(108+9*32)
2530SYS "Wimp_CreateWindow",,wimp_block% TO status_window%
2540
2550SYS "Wimp_CloseTemplate"
2560
2570ENDPROC
2580
2590------------------------------------------------------------------------
2600
2610DEF PROCcreate_menu
2620
2630LOCAL i%,name$,width%,temp%
2640
2650DIM name_block% 52,name_ptr% 10
2660DIM type_block% 52,type_ptr% 8
2670DIM load_block% 52,load_ptr% 4,hex_valid% 10
2680DIM exec_block% 52,exec_ptr% 4
2690
2700$name_ptr% = "":$type_ptr% = ""
2710$load_ptr% = "":$exec_ptr% = ""
2720$hex_valid% = "a0-9a-fA-F"
2730
2740PROCwriteable_menu(name_block%,"File name",11,0,name_ptr%,11,-1)
2750PROCwriteable_menu(type_block%,"File type",10,0,type_ptr%,9,-1)
2760PROCwriteable_menu(load_block%,"Load address",13,0,load_ptr%,5,hex_valid%)
2770PROCwriteable_menu(exec_block%,"Exec address",13,0,exec_ptr%,5,hex_valid%)
2780
2790RESTORE +0
2800
2810READ menu_max%,len_menu_max%
2820DIM menu$(len_menu_max%,menu_max%)
2830DIM menu_block%(menu_max%),num_menu_items%(menu_max%)
2840
2850FOR i%=0 TO menu_max%
2860 READ name$,num_menu_items%(i%),width%
2870 DIM temp% 28 + 24*num_menu_items%(i%)
2880 menu_block%(i%) = temp%
2890 PROCbuild_menu(menu_block%(i%),name$,width%)
2900NEXT
2910
2920FOR i%=0 TO menu_max%
2930 PROCbuild_menu_items(menu_block%(i%),num_menu_items%(i%),i%)
2940NEXT
2950
2960REM No. of menus - 1, length of longest
2970DATA 2,8
2980
2990REM Name, no. of items, width
3000DATA "BBCTape",6,9
3010DATA "Misc" ,6,11
3020DATA "Options",8,13
3030
3040REM Item text, tick, shade, dot, notify, pointer
3050
3060DATA "Misc" ,0,0,0,0,menu_block%(1)
3070DATA "Save" ,0,0,0,1,saveas%
3080DATA "Options" ,0,0,0,0,menu_block%(2)
3090DATA "Upload" ,0,0,0,0,name_block%
3100DATA "Download" ,0,0,1,0,-1
3110DATA "Quit" ,0,0,0,0,-1
3120
3130DATA "Info" ,0,0,0,0,proginfo%
3140DATA "File" ,0,0,0,1,fileinfo%
3150DATA "Status ..." ,0,0,1,0,-1
3160DATA "9600, 8n1" ,0,0,1,0,-1
3170DATA "Reset" ,0,0,0,0,-1
3180DATA "Clear" ,0,0,0,0,-1
3190
3200DATA "File type" ,0,0,0,0,type_block%
3210DATA "Load address",1,0,0,0,load_block%
3220DATA "Exec address",1,0,1,0,exec_block%
3230DATA "CR � LF" ,0,0,0,0,-1
3240DATA "Guess type" ,0,0,0,0,-1
3250DATA "Auto load" ,0,0,0,0,-1
3260DATA "Fast load" ,1,0,0,0,-1
3270DATA "Use BGET" ,0,0,0,0,-1
3280
3290ENDPROC
3300
3310------------------------------------------------------------------------
3320
3330DEF PROCinfo
3340
3350LOCAL mask%,scroll%
3360
3370IF MID$(TIME$,5,6)<>version$ ENDPROC
3380
3390mask% = (%11<<4) + (%11<<11) + (%111<<17)
3400
3410PROCopen_window(proginfo%)
3420SYS "Wimp_Poll",mask%,wimp_block%
3430
3440PROCwait(200)
3450
3460!wimp_block% = proginfo%
3470SYS "Wimp_GetWindowState",,wimp_block%
3480
3490FOR scroll%=1 TO 300
3500 wimp_block%!24 = -scroll%
3510 SYS "Wimp_OpenWindow",,wimp_block%
3520 SYS "Wimp_Poll",mask%,wimp_block%+32
3530NEXT
3540
3550PROCwait(1000)
3560
3570FOR scroll%=300 TO 0 STEP -1
3580 wimp_block%!24 = -scroll%
3590 SYS "Wimp_OpenWindow",,wimp_block%
3600 SYS "Wimp_Poll",mask%,wimp_block%+32
3610NEXT
3620
3630PROCwait(200)
3640
3650PROCclose_window(proginfo%)
3660
3670ENDPROC
3680
3690------------------------------------------------------------------------
3700
3710DEF PROCwait(time%)
3720
3730time% += TIME
3740
3750REPEAT UNTIL TIME>time%
3760
3770ENDPROC
3780
3790------------------------------------------------------------------------
3800
3810DEF PROCprog_init
3820
3830PROCassemble_crc
3840
3850REM Main data block
3860file_block_length% = 32*1024 - 1
3870DIM file_block% file_block_length%
3880
3890REM Initial option settings
3900do_crlf% = FALSE:one_shot% = TRUE
3910load_bget% = FALSE:load_exec% = TRUE
3920guess_type% = FALSE:fast_load% = TRUE
3930
3940default_file_type% = &FFF
3950
3960old_time% = 0
3970
3980DEF PROCreset_all
3990
4000file_length% = 0 :file_ptr% = file_block%
4010crlf_done% = FALSE :modified% = FALSE
4020$load_ptr% = "FFFF":$exec_ptr% = "FFFF"
4030
4040original_file_name$ = "<unknown>"
4050
4060PROCget_file_type
4070
4080DEF PROCreset_state
4090
4100REM Flush buffers and enable serial input
4110*FX 2
4120*FX 21 1
4130*FX 21 2
4140*FX 2 2
4150
4160REM Pointers etc.
4170new_ptr% = file_ptr%:crc_errors% = 0
4180put_ptr% = file_ptr%:num_bytes% = 0
4190put_end_ptr% = file_ptr%:block_length% = 0
4191last_button% = 0
4200
4210REM State machine flags
4220putting% = FALSE:shaking% = FALSE
4230getting_ok% = FALSE:getting_file_length% = FALSE
4240getting_end% = FALSE:getting_block_length% = FALSE
4250getting_block% = FALSE:getting_file_name% = FALSE
4260downloading% = FALSE:was_downloading% = FALSE
4270uploading% = FALSE:last_download% = FALSE
4280
4290poll_mask% = poll_mask% OR 1
4300
4310PROCmenu_shade(0,"Upload",FALSE)
4320PROCmenu_shade(0,"Download",FALSE)
4330
4340PROCselect_icon(status_window%,0,0)
4350PROCselect_icon(status_window%,1,0)
4360
4370IF hourglass% SYS "Hourglass_Off":hourglass% = FALSE
4380
4390ENDPROC
4400
4410------------------------------------------------------------------------
4420
4430DEF PROCassemble_crc
4440
4450REM This takes 5.31 ms, vs 2.2 sec for the Basic version!
4460
4470LOCAL ptr,length,bits,count,data,lo,hi,link,nbyt,bytloop,opt%,P%
4480
4490DIM crc% 100
4500
4510ptr = 0:length = 1:bits = 2:count = 3
4520data = 4:lo = 5:hi = 6:link = 14
4530
4540FOR opt%=0 TO 2 STEP 2
4550P% = crc%
4560[OPT opt%
4570 MOV hi,#0
4580 MOV lo,#0
4590 MOV count,#0
4600.nbyt
4610 LDRB data,[ptr,count]
4620 EOR hi,hi,data
4630 MOV bits,#8
4640.bytloop
4650 TST hi,#&80
4660 EORNE hi,hi,#8
4670 EORNE lo,lo,#&10
4680 MOV lo,lo,LSL #1
4690 ADDNE lo,lo,#1
4700 MOV hi,hi,LSL #1
4710 TST lo,#&100
4720 ADDNE hi,hi,#1
4730 SUBS bits,bits,#1
4740 BNE bytloop
4750
4760 ADD count,count,#1
4770 CMP count,length
4780 BNE nbyt
4790
4800 STRB lo,crc_lo
4810 STRB hi,crc_hi
4820 MOV PC,link
4830
4840.crc_lo EQUB 0
4850.crc_hi EQUB 0
4860]
4870NEXT
4880
4890ENDPROC
4900
4910------------------------------------------------------------------------
4920
4930DEF PROCget_file_type
4940
4950LOCAL flags%,ptr%,temp%
4960
4970REM String -> file type
4980SYS "XOS_FSControl",31,$type_ptr% TO ,,file_type%;flags%
4990IF flags% AND 1 file_type% = default_file_type%
5000
5010REM File type -> string
5020SYS "OS_FSControl",18,,file_type% TO ,,!type_ptr%,type_ptr%!4
5030type_ptr%?8 = &0D
5040ptr% = type_ptr%+7
5050WHILE ?ptr%=&20 AND ptr%>type_ptr%:?ptr%=&0D:ptr%-=1:ENDWHILE
5060
5070IF load_exec% file_type% = &FFFFFFFF
5080
5090REM Read load/exec addresses
5100SYS "XOS_ReadUnsigned",16,$load_ptr% TO ,,temp%;flags%
5110IF flags% AND 1 THEN $load_ptr% = STR$~load% ELSE load% = temp%
5120
5130SYS "XOS_ReadUnsigned",16,$exec_ptr% TO ,,temp%;flags%
5140IF flags% AND 1 THEN $exec_ptr% = STR$~exec% ELSE exec% = temp%
5150
5160ENDPROC
5170
5180************************************************************************
5190
5200Main routines
5210
5220************************************************************************
5230
5240DEF PROCnull_putting
5250
5260LOCAL timeout%,flags%
5270
5280timeout% = TIME + 20*poll_time%
5290
5300SYS "Hourglass_On":hourglass% = TRUE
5310
5320REPEAT
5330 SYS "OS_SerialOp",3,?put_ptr% TO ;flags%
5340 IF (flags% AND 2)=0 put_ptr% += 1
5350UNTIL (flags% AND 2) OR put_ptr%=put_end_ptr% OR TIME>timeout%
5360
5370SYS "Hourglass_Off":hourglass% = FALSE
5380
5390IF put_ptr%=put_end_ptr% putting% = FALSE
5400
5410IF NOT downloading% ENDPROC
5420
5430IF NOT putting% THEN
5440 downloading% = FALSE
5450 poll_mask% = poll_mask% OR 1
5460 PROCmenu_shade(0,"Upload",FALSE)
5470ENDIF
5480
5490PROCupdate_status
5500
5510ENDPROC
5520
5530------------------------------------------------------------------------
5540
5550DEF PROCupdate_status
5560
5570IF downloading% OR (was_downloading% AND NOT uploading%) THEN
5580 was_downloading% = TRUE
5590 IF downloading% OR last_download% old_time% = TIME
5600 IF old_time%<=0 old_time% = 1
5610 IF downloading% THEN last_download% = TRUE ELSE last_download% = FALSE
5620 SYS "OS_ConvertFileSize",put_end_ptr%-file_ptr%,status_length%,12
5630 $status_bytes% = STR$(put_ptr% - file_ptr%)
5640 $status_rate% = STR$((put_ptr% - file_ptr%)*100 DIV old_time%)
5650 $status_crc% = "0"
5660ELSE
5670 was_downloading% = FALSE
5680 IF uploading% old_time% = TIME
5690 IF old_time%<=0 old_time% = 1
5700 SYS "OS_ConvertFileSize",file_length%,status_length%,12
5710 $status_bytes% = STR$(file_ptr% - file_block%)
5720 $status_rate% = STR$((file_ptr% - file_block%)*100 DIV old_time%)
5730 $status_crc% = STR$(crc_errors%)
5740ENDIF
5750
5760PROCselect_icon(status_window%,0,-uploading%)
5770PROCselect_icon(status_window%,1,-downloading%)
5780PROCupdate_icon(status_window%,2)
5790PROCupdate_icon(status_window%,3)
5800PROCupdate_icon(status_window%,4)
5810PROCupdate_icon(status_window%,9)
5820
5830ENDPROC
5840
5850------------------------------------------------------------------------
5860
5870DEF PROCnull_getting
5880
5890LOCAL new_bytes%,timeout%,byte%,flags%,got%
5900
5910SYS "OS_Byte",&80,&FE TO ,new_bytes%
5920IF new_bytes%=0 AND new_ptr%-file_ptr%=num_bytes% ENDPROC
5930
5940timeout% = TIME + 2*poll_time%
5950IF fast_load% timeout% += 98*poll_time%
5960
5970SYS "Hourglass_On":hourglass% = TRUE
5980
5990REPEAT
6000 SYS "OS_SerialOp",4 TO ,byte%;flags%
6010 IF (flags% AND 2)=0 ?new_ptr% = byte%:new_ptr% += 1
6020 IF new_ptr%-file_block%+10>file_block_length% ERROR 1,"Data overrun"
6030UNTIL (flags% AND 2) OR TIME>timeout%
6040
6050num_bytes% = new_ptr% - file_ptr%
6060num_crc_bytes% = num_bytes% - block_length%
6070
6080CASE TRUE OF
6090 WHEN getting_ok% AND num_bytes%>0 :got% = FNok
6100 WHEN shaking% AND num_bytes%>1 :got% = FNshake
6110 WHEN getting_file_length% AND num_bytes%>1 :got% = FNfile_length
6120 WHEN getting_end% AND num_bytes%>0 :got% = FNend
6130 WHEN getting_block_length% AND num_bytes%>2 :got% = FNblock_length
6140 WHEN getting_block% AND num_crc_bytes%>1 :got% = FNblock
6150 WHEN getting_file_name% AND num_bytes%>8 :got% = FNfile_name
6160 OTHERWISE :got% = 0
6170ENDCASE
6180
6190IF num_bytes%>got% AND got%>0 THEN
6200 FOR new_ptr%=file_ptr% TO file_ptr%+num_bytes%-got%-1
6210 ?new_ptr% = new_ptr%?got%
6220 NEXT
6230ENDIF
6240new_ptr% = file_ptr% + num_bytes% - got%
6250
6260SYS "Hourglass_Off":hourglass% = FALSE
6270
6280ENDPROC
6290
6300------------------------------------------------------------------------
6310
6320DEF FNshake
6330
6340LOCAL i%
6350
6360IF ?file_ptr%<>ASC("S") OR file_ptr%?1<>ASC("B") THEN
6370 put_ptr% = file_ptr%:put_end_ptr% = put_ptr% + 1
6380 ?put_ptr% = ASC("x")
6390 putting% = TRUE
6400 = num_bytes%
6410ENDIF
6420
6430put_ptr% = new_ptr% - 2
6440?put_ptr% = ASC("s"):put_ptr%?1 = ASC("b")
6450
6460IF $name_ptr%="" THEN
6470 IF load_bget% THEN put_ptr%?2 = &03 ELSE put_ptr%?2 = &0C
6480 put_end_ptr% = put_ptr% + 3
6490 shaking% = FALSE:putting% = TRUE
6500 getting_ok% = TRUE :getting_file_length% = TRUE
6510ELSE
6520 put_ptr%?2 = &30
6530 FOR i%=0 TO LEN($name_ptr%):put_ptr%?(i%+3) = name_ptr%?i%:NEXT
6540 put_end_ptr% = put_ptr% + 4 + LEN($name_ptr%)
6550 $name_ptr% = ""
6560 putting% = TRUE:getting_ok% = TRUE
6570ENDIF
6580
6590= 2
6600
6610------------------------------------------------------------------------
6620
6630DEF FNok
6640
6650getting_ok% = FALSE
6660
6670IF FNbits(?file_ptr%)<6 THEN
6680 PROCmessage("Protocol error - transmission failed")
6700 PROCreset_all
6720 = 0
6721ENDIF
6730
6740IF last_button%=4 AND getting_file_length% THEN
6760 PROCmessage("Press play on tape recorder")
6770 last_button% = 0
6780ENDIF
6781
6790= 1
6820
6830------------------------------------------------------------------------
6840
6850DEF FNfile_length
6860
6870file_length% = ?file_ptr% + 256*file_ptr%?1
6880
6890getting_file_length% = FALSE
6900getting_end% = TRUE
6910
6920TIME = 0
6930
6940= 2
6950
6960------------------------------------------------------------------------
6970
6980DEF FNend
6990
7000PROCupdate_status
7010
7020IF FNbits(?file_ptr%)<6 THEN
7030 modified% = TRUE
7040 getting_file_name% = TRUE
7050 IF do_crlf% PROCdo_crlf
7060 PROCreport_completion
7070ELSE
7080 getting_block_length% = TRUE
7090ENDIF
7100
7110getting_end% = FALSE
7120
7130= 1
7140
7150------------------------------------------------------------------------
7160
7170DEF PROCreport_completion
7180
7190LOCAL report$
7200
7210IF one_shot% report$ = "Transfer completed"
7220
7230IF crc_errors%>0 THEN
7240 IF report$<>"" report$ += " with "
7250 report$ += STR$(crc_errors%) + " CRC errors during load"
7260 one_shot% = TRUE
7270 crc_errors% = 0
7280ENDIF
7290
7300IF file_ptr%-file_block%<>file_length% THEN
7310 IF report$<>"" THEN report$ += "; data" ELSE report$ += "Data"
7320 report$ += " may have been lost"
7330 one_shot% = TRUE
7340ENDIF
7350
7360IF report$<>"" PROCmessage(report$)
7370
7380ENDPROC
7390
7400------------------------------------------------------------------------
7410
7420DEF FNblock_length
7430
7440block_length% = FNvote(?file_ptr%,file_ptr%?1,file_ptr%?2)
7450IF block_length%<0 block_length% = 0:= 0
7460IF block_length%=0 block_length% = 256
7470
7480getting_block_length% = FALSE
7490getting_block% = TRUE
7500
7510= 3
7520
7530------------------------------------------------------------------------
7540
7550DEF FNvote(l1%,l2%,l3%)
7560
7570IF l1%=l2% AND l1%=l3% = l1%
7580
7590IF l1%=l2% crc_errors% += 1: = l1%
7600IF l1%=l3% crc_errors% += 1: = l1%
7610IF l2%=l3% crc_errors% += 1: = l2%
7620
7630IF FNconfirm("Serious protocol error; continue?") = 0
7640
7650PROCreset_state
7660
7670original_file_name$ = "<corrupt>"
7680
7690= -1
7700
7710------------------------------------------------------------------------
7720
7730DEF FNblock
7740
7750LOCAL A%,B%,crc_ptr%
7760
7770A% = file_ptr%
7780B% = block_length%
7790CALL crc%
7800
7810crc_ptr% = file_ptr% + block_length%
7820
7830IF ?crc_ptr%=?crc_hi AND crc_ptr%?1=?crc_lo THEN
7840 file_ptr% += block_length%
7850 put_ptr% = file_ptr%
7860 ?put_ptr% = 255
7870ELSE
7880 put_ptr% = file_ptr%
7890 ?put_ptr% = 0
7900 crc_errors% += 1
7910ENDIF
7920
7930put_end_ptr% = put_ptr% + 1
7940getting_block% = FALSE
7950putting% = TRUE
7960getting_end% = TRUE
7970
7980= num_bytes%
7990
8000------------------------------------------------------------------------
8010
8020DEF FNfile_name
8030
8040LOCAL fn_ptr%
8050
8060fn_ptr% = file_ptr% + 7
8070REPEAT fn_ptr% += 1:UNTIL ?fn_ptr%=&0D OR fn_ptr%=new_ptr%-1
8080IF ?fn_ptr%<>&0D = 0
8090
8100load% = (!file_ptr% AND &FFFF):$load_ptr% = STR$~load%
8110exec% = (file_ptr%!4 AND &FFFF):$exec_ptr% = STR$~exec%
8120
8130IF guess_type% PROCguess_type
8140
8150PROCget_file_type
8160
8170original_file_name$ = $(file_ptr%+8)
8180
8190$save_ptr% = FNfile_valid($(file_ptr%+8))
8200
8210getting_file_name% = FALSE
8220
8230IF NOT one_shot% PROCsave_file("<BBCTape$Dir>.BBCFiles."+$save_ptr%,TRUE)
8240
8250IF one_shot% THEN
8260 PROCreset_state
8270ELSE
8280 PROCstart_upload(0)
8290ENDIF
8300
8310= 0
8320
8330------------------------------------------------------------------------
8340
8350DEF PROCguess_type
8360
8370CASE TRUE OF
8380 WHEN load%>&C000 :$type_ptr% = "Text"
8390 WHEN load%>&8000 :$type_ptr% = "BBC ROM"
8400 WHEN exec%>&C000 :$type_ptr% = "Data"
8410 WHEN exec%>&8000 :$type_ptr% = "BASIC"
8420 OTHERWISE $type_ptr% = "Data"
8430ENDCASE
8440
8450ENDPROC
8460
8470------------------------------------------------------------------------
8480
8490DEF FNfile_valid(name$)
8500
8510FOR i%=1 TO LEN(name$)
8520 IF FNbad_char(MID$(name$,i%,1)) MID$(name$,i%,1) = "?"
8530NEXT
8540
8550name$ = LEFT$(name$,10)
8560
8570= name$
8580
8590------------------------------------------------------------------------
8600
8610DEF FNbad_char(char$)
8620
8630IF char$<"!" = TRUE
8640IF char$>"~" = TRUE
8650IF char$>"""" AND char$<"'" = TRUE
8660IF char$="*" = TRUE
8670IF char$="." = TRUE
8680IF char$=":" = TRUE
8690IF char$="<" = TRUE
8700IF char$=">" = TRUE
8710IF char$="@" = TRUE
8720IF char$="^" = TRUE
8730IF char$="\" = TRUE
8740 = FALSE
8750
8760------------------------------------------------------------------------
8770
8780DEF FNbits(byte%)
8790
8800LOCAL num%
8810
8820num% = 0
8830FOR bit%=0 TO 7
8840 IF byte% AND (1<<bit%) num% += 1
8850NEXT
8860
8870= num%
8880
8890************************************************************************
8900
8910Routines to deal with events from the polling loop
8920
8930************************************************************************
8940
8950DEF PROCmouse_click
8960
8970LOCAL x%,y%,b%,window%,icon%
8980
8990x% = !wimp_block% :y% = wimp_block%!4:b% = wimp_block%!8
9000window% = wimp_block%!12:icon% = wimp_block%!16
9010
9020CASE TRUE OF
9030 WHEN b%=2 :IF window%=-2 y% = 96 + 44*num_menu_items%(0) + 24
9040 SYS "Wimp_CreateMenu",,menu_block%(0),x%-64,y%
9050 WHEN window%=-2 :PROCupdate_status:PROCopen_window(status_window%)
9060 WHEN window%=saveas%
9070 CASE icon% OF
9080 WHEN 0 :IF b%>15 PROCstart_drag(window%,icon%,b%):saving% = TRUE
9090 WHEN 2 :PROCsave_file($save_ptr%,TRUE)
9100 IF b%>1 SYS "Wimp_CreateMenu",,-1
9110 ENDCASE
9120ENDCASE
9130
9140ENDPROC
9150
9160------------------------------------------------------------------------
9170
9180DEF PROCstart_drag(window%,icon%,button%)
9190
9200LOCAL bx%,by%
9210
9220drag_button% = button%
9230
9240!wimp_block% = window%
9250SYS "Wimp_GetWindowState",,wimp_block%
9260
9270bx% = wimp_block%!4 - wimp_block%!20
9280by% = wimp_block%!16 - wimp_block%!24
9290wimp_block%!4 = icon%
9300SYS "Wimp_GetIconState",,wimp_block%
9310
9320wimp_block%!4 = 5
9330wimp_block%!8 += bx%
9340wimp_block%!12 += by%
9350wimp_block%!16 += bx%
9360wimp_block%!20 += by%
9370wimp_block%!24 = 0
9380wimp_block%!28 = 0
9390wimp_block%!32 = screen_x%
9400wimp_block%!36 = screen_y%
9410SYS "Wimp_DragBox",,wimp_block%
9420
9430ENDPROC
9440
9450------------------------------------------------------------------------
9460
9470DEF PROCuser_drag_box
9480
9490LOCAL x%,y%,window%,icon%
9500
9510IF NOT saving% ENDPROC
9520
9530SYS "Wimp_GetPointerInfo",,wimp_block%
9540x% = !wimp_block% :y% = wimp_block%!4
9550window% = wimp_block%!12:icon% = wimp_block%!16
9560
9570saving% = FALSE
9580transmit_ptr% = file_block%
9590
9600PROCget_file_type
9610
9620!wimp_block% = 256
9630wimp_block%!12 = 0 :wimp_block%!16 = 1
9640wimp_block%!20 = window% :wimp_block%!24 = icon%
9650wimp_block%!28 = x% :wimp_block%!32 = y%
9660wimp_block%!36 = file_ptr% - file_block%
9670wimp_block%!40 = file_type%
9680$(wimp_block%+44) = FNleaf_name($save_ptr%) + CHR$0
9690SYS "Wimp_SendMessage",17,wimp_block%,window%,icon%
9700
9710ENDPROC
9720
9730------------------------------------------------------------------------
9740
9750DEF FNleaf_name(path$)
9760
9770LOCAL i%,char$
9780
9790i% = LEN(path$)
9800REPEAT
9810 i% -= 1
9820 char$ = MID$(path$,i%,1)
9830UNTIL char$="." OR char$=":" OR i%=1
9840
9850IF char$="." OR char$=":" = MID$(path$,i%+1)
9860
9870= path$
9880
9890------------------------------------------------------------------------
9900
9910DEF PROCmenu_selection
9920
9930LOCAL item%,sub_item%,button%
9940
9950item% = !wimp_block%:sub_item% = wimp_block%!4:IF item%<0 ENDPROC
9960
9970SYS "Wimp_GetPointerInfo",,wimp_block%
9980button% = wimp_block%!8
9990
10000CASE menu$(item%,0) OF
10010 WHEN "Misc"
10020 IF sub_item%>=0 THEN
10030 CASE menu$(sub_item%,1) OF
10040 WHEN "Status ..." :PROCupdate_status
10050 PROCopen_window(status_window%)
10060 WHEN "9600, 8n1" :SYS "OS_SerialOp",1,0
10070 SYS "OS_SerialOp",5,0
10080 SYS "OS_SerialOp",6,0
10090 WHEN "Reset" :PROCreset_state
10100 WHEN "Clear" :PROCreset_all
10110 ENDCASE
10120 ENDIF
10130 WHEN "Save" :PROCget_file_type:PROCsave_file($save_ptr%,TRUE)
10140 WHEN "Options"
10150 IF sub_item%>=0 THEN
10160 CASE menu$(sub_item%,2) OF
10170 WHEN "File type"
10180 IF load_exec% THEN
10190 load_exec% = FALSE
10200 PROCmenu_tick(2,"File type",1)
10210 PROCmenu_tick(2,"Load address",0)
10220 PROCmenu_tick(2,"Exec address",0)
10230 ENDIF
10240 WHEN "Load address","Exec address"
10250 IF NOT load_exec% THEN
10260 load_exec% = TRUE
10270 PROCmenu_tick(2,"File type",0)
10280 PROCmenu_tick(2,"Load address",1)
10290 PROCmenu_tick(2,"Exec address",1)
10300 ENDIF
10310 WHEN "CR � LF" :do_crlf% = do_crlf% EOR TRUE
10320 PROCmenu_tick_toggle(2,"CR � LF")
10330 IF modified% OR NOT uploading% PROCdo_crlf
10340 WHEN "Guess type" :guess_type% = guess_type% EOR TRUE
10350 PROCmenu_tick_toggle(2,"Guess type")
10360 IF guess_type% PROCguess_type
10370 WHEN "Auto load" :one_shot% = one_shot% EOR TRUE
10380 PROCmenu_tick_toggle(2,"Auto load")
10390 WHEN "Fast load" :fast_load% = fast_load% EOR TRUE
10400 PROCmenu_tick_toggle(2,"Fast load")
10410 WHEN "Use BGET" :load_bget% = load_bget% EOR TRUE
10420 PROCmenu_tick_toggle(2,"Use BGET")
10430 ENDCASE
10440 ENDIF
10450 WHEN "Upload" :PROCstart_upload(button%)
10460 WHEN "Download" :PROCstart_download(button%)
10470 WHEN "Quit" :PROCexit(FALSE)
10480ENDCASE
10490
10500IF button%=1 SYS "Wimp_CreateMenu",,menu_block%(0)
10510
10520ENDPROC
10530
10540------------------------------------------------------------------------
10550
10560DEF PROCdo_crlf
10570
10580LOCAL ptr%
10590
10600FOR ptr%=file_block% TO file_ptr%-1
10610 IF ?ptr%=&0A THEN ?ptr%=&0D ELSE IF ?ptr%=&0D ?ptr%=&0A
10620NEXT
10630
10640crlf_done% = crlf_done% EOR TRUE
10650
10660ENDPROC
10670
10680------------------------------------------------------------------------
10690
10700DEF PROCstart_upload(button%)
10710
10720PROCreset_all
10730
10740last_button% = button%
10750
10760put_ptr% = file_ptr%
10770?put_ptr% = ASC("x")
10780put_end_ptr% = put_ptr% +1
10790putting% = TRUE
10800shaking% = TRUE
10810uploading% = TRUE
10820poll_mask% = poll_mask% AND &FFFFFFFE
10830
10840PROCmenu_shade(0,"Download",TRUE)
10850PROCmenu_shade(0,"Upload",TRUE)
10860PROCupdate_status
10870
10880ENDPROC
10890
10900------------------------------------------------------------------------
10910
10920DEF PROCstart_download(button%)
10930
10940LOCAL flag%,length%,report$
10950
10960SYS "OS_File",17,"<BBCTape$Dir>.BBCLoadBT" TO ,,,,length%
10970
10980IF length%>file_block_length% PROCmessage("Can't download file - no room"):ENDPROC
10990
11000IF length%>file_block_length%-(file_ptr%-file_block%) THEN
11010 IF modified% THEN report$ = "Unsaved d" ELSE report$ = "D"
11020 report$ += "ata will be destroyed; continue?"
11030 IF NOT FNconfirm(report$) ENDPROC
11040 PROCreset_all
11050ELSE
11060 PROCreset_state
11070ENDIF
11080
11090OSCLI "Load <BBCTape$Dir>.BBCLoadBT " + STR$~file_ptr%
11100
11110IF button%=4 PROCmessage("Type ""*FX 2,1"" on BBC keyboard")
11120
11130put_ptr% = file_ptr%
11140put_end_ptr% = put_ptr% + length%
11150putting% = TRUE
11160downloading% = TRUE
11170poll_mask% = poll_mask% AND &FFFFFFFE
11180TIME = 0
11190
11200PROCmenu_shade(0,"Upload",TRUE)
11210PROCupdate_status
11220
11230ENDPROC
11240
11250------------------------------------------------------------------------
11260
11270DEF PROCuser_message
11280
11290CASE wimp_block%!16 OF
11300 WHEN 0 :PROCexit(TRUE)
11310 WHEN 2 :PROCdata_save_ack
11320 WHEN 4 :saved_file$ = "<BBCTape$Dir>.xxxxxxxxxx"
11330 WHEN 6 :PROCram_fetch
11340 WHEN 8 :IF modified% PROCpre_quit
11350 WHEN &400C0 :PROCget_file_type
11360 PROCsave_window
11370 IF wimp_block%!20=fileinfo% PROCfile_info
11380 SYS "Wimp_CreateSubMenu",,wimp_block%!20,wimp_block%!24,wimp_block%!28
11390 WHEN &400C1 :PROCmode_change
11400ENDCASE
11410
11420ENDPROC
11430
11440------------------------------------------------------------------------
11450
11460DEF PROCdata_save_ack
11470
11480LOCAL ptr%,safe%
11490
11500ptr% = wimp_block% + 43
11510REPEAT ptr% += 1:UNTIL ?ptr%=0
11520?ptr% = 13
11530
11540IF wimp_block%!36=-1 THEN safe% = FALSE ELSE safe% = TRUE
11550
11560PROCsave_file($(wimp_block%+44),safe%)
11570
11580saved_file$ = $(wimp_block%+44)
11590
11600IF drag_button%>16 SYS "Wimp_CreateMenu",,-1
11610
11620wimp_block%!12 = wimp_block%!8
11630wimp_block%!16 = 3
11640SYS "Wimp_SendMessage",18,wimp_block%,wimp_block%!4
11650
11660ENDPROC
11670
11680------------------------------------------------------------------------
11690
11700DEF PROCsave_file(name$,safe%)
11710
11720LOCAL exists%
11730
11740IF file_ptr%<=file_block% PROCmessage("No file loaded"):ENDPROC
11750
11760IF INSTR(name$,".")=0 AND INSTR(name$,"<")=0 THEN
11770 PROCmessage("To save, drag the file icon to a directory viewer")
11780 ENDPROC
11790ENDIF
11800
11810SYS "OS_File",17,name$ TO exists%
11820IF exists% THEN
11830 IF NOT FNconfirm("File "+name$+" exists; overwrite?") THEN
11840 IF NOT one_shot% one_shot% = TRUE:PROCmenu_tick(2,"Auto load",0)
11850 ENDPROC
11860 ENDIF
11870ENDIF
11880
11890OSCLI "Save " + name$ + " " + STR$~(file_block%) + " " + STR$~(file_ptr%)
11900
11910IF load_exec% THEN
11920 SYS "OS_File",1,name$,load%,exec%,,%11
11930ELSE
11940 SYS "OS_File",18,name$,file_type%
11950ENDIF
11960
11970IF safe% modified% = FALSE:$save_ptr% = name$
11980
11990ENDPROC
12000
12010------------------------------------------------------------------------
12020
12030DEF PROCram_fetch
12040
12050IF drag_button%>16 SYS "Wimp_CreateMenu",,-1:drag_button% = 0
12060
12070IF wimp_block%!24>file_ptr%-transmit_ptr% wimp_block%!24 = file_ptr% - transmit_ptr%
12080
12090IF wimp_block%!24>0 SYS "Wimp_TransferBlock",task_handle%,transmit_ptr%,wimp_block%!4,wimp_block%!20,wimp_block%!24
12100
12110transmit_ptr% += wimp_block%!24
12120
12130wimp_block%!12 = wimp_block%!8
12140wimp_block%!16 = 7
12150SYS "Wimp_SendMessage",17,wimp_block%,wimp_block%!4
12160
12170ENDPROC
12180
12190------------------------------------------------------------------------
12200
12210DEF PROCpre_quit
12220
12230LOCAL quit_task%
12240
12250quit_task% = wimp_block%!4
12260
12270wimp_block%!12 = wimp_block%!8
12280SYS "Wimp_SendMessage",19,wimp_block%,quit_task%
12290
12300IF NOT FNconfirm("Unsaved data: are you sure you want to Quit?") ENDPROC
12310
12320modified% = FALSE
12330
12340REM This is the approved method of dealing with a pre-quit, but
12350REM doesn't deal correctly with a quit from the task window
12360
12370SYS "Wimp_GetCaretPosition",,wimp_block%
12380wimp_block%!24 = &1FC
12390SYS "Wimp_SendMessage",8,wimp_block%,quit_task%
12400
12410ENDPROC
12420
12430------------------------------------------------------------------------
12440
12450DEF PROCsave_window
12460
12470LOCAL flags%,type$
12480
12490IF file_type%>0 THEN
12500 SYS "XWimp_SpriteOp",40,,"file_"+STR$~file_type% TO ;flags%
12510 IF flags% AND 1 THEN type$ = "xxx" ELSE type$ = STR$~file_type%
12520ELSE
12530 type$ = "xxx"
12540ENDIF
12550
12560wimp_block%!32 = saveas%
12570SYS "Wimp_DeleteWindow",,wimp_block%+32
12580
12590$(saveas_block%+88+25) = type$
12600
12610SYS "Wimp_CreateWindow",,saveas_block% TO saveas%
12620
12630ENDPROC
12640
12650------------------------------------------------------------------------
12660
12670DEF PROCfile_info
12680
12690LOCAL saved$,flags%,crlf$
12700
12710wimp_block%!32 = fileinfo%
12720SYS "Wimp_DeleteWindow",,wimp_block%+32
12730
12740REM File type icon
12750$(fileinfo_block%+108+6*32) = $(saveas_block%+108)
12760
12770IF modified% THEN saved$ = "No" ELSE saved$ = "Yes"
12780$(fileinfo_block%+108+2*32) = saved$
12790
12800IF file_type%>0 THEN
12810 $type_buffer% = $type_ptr% + STRING$(9-LEN($type_ptr%)," ")
12820 SYS "OS_ConvertHex4",file_type%,type_buffer%+9,5
12830 type_buffer%?9 = ASC("(")
12840 type_buffer%?13 = ASC(")")
12850 type_buffer%?14 = &0D
12860ELSE
12870 $type_buffer% = "<untyped>"
12880ENDIF
12890
12900SYS "OS_ConvertHex4",load%,fileinfo_block%+108+32,12
12910SYS "OS_ConvertHex4",exec%,fileinfo_block%+108+12*32,12
12920
12930$(fileinfo_block%+108+10*32) = LEFT$(original_file_name$,10)
12940
12950SYS "OS_ConvertFileSize",file_ptr%-file_block%,fileinfo_block%+108+14*32,12
12960
12970IF crlf_done% THEN crlf$ = "yes" ELSE crlf$ = "no"
12980$(fileinfo_block%+108+15*32) = crlf$
12990
13000SYS "Wimp_CreateWindow",,fileinfo_block% TO fileinfo%
13010
13020ENDPROC
13030
13040------------------------------------------------------------------------
13050
13060DEF PROCmode_change
13070
13080!wimp_block% = 4:wimp_block%!4 = 5
13090wimp_block%!8 = 11:wimp_block%!12 = 12
13100wimp_block%!16 = -1
13110SYS "OS_ReadVduVariables",wimp_block%,wimp_block%+20
13120
13130screen_x% = (1 << wimp_block%!20)*(wimp_block%!28 + 1)
13140screen_y% = (1 << wimp_block%!24)*(wimp_block%!32 + 1)
13150
13160ENDPROC
13170
13180************************************************************************
13190
13200Wimp Utilities
13210
13220************************************************************************
13230
13240DEF PROCopen_window(handle%)
13250
13260!wimp_block% = handle%
13270SYS "Wimp_GetWindowState",,wimp_block%
13280wimp_block%!28 = -1
13290
13300SYS "Wimp_OpenWindow",,wimp_block%
13310
13320ENDPROC
13330
13340------------------------------------------------------------------------
13350
13360DEF PROCclose_window(window%)
13370
13380!wimp_block% = window%
13390SYS "Wimp_CloseWindow",,wimp_block%
13400
13410ENDPROC
13420
13430------------------------------------------------------------------------
13440
13450DEF PROCbuild_menu(block%,title$,width%)
13460
13470$block% = title$
13480block%?12 = 7
13490block%?13 = 2
13500block%?14 = 7
13510block%?15 = 0
13520block%!16 = 16*width%
13530block%!20 = 44
13540block%!24 = 0
13550
13560ENDPROC
13570
13580------------------------------------------------------------------------
13590
13600DEF PROCbuild_menu_items(block%,num%,nsub%)
13610
13620LOCAL i%,text$,tick%,shade%,dot%,notify%,sub%,last%,ptr%
13630
13640FOR i%=0 TO num%-1
13650 READ text$,tick%,shade%,dot%,notify%,sub%
13660 menu$(i%,nsub%) = text$
13670 IF i%=num%-1 last% = 1 ELSE last% = 0
13680 ptr% = block% + 28 + 24*i%
13690 PROCmenu_item(ptr%,tick%,shade%,dot%,notify%,last%,sub%,text$)
13700NEXT
13710
13720ENDPROC
13730
13740------------------------------------------------------------------------
13750
13760DEF PROCmenu_item(block%,tick%,shade%,dot%,notify%,last%,sub%,text$)
13770
13780!block% = tick% + (dot%<<1) + (notify%<<3) + (last%<<7)
13790block%!4 = sub%
13800block%!8 = 1 + (1<<5) + (shade%<<22) + (7<<24)
13810
13820IF LEN(text$)<=12 THEN
13830 $(block%+12) = text$
13840ELSE
13850 DIM xxx% LEN(text$)
13860 $xxx% = text$
13870 block%!8 = block%!8 OR (1<<8)
13880 block%!12 = xxx%
13890 block%!16 = -1
13900 block%!20 = LEN(text$) + 1
13910ENDIF
13920
13930ENDPROC
13940
13950------------------------------------------------------------------------
13960
13970DEF PROCwriteable_menu(block%,title$,width%,cent%,buff%,len%,val%)
13980
13990$block% = title$
14000block%?12 = 7
14010block%?13 = 2
14020block%?14 = 7
14030block%?15 = 0
14040block%!16 = 16*width%
14050block%!20 = 44
14060block%!24 = 0
14070
14080block%!28 = (1<<2) + (cent%<<3) + (1<<7)
14090block%!32 = -1
14100block%!36 = 1 + (1<<5) + (1<<8) + (7<<24)
14110block%!40 = buff%
14120block%!44 = val%
14130block%!48 = len%
14140
14150ENDPROC
14160
14170------------------------------------------------------------------------
14180
14190DEF PROCmenu_tick(menu%,name$,set%)
14200
14210LOCAL item%
14220
14230item% = FNmenu_item_number(menu%,name$)
14240
14250IF item%>=0 PROCmenu_tick_item(menu_block%(menu%),item%,set%)
14260
14270ENDPROC
14280
14290------------------------------------------------------------------------
14300
14310DEF PROCmenu_tick_toggle(menu%,name$)
14320
14330LOCAL item%
14340
14350item% = FNmenu_item_number(menu%,name$)
14360
14370IF item%>=0 PROCmenu_tick_toggle_item(menu_block%(menu%),item%)
14380
14390ENDPROC
14400
14410------------------------------------------------------------------------
14420
14430DEF PROCmenu_shade(menu%,name$,set%)
14440
14450LOCAL item%
14460
14470item% = FNmenu_item_number(menu%,name$)
14480
14490IF item%>=0 PROCmenu_shade_item(menu_block%(menu%),item%,set%)
14500
14510ENDPROC
14520
14530------------------------------------------------------------------------
14540
14550DEF PROCmenu_shade_toggle(menu%,name$)
14560
14570LOCAL item%
14580
14590item% = FNmenu_item_number(menu%,name$)
14600
14610IF item%>=0 PROCmenu_shade_toggle_item(menu_block%(menu%),item%)
14620
14630ENDPROC
14640
14650------------------------------------------------------------------------
14660
14670DEF FNmenu_item_number(menu%,name$)
14680
14690LOCAL max_item%,item%
14700
14710IF menu%>DIM(menu$(),2) = -1
14720
14730max_item% = DIM(menu$(),1)
14740
14750item% = 0
14760WHILE item%<max_item% AND menu$(item%,menu%)<>name$
14770 item% += 1
14780ENDWHILE
14790
14800IF menu$(item%,menu%)=name$ = item%
14810
14820= -1
14830
14840------------------------------------------------------------------------
14850
14860DEF PROCmenu_tick_item(block%,item%,set%)
14870
14880LOCAL offset%
14890
14900offset% = 28 + 24*item%
14910
14920IF set% THEN
14930 block%?offset% = block%?offset% OR %00000001
14940ELSE
14950 block%?offset% = block%?offset% AND %11111110
14960ENDIF
14970
14980ENDPROC
14990
15000------------------------------------------------------------------------
15010
15020DEF PROCmenu_tick_toggle_item(block%,item%)
15030
15040LOCAL offset%
15050
15060offset% = 28 + 24*item%
15070
15080block%?offset% = block%?offset% EOR %00000001
15090
15100ENDPROC
15110
15120------------------------------------------------------------------------
15130
15140DEF PROCmenu_shade_item(block%,item%,set%)
15150
15160LOCAL offset%
15170
15180offset% = 28 + 24*item% + 10
15190
15200IF set% THEN
15210 block%?offset% = block%?offset% OR %01000000
15220ELSE
15230 block%?offset% = block%?offset% AND %10111111
15240ENDIF
15250
15260ENDPROC
15270
15280------------------------------------------------------------------------
15290
15300DEF PROCmenu_shade_toggle_item(block%,item%)
15310
15320LOCAL offset%
15330
15340offset% = 28 + 24*item% + 10
15350
15360block%?offset% = block%?offset% EOR %01000000
15370
15380ENDPROC
15390
15400------------------------------------------------------------------------
15410
15420DEF PROCselect_icon(window%,icon%,set%)
15430
15440!wimp_block% = window%
15450wimp_block%!4 = icon%
15460wimp_block%!8 = set%<<21
15470wimp_block%!12 = 1<<21
15480SYS "Wimp_SetIconState",,wimp_block%
15490
15500ENDPROC
15510
15520------------------------------------------------------------------------
15530
15540DEF PROCupdate_icon(window%,icon%)
15550
15560!wimp_block% = window%
15570wimp_block%!4 = icon%
15580wimp_block%!8 = 0
15590wimp_block%!12 = 0
15600SYS "Wimp_SetIconState",,wimp_block%
15610
15620ENDPROC
� > <BBCTape$Dir>.!RunImage
� � �
(
2app_name$ = "BBCTape"
<
F� task% 4:$task% = "TASK"
P=ș "Wimp_Initialise",200,!task%,app_name$ � ,task_handle%
Z
d� � �error(�)
n
x�wimp_init
��prog_init
�
�� � �error(�)
�
�8� Minimise memory consumption (current end + 1 page)
�� = � + 8*1024
�
�*ș "OS_ReadMonotonicTime" � idle_time%
�idle_time% += poll_time%
�
��
�B ș "Wimp_PollIdle",poll_mask%,wimp_block%,idle_time% � code%
� Ȏ code% �
; � 0 :� putting% � �null_putting � �null_getting
: ș "OS_ReadMonotonicTime" � idle_time%
, idle_time% += poll_time%
"2 � 2 :ș "Wimp_OpenWindow",,wimp_block%
,3 � 3 :ș "Wimp_CloseWindow",,wimp_block%
6 � 6 :�mouse_click
@ � 7 :�user_drag_box
J4 � 8 :ș "Wimp_ProcessKey",wimp_block%!24
T � 9 :�menu_selection
^ � 17,18 :�user_message
h% � 19 :� wimp_block%!16=3 �
r0 ș "OS_File",6,saved_file$
|E �message("Data transfer failed: Receiver died")
� �
� �
�� pigs_can_fly%
�
��exit(�)
�
��
�
�L------------------------------------------------------------------------
�
�� �exit(must%)
�
�<� If must% is TRUE we must exit, even with unsaved files
2� hourglass% ș "Hourglass_Off":hourglass% = �
&X� modified% � � must% � � �confirm("Unsaved data: are you sure you want to Quit?") �
0
:!� Clear out the RS423 buffers
D *FX 2
N*FX 21 1
X*FX 21 2
b
l+ș "Wimp_CloseDown",task_handle%,!task%
v
��
�
�L------------------------------------------------------------------------
�
�� �error(quit%)
�
�
� report$
�
�� �:� � �exit(�)
�
�;� Disk not found/not present - filer provides error box
�� �=&108D4 � �=&108D5 �
�
!string_buffer% = �
8report$ = �$ + " (internal error code " + �(�) + ")"
,$(string_buffer%+4) = �report$,250) + �0
*4ș "Wimp_ReportError",string_buffer%,1,app_name$
4
>� quit% �exit(�)
H
R�reset_state
\
f�
p
zL------------------------------------------------------------------------
�
�� �confirm(message$)
�
�� mask%,code%,end%,yes%
�
�� �
�M� � � �:ȗ ȓ 0,0,screen_x%,screen_y%:�close_window(error_window%):� �,�$
�
�#� hourglass% ș "Hourglass_Off"
�
� $error_ptr% = �message$,255)
�
��open_window(error_window%)
+ș "Wimp_GetWindowOutline",,wimp_block%
cȗ ȓ wimp_block%!4,wimp_block%!8,wimp_block%!12-wimp_block%!4-1,wimp_block%!16-wimp_block%!8-1
$
.1mask% = 1 + (%11<<4) + (%11<<11) + (%111<<17)
8
end% = �
B
L�
V. ș "Wimp_Poll",mask%,wimp_block% � code%
` Ȏ code% �
j$ � 6 :end% = �yes_or_no(yes%)
t3 � 8 :� wimp_block%!24=&1B end% = �:yes% = �
~ �
�
� end%
�
�!ȗ ȓ 0,0,screen_x%,screen_y%
� �close_window(error_window%)
�
�"� hourglass% ș "Hourglass_On"
�
�
= yes%
�
�L------------------------------------------------------------------------
�
�� �yes_or_no(� yes%)
yes% = �
'� wimp_block%!12<>error_window% = �
($� wimp_block%!16=1 yes% = �: = �
2� wimp_block%!16=4 = �
<
F= �
P
ZL------------------------------------------------------------------------
d
n� �message(message$)
x
�#� hourglass% ș "Hourglass_Off"
�
�=ș "Wimp_ReportError"," "+message$+�0,%10001,app_name$
�
�"� hourglass% ș "Hourglass_On"
�
��
�
�L************************************************************************
�
�Initialisation
�
�L************************************************************************
� �wimp_init
")� wimp_block% 1023,string_buffer% 255
,� saveas_block% 88 + 3*32
6 � fileinfo_block% 88 + 17*32
@
J� Initialise various flags
T'hourglass% = �:saving% = �
^'modified% = �:pigs_can_fly% = �
hDusing_scrap% = -1 :saved_file$ = "<BBCTape$Dir>.xxxxxxxxxx"
rversion$ = "19 Mar"
|
�� Get the screen size
�+!wimp_block% = 4:wimp_block%!4 = 5
�+wimp_block%!8 = 11:wimp_block%!12 = 12
�wimp_block%!16 = -1
�7ș "OS_ReadVduVariables",wimp_block%,wimp_block%+20
�:screen_x% = (1 << wimp_block%!20)*(wimp_block%!28 + 1)
�:screen_y% = (1 << wimp_block%!24)*(wimp_block%!32 + 1)
�
�E� Mask out null, pointer leaving/entering window, lose/gain caret
�9poll_mask% = 1 + (%11<<4) + (%11<<11):poll_time% = 10
�
�
�icon_bar
�load_templates
&�create_menu
0
: �info
D
N�
X
bL------------------------------------------------------------------------
l
v� �icon_bar
�
�!wimp_block% = -2
�+wimp_block%!4 = 0:wimp_block%!8 = 0
�+wimp_block%!12 = 68:wimp_block%!16 = 68
�!� Sprite, click notifies once
�%wimp_block%!20 = (1<<1) + (3<<12)
�'$(wimp_block%+24) = "!" + app_name$
�
�%ș "Wimp_CreateIcon",,wimp_block%
�
��
�
�L------------------------------------------------------------------------
� �load_templates
� name%,ptr%,ind_buffer%,i%
*
4� name% 12,ind_buffer% 1023
>
H?ș "Wimp_OpenTemplate",,"<" + app_name$ + "$Dir>.Templates"
R
\� Save dialogue box
f$name% = "saveas"
pXș "Wimp_LoadTemplate",,wimp_block%,ind_buffer%,ind_buffer%+1023,-1,name%,0 � ,,ptr%
z� i%=0 � 88+3*32-1
�' saveas_block%!i% = wimp_block%!i%
��
�!save_ptr% = saveas_block%!140
�3ș "Wimp_CreateWindow",,saveas_block% � saveas%
�
�� File information
�$name% = "fileInfo"
�Qș "Wimp_LoadTemplate",,wimp_block%,ptr%,ind_buffer%+1023,-1,name%,0 � ,,ptr%
�� i%=0 � 88+17*32-1
�) fileinfo_block%!i% = wimp_block%!i%
��
�,fileinfo_block%!(108+4*32) = save_ptr%
�4fileinfo_block%!(108+4*32+8) = saveas_block%!148
-type_buffer% = fileinfo_block%!(108+3*32)
7ș "Wimp_CreateWindow",,fileinfo_block% � fileinfo%
$� yes/no error box
.$name% = "error"
8Qș "Wimp_LoadTemplate",,wimp_block%,ptr%,ind_buffer%+1023,-1,name%,0 � ,,ptr%
B error_ptr% = wimp_block%!108
L7ș "Wimp_CreateWindow",,wimp_block% � error_window%
V
`� Program info box
j$name% = "proginfo"
tQș "Wimp_LoadTemplate",,wimp_block%,ptr%,ind_buffer%+1023,-1,name%,0 � ,,ptr%
~?$(wimp_block%!236) = �"1.00 (25-Feb-1991)",wimp_block%!244)
�3ș "Wimp_CreateWindow",,wimp_block% � proginfo%
�
�� Status window
�$name% = "status"
�Hș "Wimp_LoadTemplate",,wimp_block%,ptr%,ind_buffer%+1023,-1,name%,0
�+status_length% = wimp_block%!(108+2*32)
�+status_bytes% = wimp_block%!(108+3*32)
�+status_rate% = wimp_block%!(108+4*32)
�+status_crc% = wimp_block%!(108+9*32)
�8ș "Wimp_CreateWindow",,wimp_block% � status_window%
�
�ș "Wimp_CloseTemplate"
�
L------------------------------------------------------------------------
(
2� �create_menu
<
F� i%,name$,width%,temp%
P
Z!� name_block% 52,name_ptr% 10
d!� type_block% 52,type_ptr% 8
n/� load_block% 52,load_ptr% 4,hex_valid% 10
x!� exec_block% 52,exec_ptr% 4
�
�$$name_ptr% = "":$type_ptr% = ""
�$$load_ptr% = "":$exec_ptr% = ""
�$hex_valid% = "a0-9a-fA-F"
�
�A�writeable_menu(name_block%,"File name",11,0,name_ptr%,11,-1)
�@�writeable_menu(type_block%,"File type",10,0,type_ptr%,9,-1)
�K�writeable_menu(load_block%,"Load address",13,0,load_ptr%,5,hex_valid%)
�K�writeable_menu(exec_block%,"Exec address",13,0,exec_ptr%,5,hex_valid%)
�
�� +0
�
�� menu_max%,len_menu_max%
$� menu$(len_menu_max%,menu_max%)
7� menu_block%(menu_max%),num_menu_items%(menu_max%)
"� i%=0 � menu_max%
,( � name$,num_menu_items%(i%),width%
6) � temp% 28 + 24*num_menu_items%(i%)
@ menu_block%(i%) = temp%
J/ �build_menu(menu_block%(i%),name$,width%)
T�
^
h� i%=0 � menu_max%
r? �build_menu_items(menu_block%(i%),num_menu_items%(i%),i%)
|�
�
�)� No. of menus - 1, length of longest
� � 2,8
�
�� Name, no. of items, width
�� "BBCTape",6,9
�� "Misc" ,6,11
�� "Options",8,13
�
�2� Item text, tick, shade, dot, notify, pointer
�
�+� "Misc" ,0,0,0,0,menu_block%(1)
�$� "Save" ,0,0,0,1,saveas%
+� "Options" ,0,0,0,0,menu_block%(2)
(� "Upload" ,0,0,0,0,name_block%
� "Download" ,0,0,1,0,-1
&� "Quit" ,0,0,0,0,-1
0
:&� "Info" ,0,0,0,0,proginfo%
D&� "File" ,0,0,0,1,fileinfo%
N� "Status ..." ,0,0,1,0,-1
X� "9600, 8n1" ,0,0,1,0,-1
b� "Reset" ,0,0,0,0,-1
l� "Clear" ,0,0,0,0,-1
v
�(� "File type" ,0,0,0,0,type_block%
�(� "Load address",1,0,0,0,load_block%
�(� "Exec address",1,0,1,0,exec_block%
�� "CR � LF" ,0,0,0,0,-1
�� "Guess type" ,0,0,0,0,-1
�� "Auto load" ,0,0,0,0,-1
�� "Fast load" ,1,0,0,0,-1
�� "Use BGET" ,0,0,0,0,-1
�
��
�
�L------------------------------------------------------------------------
�
� �info
� mask%,scroll%
*� ��$,5,6)<>version$ �
4
>-mask% = (%11<<4) + (%11<<11) + (%111<<17)
H
R�open_window(proginfo%)
\$ș "Wimp_Poll",mask%,wimp_block%
f
p�wait(200)
z
�!wimp_block% = proginfo%
�)ș "Wimp_GetWindowState",,wimp_block%
�
�� scroll%=1 � 300
� wimp_block%!24 = -scroll%
�' ș "Wimp_OpenWindow",,wimp_block%
�) ș "Wimp_Poll",mask%,wimp_block%+32
��
�
��wait(1000)
�
�� scroll%=300 � 0 � -1
� wimp_block%!24 = -scroll%
' ș "Wimp_OpenWindow",,wimp_block%
) ș "Wimp_Poll",mask%,wimp_block%+32
�
$
.�wait(200)
8
B�close_window(proginfo%)
L
V�
`
jL------------------------------------------------------------------------
t
~� �wait(time%)
�
�time% += �
�
�� � �>time%
�
��
�
�L------------------------------------------------------------------------
�
�� �prog_init
�
��assemble_crc
� Main data block
$file_block_length% = 32*1024 - 1
$� file_block% file_block_length%
(
2� Initial option settings
<"do_crlf% = �:one_shot% = �
F"load_bget% = �:load_exec% = �
P"guess_type% = �:fast_load% = �
Z
ddefault_file_type% = &FFF
n
xold_time% = 0
�
�� �reset_all
�
�2file_length% = 0 :file_ptr% = file_block%
�$crlf_done% = � :modified% = �
�-$load_ptr% = "FFFF":$exec_ptr% = "FFFF"
�
�%original_file_name$ = "<unknown>"
�
��get_file_type
�
�� �reset_state
�
+� Flush buffers and enable serial input
*FX 2
*FX 21 1
"*FX 21 2
,*FX 2 2
6
@� Pointers etc.
J.new_ptr% = file_ptr%:crc_errors% = 0
T.put_ptr% = file_ptr%:num_bytes% = 0
^.put_end_ptr% = file_ptr%:block_length% = 0
_last_button% = 0
h
r� State machine flags
|0putting% = �:shaking% = �
�0getting_ok% = �:getting_file_length% = �
�0getting_end% = �:getting_block_length% = �
�0getting_block% = �:getting_file_name% = �
�0downloading% = �:was_downloading% = �
�0uploading% = �:last_download% = �
�
�poll_mask% = poll_mask% � 1
�
��menu_shade(0,"Upload",�)
��menu_shade(0,"Download",�)
�
�$�select_icon(status_window%,0,0)
�$�select_icon(status_window%,1,0)
2� hourglass% ș "Hourglass_Off":hourglass% = �
&�
0
:L------------------------------------------------------------------------
D
N� �assemble_crc
X
b;� This takes 5.31 ms, vs 2.2 sec for the Basic version!
l
v@� ptr,length,bits,count,data,lo,hi,link,nbyt,bytloop,opt%,P%
�
�� crc% 100
�
�*ptr = 0:length = 1:bits = 2:count = 3
�+data = 4:lo = 5:hi = 6:link = 14
�
�� opt%=0 � 2 � 2
�
P% = crc%
�
[OPT opt%
� MOV hi,#0
� MOV lo,#0
� MOV count,#0
� .nbyt
& LDRB data,[ptr,count]
� hi,hi,data
MOV bits,#8
.bytloop
* TST hi,#&80
4 �NE hi,hi,#8
> �NE lo,lo,#&10
H" MOV lo,lo,LSL #1
R ADDNE lo,lo,#1
\" MOV hi,hi,LSL #1
f TST lo,#&100
p ADDNE hi,hi,#1
z" SUBS bits,bits,#1
� BNE bytloop
�
�$ ADD count,count,#1
�" CMP count,length
� BNE nbyt
�
� STRB lo,crc_lo
� STRB hi,crc_hi
� MOV PC,link
�
�.crc_lo EQUB 0
�.crc_hi EQUB 0
�]
�
�
$
.L------------------------------------------------------------------------
8
B� �get_file_type
L
V� flags%,ptr%,temp%
`
j� String -> file type
t:ș "XOS_FSControl",31,$type_ptr% � ,,file_type%;flags%
~0� flags% � 1 file_type% = default_file_type%
�
�� File type -> string
�?ș "OS_FSControl",18,,file_type% � ,,!type_ptr%,type_ptr%!4
�type_ptr%?8 = &0D
�ptr% = type_ptr%+7
�5ȕ ?ptr%=&20 � ptr%>type_ptr%:?ptr%=&0D:ptr%-=1:�
�
�'� load_exec% file_type% = &FFFFFFFF
�
�� Read load/exec addresses
�8ș "XOS_ReadUnsigned",16,$load_ptr% � ,,temp%;flags%
�7� flags% � 1 � $load_ptr% = �~load% � load% = temp%
8ș "XOS_ReadUnsigned",16,$exec_ptr% � ,,temp%;flags%
7� flags% � 1 � $exec_ptr% = �~exec% � exec% = temp%
(�
2
<L************************************************************************
F
PMain routines
Z
dL************************************************************************
n
x� �null_putting
�
�� timeout%,flags%
�
� timeout% = � + 20*poll_time%
�
�$ș "Hourglass_On":hourglass% = �
�
��
�, ș "OS_SerialOp",3,?put_ptr% � ;flags%
�$ � (flags% � 2)=0 put_ptr% += 1
�7� (flags% � 2) � put_ptr%=put_end_ptr% � �>timeout%
�
�%ș "Hourglass_Off":hourglass% = �
(� put_ptr%=put_end_ptr% putting% = �
"� � downloading% �
,
6� � putting% �
@ downloading% = �
J# poll_mask% = poll_mask% � 1
T �menu_shade(0,"Upload",�)
^�
h
r�update_status
|
��
�
�L------------------------------------------------------------------------
�
�� �update_status
�
�8� downloading% � (was_downloading% � � uploading%) �
� was_downloading% = �
�3 � downloading% � last_download% old_time% = �
�" � old_time%<=0 old_time% = 1
�> � downloading% � last_download% = � � last_download% = �
�F ș "OS_ConvertFileSize",put_end_ptr%-file_ptr%,status_length%,12
�. $status_bytes% = �(put_ptr% - file_ptr%)
@ $status_rate% = �((put_ptr% - file_ptr%)*100 � old_time%)
$status_crc% = "0"
�
& was_downloading% = �
0 � uploading% old_time% = �
:" � old_time%<=0 old_time% = 1
D< ș "OS_ConvertFileSize",file_length%,status_length%,12
N1 $status_bytes% = �(file_ptr% - file_block%)
XC $status_rate% = �((file_ptr% - file_block%)*100 � old_time%)
b% $status_crc% = �(crc_errors%)
l�
v
�.�select_icon(status_window%,0,-uploading%)
�0�select_icon(status_window%,1,-downloading%)
�"�update_icon(status_window%,2)
�"�update_icon(status_window%,3)
�"�update_icon(status_window%,4)
�"�update_icon(status_window%,9)
�
��
�
�L------------------------------------------------------------------------
�
�� �null_getting
�
+� new_bytes%,timeout%,byte%,flags%,got%
&ș "OS_Byte",&80,&FE � ,new_bytes%
4� new_bytes%=0 � new_ptr%-file_ptr%=num_bytes% �
*
4timeout% = � + 2*poll_time%
>*� fast_load% timeout% += 98*poll_time%
H
R$ș "Hourglass_On":hourglass% = �
\
f�
p( ș "OS_SerialOp",4 � ,byte%;flags%
z6 � (flags% � 2)=0 ?new_ptr% = byte%:new_ptr% += 1
�E � new_ptr%-file_block%+10>file_block_length% � 1,"Data overrun"
�� (flags% � 2) � �>timeout%
�
�+num_bytes% = new_ptr% - file_ptr%
�/num_crc_bytes% = num_bytes% - block_length%
�
�
Ȏ � �
�< � getting_ok% � num_bytes%>0 :got% = �ok
�? � shaking% � num_bytes%>1 :got% = �shake
�E � getting_file_length% � num_bytes%>1 :got% = �file_length
�= � getting_end% � num_bytes%>0 :got% = �end
�F � getting_block_length% � num_bytes%>2 :got% = �block_length
�? � getting_block% � num_crc_bytes%>1 :got% = �block
C � getting_file_name% � num_bytes%>8 :got% = �file_name
7 :got% = 0
�
$
. � num_bytes%>got% � got%>0 �
88 � new_ptr%=file_ptr% � file_ptr%+num_bytes%-got%-1
B! ?new_ptr% = new_ptr%?got%
L �
V�
`,new_ptr% = file_ptr% + num_bytes% - got%
j
t%ș "Hourglass_Off":hourglass% = �
~
��
�
�L------------------------------------------------------------------------
�
�� �shake
�
�� i%
�
�0� ?file_ptr%<>�("S") � file_ptr%?1<>�("B") �
�7 put_ptr% = file_ptr%:put_end_ptr% = put_ptr% + 1
� ?put_ptr% = �("x")
� putting% = �
= num_bytes%
�
put_ptr% = new_ptr% - 2
(+?put_ptr% = �("s"):put_ptr%?1 = �("b")
2
<� $name_ptr%="" �
F8 � load_bget% � put_ptr%?2 = &03 � put_ptr%?2 = &0C
P! put_end_ptr% = put_ptr% + 3
Z/ shaking% = �:putting% = �
d0 getting_ok% = � :getting_file_length% = �
n�
x put_ptr%?2 = &30
�= � i%=0 � �($name_ptr%):put_ptr%?(i%+3) = name_ptr%?i%:�
�1 put_end_ptr% = put_ptr% + 4 + �($name_ptr%)
� $name_ptr% = ""
�& putting% = �:getting_ok% = �
��
�
�= 2
�
�L------------------------------------------------------------------------
�
� � �ok
�
�getting_ok% = �
� �bits(?file_ptr%)<6 �
6 �message("Protocol error - transmission failed")
, �reset_all
@ = 0
A�
J
T-� last_button%=4 � getting_file_length% �
h- �message("Press play on tape recorder")
r last_button% = 0
|�
}
�= 1
�
�L------------------------------------------------------------------------
�
�� �file_length
�
�/file_length% = ?file_ptr% + 256*file_ptr%?1
�
�getting_file_length% = �
�getting_end% = �
�
� = 0
= 2
&
0L------------------------------------------------------------------------
:
D
� �end
N
X�update_status
b
l� �bits(?file_ptr%)<6 �
v modified% = �
� getting_file_name% = �
� � do_crlf% �do_crlf
� �report_completion
��
� getting_block_length% = �
��
�
�getting_end% = �
�
�= 1
�
�L------------------------------------------------------------------------
�
� �report_completion
� report$
*.� one_shot% report$ = "Transfer completed"
4
>� crc_errors%>0 �
H' � report$<>"" report$ += " with "
R; report$ += �(crc_errors%) + " CRC errors during load"
\ one_shot% = �
f crc_errors% = 0
p�
z
�+� file_ptr%-file_block%<>file_length% �
�= � report$<>"" � report$ += "; data" � report$ += "Data"
�& report$ += " may have been lost"
� one_shot% = �
��
�
�#� report$<>"" �message(report$)
�
��
�
�L------------------------------------------------------------------------
�
�� �block_length
=block_length% = �vote(?file_ptr%,file_ptr%?1,file_ptr%?2)
+� block_length%<0 block_length% = 0:= 0
$)� block_length%=0 block_length% = 256
.
8getting_block_length% = �
Bgetting_block% = �
L
V= 3
`
jL------------------------------------------------------------------------
t
~� �vote(l1%,l2%,l3%)
�
�� l1%=l2% � l1%=l3% = l1%
�
�%� l1%=l2% crc_errors% += 1: = l1%
�%� l1%=l3% crc_errors% += 1: = l1%
�%� l2%=l3% crc_errors% += 1: = l2%
�
�7� �confirm("Serious protocol error; continue?") = 0
�
��reset_state
�
�%original_file_name$ = "<corrupt>"
= -1
L------------------------------------------------------------------------
(
2� �block
<
F� A%,B%,crc_ptr%
P
ZA% = file_ptr%
dB% = block_length%
n
� crc%
x
�(crc_ptr% = file_ptr% + block_length%
�
�.� ?crc_ptr%=?crc_hi � crc_ptr%?1=?crc_lo �
�" file_ptr% += block_length%
� put_ptr% = file_ptr%
� ?put_ptr% = 255
��
� put_ptr% = file_ptr%
� ?put_ptr% = 0
� crc_errors% += 1
��
�
�!put_end_ptr% = put_ptr% + 1
getting_block% = �
putting% = �
getting_end% = �
"
,= num_bytes%
6
@L------------------------------------------------------------------------
J
T� �file_name
^
h
� fn_ptr%
r
|fn_ptr% = file_ptr% + 7
�6� fn_ptr% += 1:� ?fn_ptr%=&0D � fn_ptr%=new_ptr%-1
�� ?fn_ptr%<>&0D = 0
�
�6load% = (!file_ptr% � &FFFF):$load_ptr% = �~load%
�6exec% = (file_ptr%!4 � &FFFF):$exec_ptr% = �~exec%
�
�� guess_type% �guess_type
�
��get_file_type
�
�(original_file_name$ = $(file_ptr%+8)
�
�,$save_ptr% = �file_valid($(file_ptr%+8))
getting_file_name% = �
&D� � one_shot% �save_file("<BBCTape$Dir>.BBCFiles."+$save_ptr%,�)
0
:� one_shot% �
D �reset_state
N�
X �start_upload(0)
b�
l
v= 0
�
�L------------------------------------------------------------------------
�
�� �guess_type
�
�
Ȏ � �
�( � load%>&C000 :$type_ptr% = "Text"
�+ � load%>&8000 :$type_ptr% = "BBC ROM"
�( � exec%>&C000 :$type_ptr% = "Data"
�) � exec%>&8000 :$type_ptr% = "BASIC"
�# $type_ptr% = "Data"
��
�
!�
!
!L------------------------------------------------------------------------
!
!*� �file_valid(name$)
!4
!>� i%=1 � �(name$)
!H2 � �bad_char(�name$,i%,1)) �name$,i%,1) = "?"
!R�
!\
!fname$ = �name$,10)
!p
!z= name$
!�
!�L------------------------------------------------------------------------
!�
!�� �bad_char(char$)
!�
!�� char$<"!" = �
!�� char$>"~" = �
!� � char$>"""" � char$<"'" = �
!�� char$="*" = �
!�� char$="." = �
!�� char$=":" = �
!�� char$="<" = �
!�� char$=">" = �
"� char$="@" = �
"� char$="^" = �
"� char$="\" = �
"$ = �
".
"8L------------------------------------------------------------------------
"B
"L� �bits(byte%)
"V
"`
� num%
"j
"tnum% = 0
"~� bit%=0 � 7
"�# � byte% � (1<<bit%) num% += 1
"��
"�
"�
= num%
"�
"�L************************************************************************
"�
"�6Routines to deal with events from the polling loop
"�
"�L************************************************************************
"�
"�� �mouse_click
#
#
� x%,y%,b%,window%,icon%
#
#Ex% = !wimp_block% :y% = wimp_block%!4:b% = wimp_block%!8
#(3window% = wimp_block%!12:icon% = wimp_block%!16
#2
#<
Ȏ � �
#FE � b%=2 :� window%=-2 y% = 96 + 44*num_menu_items%(0) + 24
#PD ș "Wimp_CreateMenu",,menu_block%(0),x%-64,y%
#Z? � window%=-2 :�update_status:�open_window(status_window%)
#d � window%=saveas%
#n Ȏ icon% �
#x@ � 0 :� b%>15 �start_drag(window%,icon%,b%):saving% = �
#�' � 2 :�save_file($save_ptr%,�)
#�1 � b%>1 ș "Wimp_CreateMenu",,-1
#� �
#��
#�
#��
#�
#�L------------------------------------------------------------------------
#�
#�(� �start_drag(window%,icon%,button%)
#�
#�
� bx%,by%
#�
$drag_button% = button%
$
$!wimp_block% = window%
$")ș "Wimp_GetWindowState",,wimp_block%
$,
$6)bx% = wimp_block%!4 - wimp_block%!20
$@)by% = wimp_block%!16 - wimp_block%!24
$Jwimp_block%!4 = icon%
$T'ș "Wimp_GetIconState",,wimp_block%
$^
$hwimp_block%!4 = 5
$rwimp_block%!8 += bx%
$|wimp_block%!12 += by%
$�wimp_block%!16 += bx%
$�wimp_block%!20 += by%
$�wimp_block%!24 = 0
$�wimp_block%!28 = 0
$�wimp_block%!32 = screen_x%
$�wimp_block%!36 = screen_y%
$�"ș "Wimp_DragBox",,wimp_block%
$�
$��
$�
$�L------------------------------------------------------------------------
$�
$�� �user_drag_box
%
%� x%,y%,window%,icon%
%
%&� � saving% �
%0
%:)ș "Wimp_GetPointerInfo",,wimp_block%
%D6x% = !wimp_block% :y% = wimp_block%!4
%N7window% = wimp_block%!12:icon% = wimp_block%!16
%X
%bsaving% = �
%ltransmit_ptr% = file_block%
%v
%��get_file_type
%�
%�!wimp_block% = 256
%�3wimp_block%!12 = 0 :wimp_block%!16 = 1
%�7wimp_block%!20 = window% :wimp_block%!24 = icon%
%�4wimp_block%!28 = x% :wimp_block%!32 = y%
%�/wimp_block%!36 = file_ptr% - file_block%
%�"wimp_block%!40 = file_type%
%�3$(wimp_block%+44) = �leaf_name($save_ptr%) + �0
%�6ș "Wimp_SendMessage",17,wimp_block%,window%,icon%
%�
%��
%�
&L------------------------------------------------------------------------
&
&� �leaf_name(path$)
&
&*� i%,char$
&4
&>i% = �(path$)
&H�
&R
i% -= 1
&\ char$ = �path$,i%,1)
&f"� char$="." � char$=":" � i%=1
&p
&z*� char$="." � char$=":" = �path$,i%+1)
&�
&�= path$
&�
&�L------------------------------------------------------------------------
&�
&�� �menu_selection
&�
&�� item%,sub_item%,button%
&�
&�>item% = !wimp_block%:sub_item% = wimp_block%!4:� item%<0 �
&�
&�)ș "Wimp_GetPointerInfo",,wimp_block%
&�button% = wimp_block%!8
'
'Ȏ menu$(item%,0) �
' � "Misc"
'$ � sub_item%>=0 �
'.! Ȏ menu$(sub_item%,1) �
'8* � "Status ..." :�update_status
'B; �open_window(status_window%)
'L0 � "9600, 8n1" :ș "OS_SerialOp",1,0
'V3 ș "OS_SerialOp",5,0
'`3 ș "OS_SerialOp",6,0
'j( � "Reset" :�reset_state
't& � "Clear" :�reset_all
'~ �
'� �
'�7 � "Save" :�get_file_type:�save_file($save_ptr%,�)
'� � "Options"
'� � sub_item%>=0 �
'�! Ȏ menu$(sub_item%,2) �
'� � "File type"
'� � load_exec% �
'� load_exec% = �
'�+ �menu_tick(2,"File type",1)
'�. �menu_tick(2,"Load address",0)
'�. �menu_tick(2,"Exec address",0)
'� �
( + � "Load address","Exec address"
(
� � load_exec% �
( load_exec% = �
(+ �menu_tick(2,"File type",0)
((. �menu_tick(2,"Load address",1)
(2. �menu_tick(2,"Exec address",1)
(< �
(F3 � "CR � LF" :do_crlf% = do_crlf% � �
(P= �menu_tick_toggle(2,"CR � LF")
(ZB � modified% � � uploading% �do_crlf
(d9 � "Guess type" :guess_type% = guess_type% � �
(n@ �menu_tick_toggle(2,"Guess type")
(x8 � guess_type% �guess_type
(�5 � "Auto load" :one_shot% = one_shot% � �
(�? �menu_tick_toggle(2,"Auto load")
(�7 � "Fast load" :fast_load% = fast_load% � �
(�? �menu_tick_toggle(2,"Fast load")
(�7 � "Use BGET" :load_bget% = load_bget% � �
(�> �menu_tick_toggle(2,"Use BGET")
(� �
(� �
(�* � "Upload" :�start_upload(button%)
(�, � "Download" :�start_download(button%)
(� � "Quit" :�exit(�)
(��
(�
)4� button%=1 ș "Wimp_CreateMenu",,menu_block%(0)
)
)�
)"
),L------------------------------------------------------------------------
)6
)@� �do_crlf
)J
)T
� ptr%
)^
)h$� ptr%=file_block% � file_ptr%-1
)r5 � ?ptr%=&0A � ?ptr%=&0D � � ?ptr%=&0D ?ptr%=&0A
)|�
)�
)�crlf_done% = crlf_done% � �
)�
)��
)�
)�L------------------------------------------------------------------------
)�
)�� �start_upload(button%)
)�
)��reset_all
)�
)�last_button% = button%
)�
*put_ptr% = file_ptr%
*?put_ptr% = �("x")
*put_end_ptr% = put_ptr% +1
*&putting% = �
*0shaking% = �
*:uploading% = �
*D)poll_mask% = poll_mask% � &FFFFFFFE
*N
*X�menu_shade(0,"Download",�)
*b�menu_shade(0,"Upload",�)
*l�update_status
*v
*��
*�
*�L------------------------------------------------------------------------
*�
*�� �start_download(button%)
*�
*�� flag%,length%,report$
*�
*�;ș "OS_File",17,"<BBCTape$Dir>.BBCLoadBT" � ,,,,length%
*�
*�L� length%>file_block_length% �message("Can't download file - no room"):�
*�
*�:� length%>file_block_length%-(file_ptr%-file_block%) �
+9 � modified% � report$ = "Unsaved d" � report$ = "D"
+3 report$ += "ata will be destroyed; continue?"
+ � � �confirm(report$) �
+ �reset_all
+*�
+4 �reset_state
+>�
+H
+R3� "Load <BBCTape$Dir>.BBCLoadBT " + �~file_ptr%
+\
+f<� button%=4 �message("Type ""*FX 2,1"" on BBC keyboard")
+p
+zput_ptr% = file_ptr%
+�%put_end_ptr% = put_ptr% + length%
+�putting% = �
+�downloading% = �
+�)poll_mask% = poll_mask% � &FFFFFFFE
+�� = 0
+�
+��menu_shade(0,"Upload",�)
+��update_status
+�
+��
+�
+�L------------------------------------------------------------------------
+�
,� �user_message
,
,Ȏ wimp_block%!16 �
,$ � 0 :�exit(�)
,. � 2 :�data_save_ack
,88 � 4 :saved_file$ = "<BBCTape$Dir>.xxxxxxxxxx"
,B � 6 :�ram_fetch
,L% � 8 :� modified% �pre_quit
,V � &400C0 :�get_file_type
,` �save_window
,j8 � wimp_block%!20=fileinfo% �file_info
,tX ș "Wimp_CreateSubMenu",,wimp_block%!20,wimp_block%!24,wimp_block%!28
,~ � &400C1 :�mode_change
,��
,�
,��
,�
,�L------------------------------------------------------------------------
,�
,�� �data_save_ack
,�
,�� ptr%,safe%
,�
,�ptr% = wimp_block% + 43
,�� ptr% += 1:� ?ptr%=0
- ?ptr% = 13
-
-/� wimp_block%!36=-1 � safe% = � � safe% = �
-
-('�save_file($(wimp_block%+44),safe%)
-2
-<#saved_file$ = $(wimp_block%+44)
-F
-P.� drag_button%>16 ș "Wimp_CreateMenu",,-1
-Z
-d"wimp_block%!12 = wimp_block%!8
-nwimp_block%!16 = 3
-x6ș "Wimp_SendMessage",18,wimp_block%,wimp_block%!4
-�
-��
-�
-�L------------------------------------------------------------------------
-�
-�� �save_file(name$,safe%)
-�
-�
� exists%
-�
-�9� file_ptr%<=file_block% �message("No file loaded"):�
-�
-�%� �name$,".")=0 � �name$,"<")=0 �
-�C �message("To save, drag the file icon to a directory viewer")
. �
.�
.
."#ș "OS_File",17,name$ � exists%
.,� exists% �
.69 � � �confirm("File "+name$+" exists; overwrite?") �
.@? � � one_shot% one_shot% = �:�menu_tick(2,"Auto load",0)
.J �
.T �
.^�
.h
.rC� "Save " + name$ + " " + �~(file_block%) + " " + �~(file_ptr%)
.|
.�� load_exec% �
.�+ ș "OS_File",1,name$,load%,exec%,,%11
.��
.�& ș "OS_File",18,name$,file_type%
.��
.�
.�-� safe% modified% = �:$save_ptr% = name$
.�
.��
.�
.�L------------------------------------------------------------------------
.�
.�� �ram_fetch
/
/?� drag_button%>16 ș "Wimp_CreateMenu",,-1:drag_button% = 0
/
/&W� wimp_block%!24>file_ptr%-transmit_ptr% wimp_block%!24 = file_ptr% - transmit_ptr%
/0
/:u� wimp_block%!24>0 ș "Wimp_TransferBlock",task_handle%,transmit_ptr%,wimp_block%!4,wimp_block%!20,wimp_block%!24
/D
/N#transmit_ptr% += wimp_block%!24
/X
/b"wimp_block%!12 = wimp_block%!8
/lwimp_block%!16 = 7
/v6ș "Wimp_SendMessage",17,wimp_block%,wimp_block%!4
/�
/��
/�
/�L------------------------------------------------------------------------
/�
/�� �pre_quit
/�
/�� quit_task%
/�
/�quit_task% = wimp_block%!4
/�
/�"wimp_block%!12 = wimp_block%!8
/�3ș "Wimp_SendMessage",19,wimp_block%,quit_task%
0
0B� � �confirm("Unsaved data: are you sure you want to Quit?") �
0
0 modified% = �
0*
04A� This is the approved method of dealing with a pre-quit, but
0>=� doesn't deal correctly with a quit from the task window
0H
0R+ș "Wimp_GetCaretPosition",,wimp_block%
0\wimp_block%!24 = &1FC
0f2ș "Wimp_SendMessage",8,wimp_block%,quit_task%
0p
0z�
0�
0�L------------------------------------------------------------------------
0�
0�� �save_window
0�
0�� flags%,type$
0�
0�� file_type%>0 �
0�< ș "XWimp_SpriteOp",40,,"file_"+�~file_type% � ;flags%
0�9 � flags% � 1 � type$ = "xxx" � type$ = �~file_type%
0��
0� type$ = "xxx"
0��
1
1wimp_block%!32 = saveas%
1*ș "Wimp_DeleteWindow",,wimp_block%+32
1$
1."$(saveas_block%+88+25) = type$
18
1B3ș "Wimp_CreateWindow",,saveas_block% � saveas%
1L
1V�
1`
1jL------------------------------------------------------------------------
1t
1~� �file_info
1�
1�� saved$,flags%,crlf$
1�
1�wimp_block%!32 = fileinfo%
1�*ș "Wimp_DeleteWindow",,wimp_block%+32
1�
1�� File type icon
1�6$(fileinfo_block%+108+6*32) = $(saveas_block%+108)
1�
1�0� modified% � saved$ = "No" � saved$ = "Yes"
1�($(fileinfo_block%+108+2*32) = saved$
1�
2 � file_type%>0 �
2
8 $type_buffer% = $type_ptr% + �9-�($type_ptr%)," ")
25 ș "OS_ConvertHex4",file_type%,type_buffer%+9,5
2 type_buffer%?9 = �("(")
2( type_buffer%?13 = �(")")
22 type_buffer%?14 = &0D
2<�
2F! $type_buffer% = "<untyped>"
2P�
2Z
2d7ș "OS_ConvertHex4",load%,fileinfo_block%+108+32,12
2n:ș "OS_ConvertHex4",exec%,fileinfo_block%+108+12*32,12
2x
2�;$(fileinfo_block%+108+10*32) = �original_file_name$,10)
2�
2�Nș "OS_ConvertFileSize",file_ptr%-file_block%,fileinfo_block%+108+14*32,12
2�
2�/� crlf_done% � crlf$ = "yes" � crlf$ = "no"
2�($(fileinfo_block%+108+15*32) = crlf$
2�
2�7ș "Wimp_CreateWindow",,fileinfo_block% � fileinfo%
2�
2��
2�
2�L------------------------------------------------------------------------
2�
3� �mode_change
3
3*!wimp_block% = 4:wimp_block%!4 = 5
3"+wimp_block%!8 = 11:wimp_block%!12 = 12
3,wimp_block%!16 = -1
367ș "OS_ReadVduVariables",wimp_block%,wimp_block%+20
3@
3J:screen_x% = (1 << wimp_block%!20)*(wimp_block%!28 + 1)
3T:screen_y% = (1 << wimp_block%!24)*(wimp_block%!32 + 1)
3^
3h�
3r
3|L************************************************************************
3�
3�Wimp Utilities
3�
3�L************************************************************************
3�
3�� �open_window(handle%)
3�
3�!wimp_block% = handle%
3�)ș "Wimp_GetWindowState",,wimp_block%
3�wimp_block%!28 = -1
3�
3�%ș "Wimp_OpenWindow",,wimp_block%
3�
4�
4
4L------------------------------------------------------------------------
4&
40� �close_window(window%)
4:
4D!wimp_block% = window%
4N&ș "Wimp_CloseWindow",,wimp_block%
4X
4b�
4l
4vL------------------------------------------------------------------------
4�
4�'� �build_menu(block%,title$,width%)
4�
4�$block% = title$
4�block%?12 = 7
4�block%?13 = 2
4�block%?14 = 7
4�block%?15 = 0
4�block%!16 = 16*width%
4�block%!20 = 44
4�block%!24 = 0
4�
4��
5
5L------------------------------------------------------------------------
5
5 *� �build_menu_items(block%,num%,nsub%)
5*
548� i%,text$,tick%,shade%,dot%,notify%,sub%,last%,ptr%
5>
5H� i%=0 � num%-1
5R, � text$,tick%,shade%,dot%,notify%,sub%
5\ menu$(i%,nsub%) = text$
5f' � i%=num%-1 last% = 1 � last% = 0
5p ptr% = block% + 28 + 24*i%
5zA �menu_item(ptr%,tick%,shade%,dot%,notify%,last%,sub%,text$)
5��
5�
5��
5�
5�L------------------------------------------------------------------------
5�
5�C� �menu_item(block%,tick%,shade%,dot%,notify%,last%,sub%,text$)
5�
5�<!block% = tick% + (dot%<<1) + (notify%<<3) + (last%<<7)
5�block%!4 = sub%
5�2block%!8 = 1 + (1<<5) + (shade%<<22) + (7<<24)
5�
5�� �(text$)<=12 �
6 $(block%+12) = text$
6�
6 � xxx% �(text$)
6$ $xxx% = text$
6.# block%!8 = block%!8 � (1<<8)
68 block%!12 = xxx%
6B block%!16 = -1
6L block%!20 = �(text$) + 1
6V�
6`
6j�
6t
6~L------------------------------------------------------------------------
6�
6�A� �writeable_menu(block%,title$,width%,cent%,buff%,len%,val%)
6�
6�$block% = title$
6�block%?12 = 7
6�block%?13 = 2
6�block%?14 = 7
6�block%?15 = 0
6�block%!16 = 16*width%
6�block%!20 = 44
6�block%!24 = 0
6�
7 ,block%!28 = (1<<2) + (cent%<<3) + (1<<7)
7
block%!32 = -1
7-block%!36 = 1 + (1<<5) + (1<<8) + (7<<24)
7block%!40 = buff%
7(block%!44 = val%
72block%!48 = len%
7<
7F�
7P
7ZL------------------------------------------------------------------------
7d
7n"� �menu_tick(menu%,name$,set%)
7x
7�� item%
7�
7�*item% = �menu_item_number(menu%,name$)
7�
7�=� item%>=0 �menu_tick_item(menu_block%(menu%),item%,set%)
7�
7��
7�
7�L------------------------------------------------------------------------
7�
7�$� �menu_tick_toggle(menu%,name$)
7�
7�� item%
8
8*item% = �menu_item_number(menu%,name$)
8
8"?� item%>=0 �menu_tick_toggle_item(menu_block%(menu%),item%)
8,
86�
8@
8JL------------------------------------------------------------------------
8T
8^#� �menu_shade(menu%,name$,set%)
8h
8r� item%
8|
8�*item% = �menu_item_number(menu%,name$)
8�
8�>� item%>=0 �menu_shade_item(menu_block%(menu%),item%,set%)
8�
8��
8�
8�L------------------------------------------------------------------------
8�
8�%� �menu_shade_toggle(menu%,name$)
8�
8�� item%
8�
8�*item% = �menu_item_number(menu%,name$)
9
9@� item%>=0 �menu_shade_toggle_item(menu_block%(menu%),item%)
9
9&�
90
9:L------------------------------------------------------------------------
9D
9N$� �menu_item_number(menu%,name$)
9X
9b� max_item%,item%
9l
9v� menu%>�(menu$(),2) = -1
9�
9�max_item% = �(menu$(),1)
9�
9�
item% = 0
9�2ȕ item%<max_item% � menu$(item%,menu%)<>name$
9� item% += 1
9��
9�
9�&� menu$(item%,menu%)=name$ = item%
9�
9�= -1
9�
9�L------------------------------------------------------------------------
:
:(� �menu_tick_item(block%,item%,set%)
:
:
� offset%
:*
:4offset% = 28 + 24*item%
:>
:H� set% �
:R1 block%?offset% = block%?offset% � %00000001
:\�
:f1 block%?offset% = block%?offset% � %11111110
:p�
:z
:��
:�
:�L------------------------------------------------------------------------
:�
:�*� �menu_tick_toggle_item(block%,item%)
:�
:�
� offset%
:�
:�offset% = 28 + 24*item%
:�
:�/block%?offset% = block%?offset% � %00000001
:�
:��
;
;L------------------------------------------------------------------------
;
;$)� �menu_shade_item(block%,item%,set%)
;.
;8
� offset%
;B
;L offset% = 28 + 24*item% + 10
;V
;`� set% �
;j1 block%?offset% = block%?offset% � %01000000
;t�
;~1 block%?offset% = block%?offset% � %10111111
;��
;�
;��
;�
;�L------------------------------------------------------------------------
;�
;�+� �menu_shade_toggle_item(block%,item%)
;�
;�
� offset%
;�
;� offset% = 28 + 24*item% + 10
;�
<