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 ;� <