No listings or specifications were available for any of the code examples shown here, therefore they were saved from a live 512 system and disassembled. This has two implications. Firstly, they should be accurate, and secondly there is unfortunately no way to determine the precise purpose of some areas of data storage or some parts of the code in detail for all circumstances.
In the original disassembly there were short sections of code in page 6, now omitted, which were not called from any of the tube roufines here or elsewhere. Direct calls to ROM addresses within the code tend to suggest that they were incidental to tube operation. If they have any relevant function it is possible that these portions of code are used only during initial machine power-up and are subsequently overwritten. More probable however, is that they are downloaded simply because they just happen to occupy the last few bytes of that page, the bulk of which is relevant and remains.
The code shown below, which in essence and function is common to all BBC micro second processor support, consists of two parts. The first resides in page zero and is called at &16 on execution of a BRK instraction and is used to inform the co-processor of host software errors. During tube initialisation, when a hard break has been issued, if the tube is found to be active the break vector at &202 is therefore re-directed to point to &16 in zero page.
The second portion of the code is located in pages 4,5 and 6, normally reserved for the host's current language, which of course is irrelevant when running a co-processor. Page 7, normally the input strearn buffer, is used as a 256 byte data buffer for various transfers and calls. This code calls the zero page code at both location &32 and &36. In turn it is itself called by the zero page code. The entry addresses for this depend on the function called for by the co-processor. This is indicated by a single hex digit, detected within the idle loop at &36.
This is where the 6502 'waits' in the host code for co-processor dialogue when there is no current activity. The code entry points for the various function calls are located in a table of twelve addresses at &500 in both examples.
The two sections of the code are downloaded from the filing system ROM, provided that it includes support for the tube. The original DFS 0.9 did not, but all Acorn disc filing systens since DNFS 1.2, including the 1770 DFS and all versions of ADFS have, as have the alternatives from Solidisk and more recent versions from Watford Electronics. No Watford code has been checked, but like the STL version which has, it is likely to be identical byte for byte with the Acorn code, and the entry points, functions and returned values must be.
Note that the ADFS in the Master's 'Mega-ROM' is different to that in the stand-alone ADFS ROMs used by model B or B+ machines. The Master version of this code is therefore shown in the second example of the host code. The major differences are a slight 'shuffling' of the order of several of the routines and the saving of a few bytes of memory by using a 2 byte 65C02 relative branch instruction (BRA) instead of a three byte absolute JMP.
These differences are not in the interests of efficiency, as in places this technique is clearly less efficient. It is rather a by-product of the fact that Acorn's ADFS code is produced by a macro assembler rather than being hand-coded, with the result that some of the generated code is highly stylised. As the entry points in the code must remain fixed (i.e. 6502.SYS does not configure itself to suit the host type or its MOS) any bytes saved are wasted, as shown at &47h. Also, for example at &65F, there are no less than 2 relative branches followed by an absolute jump where only an absolute IMP would normally be used.
For both examples of this code shown here the functions are substantially similar, therefore to aid comparison the same labels have been used where direct equivalents of operations exist. The latest incarnation of the Master's 'Mega-ROM', released in November 1989 (since these disassemblies were produced and too late for inclusion) is largely similar to the Master version shown and 'hackers' should have little trouble in dis-assembling and understanding the new code. For all versions of the code the entry points, the functions, temporary workspace and zero page code are the same.
For a 512, regardless of host type, additional functions are required over and above those of a 6502 co-processor. rfl the case of the 512 therefore, extra code is loaded from the DOS boot disc. Initially this is transferred across the tube to the 512 from the DOS file called 6502.SYS, contained in the boot disc. Before system initialisation this file is transferred back across the tube and located at &2800, after shadow RAM has been turned off by an OSBYTE 114. The 6502.SYS code is then initialised, which results in the redirection of three more of the host's vectors. The user-vector at &200 is re-directed to &2803, the interrupt request 1 vector at &204 is redirected to &2834 and the event vector at &220 is re-directed to &2831.
6502.SYS performs many functions not provided by the standard host code. These include very fast screen updates (by direct pokes, which is why the host's shadow is not active), direct programming of the 6845 CRTC chip for the various IBM screen formats, special actions for keyboard activity scanning and reading mouse or tracker ball movement via the user-port.
6502.SYS must also perform some direct floppy disc control as CP/M formats, PC formats, as well as the 512's 800K format are not supported by ADFS, although they are by the WD1770 or 1772 if it is programmed directly. It will be found by reference to the 6502.SYS disassembly that, unlike 6502 second processors, the host code is called by the 512 via 6502.SYS only when standard MOS or ADFS filing system calls are required, though for speed 6502.SYS also issues several MOS calls directly itself. The host code is therefore of secondary irnportance to the 512, for which the majority of functions are provided by its own specialised code.
; ****************** ; 6502 TUBE-HOSTCODE ; ******************
; ******************************* ; Tube register data declarations ; *******************************
r1-stat=&FEE0 r1-data=&FEEl r2-stat=&FEE2 r2-data=&FEE3 r3-data=&FEE5 r4-stat=&FEE6 r4-data=&FEE7
; ************* ; Host OS calls ; ************* ; Filing system ; *************
osfind=&FFCE osgbpb=&FFD1 osbput=&FFD4 osbget=&FFD7 osargs=&FFDA osfile=&FFDD
; ******* ; general ; *******
osrdch=&FFE0 oswrch=&FFEE osword=&FFF1 osbyte=&FFF4 oscli=&FFF7
; ******************* ; zero Page work area ; *******************
; The first two bytes are used for indirect loading 'from' ; when relocating a language across the tube in 6502 co-processors. ; In the 512 system the first 16 bytes are used as the parameter ; block for various OSWORD or filing system operations
.romadd 00 EQUD 0000 04 EQUD 0000 08 EQUD 0000 0C EQUD 0000
10 EQUW 00
; Bytes &12 and &13 are used for the hi-lo-byte pair for ; block transfers of memory across the tube
12 EQUW 00
14 EQUB 0 ; Tube status - &8O = free / zero = busy 15 EQUB 0 ; Current owner ID - £80 = nobody
; Status bits are as follows ; Bit 0 = &O1 is the Interlock for FDC and IRQ in use ; Bit 1 = &02 is the Bad FSmap flag ; Bit 2 = &04 is the MON flaq ; Bit 3 = &05 is the *compact flag (i.e. 'Do not disturb') Not used by DOS ; Bit 4 - &10 is set during an atomic series of operations for the MFM ; Bit 5 - &20 is set it there's a Winchester controller ; Bit 6 - £40 is set when tube is in use ; Bit 7 - &80 is set if tube is present
; The following is the BRK handling code located at byte &16 in zero page.
.brk handler 016 LDA #&FF \Load A with 255 018 JSR write_R4_data \Write A to tube data register A 01B LDA r2-data \Load A from tube data register 2 01E LDA #0 \Load A with zero 020 JSR write_R2_data \Write A to tube data register 2 023 TAY \Set Y to zero 024 LDA (&FD),Y \Load A with first error byte 026 JSR write_R2_data \Write to tube data register 2 029 INY \Increment Y 02A LDA (&FD),Y \Load second and subsequent error bytes 02C JSR write_R2_data \Write to tube data register 2 02F TAX \Transfer A to X 030 BNE &29 \Was byte zero (termination)?- No repeat
.reset_stack 032 LDX &FF \Load X with 255 034 TXS \Transfer to stack pointer (reset stack) 035 CLI \Clear interrupt disable flag
; This is the tube-idle loop which keeps the 6502 amused ; when there is no current I/O activity or tube transfer ; in progress. It continually checks register 1 status ; and if nothing is required checks register 2 - until ; either requires attention this is repeated endlessly.
; Register 1 is reserved for the current output channel ; (screen, printer, RS232) hence an immediate OSWRCH is ; expected if R1 is pending - thus if an output delay is ; caused by the host or peripherals the co-pro is also ; forced to wait. It is the entry for all other activity ; therefore, even if R2 is pending. R1 is serviced first.
; The R2 entry causes an indirect jump to various code ; entry points in page 5 to give access to the required ; facilities.
.tube_idle_poll 036 BIT ri-stat \test tube register 1 status 039 flPL &41 \Not ready - try reqister 2 03B LDA ri-data \Read tube data register 1 03E Jsn anwrch \write to current output stream 041 SIT r2-stat \Test tube register 2 status 044 BPL '36 \not ready - try register 1 again 046 BIT ri-stat \Register 2 ready - recheck register 1 049 assI &33 \negimter 1 not, ready - do that first 045 rnx r2-data \Read function cods tram data register a OAE Sn' &51 ~store at j~var. modifyina it- address 050 JMP (~WnpVHX to modified address Cs500+x - dirty!)
iL-var 051 EOUE C \variable 10-byte of j~ point in page 5 052 EQUn &05 \~ixed hi-byte of iL- point (page 5
This is the 4 byte address used for language re-location across the tube
.reloc_data \used for 4 byte memory addressing. 063 FOUR 0 \LO-byte of low order of 4 byte address 054 ~ous 0 \Hi-byte of low order of 4 byte address oss tat's 0 \These bytes contain 'rrFF for the host 056 EQUE C \and &0000 upwards for the co-processor
Model BBC B+ source listing
Tube host code for model n. n+ machines using stand-alone Ants
This is the start of the code which
occupies pages 0 through 6.
Page 7 is also used as a buffer for 256 byte transfers
400 JMP &404 \Entry to copy language across tube 403 JMp &0A7 \Entry to copy ESCAPE flag across tube
This is the only entry point from 6502Sys
tube_entry \A-t29 for tube releace, 193 for claim IC' CKP iSSO \Entry for 6502sYs - Tube claim or release? 408 BCC &435 \&t's neither - must be data transfer 40A CKP faco ~Is it a tube claim? 40c ECS a428 \Yes - branch to claim_tube 40E ORA · ;&4O \no it's a release - set bit 7 on 410 CMP &15 \Are ~e the tube owner? 412 ENE &434 \If not branch return - do nothing 414 PflP \save processor status on stack 415 SE' ~set interrupt disable flag 416 LDA *5 \Lcad A with 5 416 JSR write_R4_data \write A to tube R~ 419 LDA i's \Load A with tube owner AiD asa write RI data \Write A to tube RA 420 FLP \Restore processor status from stack 421 LDA t&60 \load A with 128 423 STA &15 \store in tube owner (&15) 42S STA '14 \and in tilbe status (&14 427 RTS \Return -claim tube 428 ASt ~l4 \Shift left tube status 42A Bes $432 ~Tube wa3 tree - now it'S ours - store owner 42C ChP &15 \Tube busy. As it us in &15? 42E BEQ &4a4 \Yes it~s already ours - exit 430 CLc \clear carry - claim failed 431 RTS \Return
.store owner 432 stA &15 \store A in zero paqe byte &15 '34 nTs \Return
data transfer 435 PHP \save processor statue on stack 43' SEx \Disable Interrusts (time critical transfer) 437 STY &~S \store y (lo-address byte in '13 439 5,,' &12 \Stort X (hi-address byte in &12 433 ask write_RI_data \write A to tube data register 4 43! TAX ~and also store in 'C 43? LDY #3 \Load r for 4 byte transfer 441 tUn &15 \Load A froit zero page tube~owner 443 JSn write_~4_data \write A to tube data register A 446 WA ('12 ,Y \Load A fr~ indexed zero page address 44S Jsn write_RA_data \write byte to tube data register A 44fl flEy \Decrement count 44c BPL &446 \co~1ete? No - loop back and repeat 44E ~Y jale \Load Y 24 450 S~Y ri_stat \write to tube registeri status 453 WA ~51S.X \Load from temporary_data 45' STA ri_stat \write register 1 status 459 LS't A \Divide value by 2 Ask tSR A \and again (- Divide value by 4 45a ncc &463 \nranch if old bit 1 was C 4SD PIT r3_data \waste a bit of time? These two 460 BIT r3_data \instructinns Set p but do not affect A 463 JSR write R4 data \which is written to tube data register 4 4C6 SIT r4_Stat \Tnnt register 4 status 469 nvc &466 \Not ready - loo~ until it in 463 BeS &47A \status ears terminate Operation 46D cpx ;4 \was original A - 4 46? linE &4e2 \no - branch to return
.soft_break 471 JsR &414 \Inform co-pro of tube release 474 Js~ write_Ra_data \write A to tube data register S 477 JMP &32 \J~ to reset_stack
.terminate_operation 47A LSR A \Clear top bit 475 BCC ~462 \Branch if bottom bit was also clear 47D WY f&aa \confirm action terainated 4~T Sty ri_stat \write y to tube register 1 status 462 pIr \Rsstote processor status reg from stack 4SS KTS copy_langtiage
464 cLr \Enable interrupts
465 MOS '49$ \rf catry branch to claim tubs
467 mm &48c \rf not zero we~ve not finished branch 489 JMp &59C \J~ to termination at send_c~1etion byte 48c Lnx 40 \Load X tero 4SE WY *&FF ~Load Y 255 490 WA flFD \Load A 253 492 JSR osbyte \Read~write last break 495 TXA \Last break byte in X, transfer to A ~96 BEQ &471 \soft break - branch to soft_break 49e LDA #~rr \Load A 255 (all bits on) 49A JSR &406 \Exsc tube claim code (hard break - startup) 49D BCC &496 \If not successful repeat until it is 49F JSR ~4D~ \check current ~on, set up reloc.rt lan4"age 432 LDA *7 \Load A with 7 for call to tube_entry 4A4 JSR &4C3 \Jup to tube entry (with return) 437 LDY *0 \set Y counter to zero 4A9 STY 0 \Store in romadd (10-byte of transfer addr 4An LDA (O~,Y \toad byte to be transferred 4AD STA r3_data \write A to tube data register 3 4B0 NOP \These Mops are included s~ly to cause a AB1 NOP \de1a~, as the as transfet is 'slow 4B2 NOP \cThia extra NO? needed for 6502 and ZOO) 4Ba INY \rncrwnent Y - Finished current page? 4BA BNE &4AD \No repeat until 256 bytes tranaterred 4B~ INC 654 \Increment hi-byte, lot, order of co-~ro addr 439 ENS &4C0 \64K transferred? No-branch update-host-page 4SA INC &55 \Next 64K in co-pro. Inc. 10-byte high order 4fle stat &4c0 \16Mb co~1ete? no.branch npdate-host-~age 4BE INC &56 \:nc co-pro hi-byte hiah ordercnext 1~nb! update_hostjage 'Co INC 1 \Incr-ent RON address hi-byte ~C2 BIT 1 \Teat > ~ bit. In 'Ci (2~14 - "'C eadresaed) .C. BVc ~4~ \rt tEK co-let. branch for tub, data xfer 4C~ asa &4D2 \Check current no" and set up reloc.!! lsng Ac' WA #4 \Load A .ith 4 for tube transfer type 403 WY \Load Y (la-byte for tube data transfer 4cn rnx ~&53 \Load X (hi-byte rot tube data transfer 4cr JXP ~4O6 \J~ to tube_entry check_roTa_type 4D2 LDA ~&SO \ncad A 120 404 STA &54 \set co-pro relocation addre5s to &0000e000 'De STA 1 \And set hosttXfer ircit' address to 'SOOC ADS IDA t&20 \set bit ~ Ott all othnr5 off ADA AND &SOO' \Aflt current RON tyna byte - is it a lang cnn TA? \Put result in Y in case At's not INTh s~Y &s3 \put result in 'sa in case it~s not AED BEQ &4Th \means RON in NOT lang - branch no_reloc 4:2 lAX 58007 \Load X with ~I copyright pointer offset read C 4E5 Iba \Inc X to point to firat C of (C string 4s6 WA &8000.x \Load A with copyright bytes until byte - 0 4E9 BNs~&4E5 \Until 0 it~s the c'right notice AEn LDA &6001,X \Load 1st byte of ca-flrocessot reloc address 4EE STA &53 \Store in zero page byte &5a 470 WA ~SOO2.x \boad 2nd byte of relocation address 4r3 STA &54 \Stote in zero page byte &S4 4r5 'fly &6003,X \Load Y with 3rd byte of relocation address ~rs LDA aa004,x \Load A with 4th byte of relocation address reloc 4FB STA &5e \store accumlator in zero page byte 6~6 4FD STY &55 \store Y in zero page byte &55 4FF k~S \Return
; These are indirect jumps taken from the tube idle loop ; cede at &036 to &050 The a~ras5 In &O51 Is pnknd to ; index one of the following indirect jump addresses.
500 EOUW &3705 \was 0 - jump osrdch_call 502 sOUW &9605 \ was 2 - ju'np oncli_call 504 ECUW ar205 \ ~n2 was 4 - 5u~ shor~ _nabyte soe EQUW &0706 \n2 was 6 - j~ long-osbyte 508 ~auw &2706 \n2 was S - jump OSWORD_call 50A EQUW &6806 \R2 was A jump cawordo-call SOC EQUW &5305 \ ~a3 C - ju~ osarga_call SOE EQUW &2n05 \ft2 was E - ~ o,bget_call 510 sOUW &2005 \ was 10 - zump osbput_call 512 KOOW &4205 \ ~n2 was 12 - itimp osfind_call 1 514 EQuw &A~O5 \ was 14 - ju~ osfilo call 516 tom' ~DlO5 \ was 16 - j~ osgbpb_call .te~rary-data 518 SOUw 00 51k RQWI OO 510 EQuw OG 51E RQUS OO .onbput_call 520 JSn rend_'12 data \Load A with fil. handle from register 2 523 TAY \File handle must be in Y 524 Jsn read_fl_data \Load A with tube data register 2 527 Jsn asbpnt \Put a single byte to file 52A JMP \Jmp to send completion byte
.osbget_call 520 JSR read_~_data \Load A with file handle from r~i5ter 2 $30 TAY \rile handle mu5t be in V 531 JSa osbget \c;et one byte from file 5a4 SM? asak \aun~ to transfer_one_byte
.osrdch call 53~ JSR
.transfer_one_byte SSA flea A \shift tight one bit San JsR write ~ data \write A to tube data reginter 2 sat 'tot a \Shift left one bit 3)4? &5~t \J-p to send unshifted byte
.osfind_call_1 542 Jsn read_RZ_data \Load A with tube data re~ister 2 545 BEQ osfind_call_2 \zero byte means close a file SA' PRA ~stnre A on ntack temporarily 541 JSa block transfer \Transfer file-naras from co~ro 54fl Pu \nestore A (Contents - access mode) sac jsn osfind \open the named file 54F JXP &s9E \Jmp to return file handle
.osfind_call_2 55~ JSR read_fl_data \toad A with tube data register 2 555 TAY \File handle must be in Y 556 LDA *0 \Lcad A with zero 5se Jsn ostind \Clone file SSn OMP &59c \Jnrnp to send conpietion byte
.osarga_call 55E Osri read_R2_data ~Load A tram tube data register 2 sel TAY \put file handle in Y 562 LDx ~4 \Set up loop count 564 3sn read_fl_data \LOad A fro~ tube data register 2 567 S~A &r~,x \store at bottom of zero page 569 flEX \Decremnt count SeA ENS &564 \coa~1ete? No - loop back and re~at 56c Jsa read_RI data \Load A with osarg~ call type SEF JsR onarga \nead(write tile attrihutea 572 3srt write_R2_data \write A to tube data register 2 575 rnx *3 \Set up loop count for 4 bytes 577 WA O,X \Load A with returned attributes 579 Jsn write_'2_data \write a to tube data re4ister 2 57C DEX ~D.crmnnt count 57fl BPL 6577 \c~1et,? No - loop back and repeat $77 JwP '36 \Jnnp to tube idle polling loop
-block transfer 582 tux to ~2oro sac INY IC \and Ses JSR read_fl_data \Load A from tube data register 2 509 STA data,Y \store in 256 byte buffer at &700 Sec '~ \Incr~nt Y SaD BEQ end_block \Finished 2S~ bytes? - Yes 5SF am ~Nn \ wa3 byte CR (end of transfer 5~1 SNE isee \NO - Loop back for next byte
end-block $93 ~Y ~? \Finisbed! - Load Y with 7 595 't~s \Rsturn
-ouch call 5~c Jsa block_ttansfer \Get cli string S9~ JSR ascii \Call "0S co-and line interpreter
send_copletion_byte 5~C ~A *'7r \Load A with 127 (co~1etion byte) SSE flI' r2_stat \Test tube register 2 status Sal Evo ~59E \not ready - repeat 5A3 STA rZ_data \write A to tube data register 2 5A6 JNp '35 \3~ to tube idle polling loop
osfile call 5A9 IDX talc \Set up for is byte transfer in x SAn asa read_fl_data \toad A frOm tube data register 2 SAL STA &i,x \5tore at romadd+1,x sao flEx \Decreraent count 531 SNE &SAB \1eto7 - Na loop back and repeat 5B3 JSR block_transfer ~transfer bytes Sne STX 0 \Raset filename hi-byte to zero SBR STY 1 \Set filena~ pointer la-byte to Y SnA rnY *0 \set x-Y to point to 16 byte parameter block 5Bc SSR read_R2_data \Lcad A trOta tube data register 2 SEF JSR osfile \Ca1Y osfile - A defines required action 5c2 JSR write_RZ_data \write result code to tube data register 2 5C5 LDX #610 \set up for 16 byte transfer out 5C7 Ink 1,X \Load from romadd+1.x 509 JSR write_R2_data \write A to tube data register 2 SOC DEX \Decro~nt count 5cn slit 'Sd \c~lete? - '10 loop bac~ and repeat SCF BEQ &SAE \2 stage j~ back to tub._idle_loop
.osqb~_call sni inx ~&n \toad X counter with length of param- block 5n3 JSR read_fl_data \Load A from tubs data register a 506 S~A &rr,x \store at bottom of Page zero (1 to aD) SflS DEX \necremant count Sflg BIlE &5D3 \cc~let.~ - No loon back and repeat 5DB JSK read_RI_data \Load A frog~ tube data tegistet 2 SDE WY 40 ~sot Y to la-byte of parems 5t0 Jsn osgbpb \call osgetbytelputbyte 5E3 PRA \preserw A on stack 5E4 W~ \set loop count 5~6 ~A O,X \boad returned file info~tion SEa Jsa write_fl_data \write A to tube data register 2 5ES flEx \Decrereflt count 5EC flPt &5E6 \Complctc? No - Loop back and re~at SEE PLA \flestore A from stack 5SF JMP $53A \Ju=p to transfer_one_byte
.short_osbyte 5F2 JSR read_n2_data \Load A tram tube data re~ister 2 SF5 TAX \set X paramter SF6 Jan read FIS data \Load cabyte n~ber from tabe data reg SIrS JSR osbyte \Call osbyte
SF0 BIT r2_stat \'remt register 2 status srr nvc aSFO \Not ready - loop back until it is 601 STX rZ_data \write returned X value to tube data reg 2 604 JKp &36 \3wnp to tube idle polling 100p
.long_osbyte 607 JSR read RI data \Load A frog~ tube data register 2 EGA TA)[ \set osbyte 'C paramtar Con Jsn read_R2_data \Load A from tube data register 2 COE TAY \set osbyte Y parameter SOF Jsn read_R2_data \load A from tube data register 2 612 JSR osbyte \call osbyte 615 EoR *&9D \was it osbyte 157 (fast tube flPUT~? 617 BEG &604 \Yea - Branch to idle poll j~ 619 KOR A \Not 157 - shift right one bit GiA JSft write_R2_data \writo A to tube data register 2 Gin BIT r2 stat \Test tube register 2 status 620 ave &61n \NOt ready - loop back until it is 622 STY rZ_data \write Y to tube data register 2 625 nvs aSFC ~nranch to write X value to register 2
.osword call 627 Jsn read R2_data \Load A from tube data register 2 62A TAY \Save read/write action in Y enn nIT r2 _stat \Test tube register 2 s~atus 62E BPL &S2a \Not ready - 1cc~ until it is 630 rnx r2_data \Load X with param. block offset 633 DEX \Decrement X - If it~s zero no parameter. 634 ml' &645 \ now ~t?? - Yes branch to csword_setup 636 BIT r2_stat \lest tube register 2 status 639 nPL &~~6 \not ready - loop back until it is 63B Kak r2_data \ ~flead tube data register 2 63E STA &126,x \Store in paramter block at offset 641 DEX \necrement count 642 flPL &636 \c~lete? no - loop back and repeat 644 TYA \nsstore read/write action from
.osword_setup 645 ~X ~&28 \Load X with patam. block address lot, byte 647 Wy ~1 \toad Y with param. block address high byte 644 asa onword \Ezecute osgord using parm. block at &126 64c nIT z2_stat \Test tube register 2 status 64r BPL &64c \not ready - loop back until it is 551 LOx r2_data \Load A from tube data register 2 65~ flEx \Decrement x 655 SM' &6e5 \cor~lete? Yea - 657 In? &12s,x \Else read paranstet into ~SA nIT r2_stat \.!est tube re~ister 2 statun 650 avc SeSA \not ready - loo~ back until it is 65r STY r2 data \write y to tube data register 2 '62 flEx \DecremeQt count 663 BPL &657 \con~lete? no - loop back and tepeat s'5 S"? &36 \Jtimp to tube idle polling loop
.oswordo_call 6's Lox #4 \set loon count to 4 in x SCA Jsn read_;12_data \Load A fro~ tube data register fl 6~fl STA O,X \store at rmadd+x 66? flEx \necrement count until 'C - 'Fr 670 apt SGGA \5 bytes Xferred? - No loop back and repeat 6~2 "ix \Incr~nt X (back to zero) 673 WY *0 \Set Y to zero 675 TXA \Set A to zero 676 JSR ozwcrd \oet characters fro~ current in~ut stream 679 BCC a6eo \RSturfl preaned? - Yes - branch to wtite G79 WA ~&FF \Escape pressed! - load A with 255 and 67D JMp &59E \J~ to write tegister 2
.read_string ~ao wx ~o \zeto loop counter 6S2 LOX *&7F \Load A with start string byte 6S4 Jsn write_&12_data \write A to tnbe data registar 2 6S7 WA data.x \toad from 256 byte block at &700 ERA asri write_R2_data \write A to tube data register 2 Sen "ix \Incr~nt count 'SE OMP l&D \End of in~ut warked by cMa$13? 6~O fiNE ~6S7 \No - loop back for next byte 692 aMP &36 \rndirect it- to tube idle flolling loop
.write fl data 695 BIT r2_stat \Test RZ status 696 BVc write_~_data \wot ready - loop until it is 69A STA r2_data \write A to tube data register 2 'SD RTS \RSturfl
write R4 data 6~E nIT r4_5tat \Temt n4 status Gal BYC write_R4_data \Not ready - loop until it is 'A3 STA r4_data \Write A to tube data register 4 6A6 RTS \Keturn
6A7 WA &rr \Laad Accunnjlatcr with 255 6A9 SEC \Set earrr flag 6AA "Ca A \notate right Accnmnlator bits EAB ml! write_Ri_data \Branch on -ve flag (bit 7. prev carry SAD PHA \?teserve A on stack SAE InA 40 \toad A with zero 630 Jsn write_RI_data \write A to tube data register 1 6B3 7YA \transfer content3 of Y to A SEA JSn write_RA_data \nrite A to tube data register 1 Sn7 Tm \Transfer content5 of X to A GnS asa write_Ri_data \write A to tube data register 1 EBB PIA \Restore A ftoa stack
-write Ri data 6nc BIT ri_5tat \rest al status ear nvc write_RY_data \ae~at - Ri not ready (bit 6 clear) Gd STA ri_data \write Ri data from A 'CC ~fS ~Return
-read R2 data 5c5 BIT r2_stat \Test Ttfl status 'CS B~t read_'t2_data \Repeat - ~ not ready (bit 7 clear ECA WA r2_data ~nsad regiater 2 data into A 600 aTS \neturn
700 .dat. \flata buffer far (up to) 256 bytes
; Master 128 source listing
; Tube host code for Master 128 machine, using Mega-ROM ADFS ; This is the start of the code which occupies pages 4 through ~ ; Page 7 is also used. as a butter for 256 byte transfers.
400 JMP &4C2 \Entry to cony language across tube 403 JIw ~675 \Entry to copy ESCAPZ flag across tube
.tube_entry \On entry A~129 for tube rel, 193 for claim 406 cXP ~aeo \Entry for 6502sYs-Is it tube claim or tel? 409 Thea ~433 \rt's neither - rust be data transfer 40A CMp ~&co \!3 it a tub, claim? 40c ncs ~426 \Yes - branch to c1a~_tube lot OAR ~s40 \NO it~s a release - set bit 7 on '10 CKp als \Are we the tub, owner? ~12 ENE ~4~2 \If not branch return - do nothin0 414 eMP \save processor statun on atack 415 SEI \set interrupt disable flag 416 ~A $5 \boad A with 5 41S JsR write_RA_data \write A to tube a' 41n Jsa write n4_tube_owner \Load A with tube otmer and writ. to Re 41K pLp ~Reator. \rooessot status tram stack 417 IflA ,&E0 ~load A with 128 421 STA &15 \Store An t~ owner (&15 423 STA &14 \and in tube stattis (&14 ~25 Ft's \'etnrn
.claim_tube 426 ASL &14 \shift left tube status 428 Ecs &430 \ uaa free - now it'a ours - store own~r 42A CPe '15 \Tube bnsy, is it us in &15? 42e etc &432 \yes it~s alreadr ours - exit 42& crc \Clear carry - claim failed 42r R7S \Return
.store owner 430 STA &15 \store A An z~ro page byte ~15 4~2 RTS \Rsturn
.data_transfer Ass pnp \save processor statue on stack 434 SEI \Disable interrupt , (tine critical transfer) 4~5 STY '13 \store Y (10-address byte in &lj 41~ STX &12 \starn X (hi-address byte) in &12 439 JSR write_R4_data \write A to tube data register 4 43c TAX \and also store in x 43D LDY .3 \Load Y for A byte transf.r 4SF Jsn write_R4_tube_ovaer \Load tube owner and write to Ra 442 InA c&12}.y \Load A frm indexed zero page address 444 Jsn writ._rt4_data \write byte to tube data register A 447 flEX \Decreent 448 aph ~4~2 \comp1~t,? No - loop bacir and repeat 44A WY isle \Load Y 2~ 440 STY ri_stat \wtite to tube tegisteri status ''F WA '5i6,X \Load frort te-rary_data 45~ STA ri_stat ~write regist,r 1 status 455 LSR A \Divide value by 2 456 LSR A \and again C- Divide value by 4) 457 ncc aAsr \ntanch if old bit 1 Was 0 ASS BIT r3_data \waste a bit of tint? These two 45C sI'r ra_data \insttuctions set F but do not attect A 4Sr JSR write_R4_data \Wh*ch in written to tube data register 4 462 srT r4 stat \¶est regi5ter 4 statun 465 Bvc ~4~2 \Not ready - loop until it is 467 acs &476 \statn5 says terminat, op.ration 469 cpx #4 \wa5 original A - I 'GB BRE a47E - branch to return 160 Jsn '414 \Inform co~ro of tube release 470 JSn '561 \wrAt. A to tube data register 2 473 JMp ~32 \J~ to reset_stack
.terminate_operation 47' 1&rt A \Clear top bit 4~7 scc &47E \Branch if bottom btt was also clear 47~ tar ~'ae \confirm action terminated '75 sTY ri_stat \write Y to tub, rgi,t.r 1 status 47t Pt, \Rostore processor Status reg fr~ stack 47F RTS \Returfl 460 Wx &29n - \s copy of last BREAK type byte 4e3 BEQ &46D \O-soft - branch inform 512, reset stack 4S5 ~A ~&FF \Load A 255 (all bits on) 4$, Jsn &406 \Ex tube claim code (hard break - startup) 48A floe &4e5 \If not successful repeat until it is 4Sc JSR &4C9 \Ch.ck current RON, set u~ reloc.if lang 4er pHp \Save processor status 490 S~X \Disab1e interrusts 491 IrA ~7 \~ad A with 1 for call to tube_entry 4,3 JSR SAaB \J~ to tube entry (with return) 496 tnT 40 \Store in rgmadd (la-byte of xfer address) 49$ STZ a \store in romadd (10-byte of kfer address) 49A rflA (O),Y \Load byte to be transferred 49c STA r3_data \wtite A to tube data register 3 49r flop \These flOps are included sin~ply to eanse a 4A0 NOP \delay. as the Ra transfer is slow' 4Al NOP \(Extra NO? needed for the 6502 and zec) 4A2 INY \Increment y - Finished current page? 4As BNE ~49A \No - repeat until 256 bytes transferred 4A5 PLY \aestore processor flags 4A6 Inc &s4 \~nc hi-byte. low order of co-pro address AAS ENE &4B0 \64~ xferred? Nn - branch update-host-page 4AA INC ass \Next 64K in co-pro- Inc- ic-byte high order 4AC BNs SABO \1&Wb c~lete? No-br. update-host-page \increment fiflM address hi-byte 4AE INC &5E \Inc co-pro hi-byte high ordcr(next 16Mb-)
4n0 INC ~l \:ncre~nt ROM address hi-byte 4n2 BIT al \test > 6 bits in &O1 C2~14 - 16K adnressed 454 Bvc '4sf \If 16K c~1ete branch for tube data xter dnA 3sn &4C9 \check cnrrent RON and set up reloc-if lang 4S9 LDA ~4 \Load A with 4 for tube transfer type 49S ~Y *0 ~Lcad Y (10-byte) for tube data transfer 4nn rnx ~&53 \Load X (hi-byte) for tube data transter 43? OMP &4C6 \Jti'ap to tube_entry
copy_language 4c2 CLI \Enable interrupts 4c3 ncs a4as \If carry branch to claim tube 4c5 flNr &480 \If not zero we've not finished - branch AC? BRA &52A \a tc termination at send_completion_byte
.check_ram_type (Cs tAX saso \Load A ~2B 4CR STA &54 \set co~pro relocation address to &0000s000 4Cn STA I \And net host ~Xter frOTh address to ICF ILA ~a20 \sat bit 6 on, all others off 4n1 AND &BOOC \Abtj cnrrent ROM type byte - is it a lang? 4D4 TAY ' \Pnt result in y in casa it's not Ans STY &53 \put result in &53 in case it's not 4D7 BEQ &4t2 - RON is NOT a language - branch no_reloc 4D9 LDx &e007 \Load X with $tO~ copyright flointer offaet
read C Cflc INX \Inc X to first of '(C), atring 4DD LDA &a000,x \Load A with copyright bytes until byte - 0 4s0 nnr &4nc \untii it1s the Cc notice - branch read_C 4E2 LDA &E00!,x \Lnad 1st byte of co-pro reloc address 4E5 STA &53 \store in zero page byte &5~ 4E7 LDA ~8OO2,x \Load 2nd byte of relocation address 4EA SIA &54 \store in zero page byte &54 4EC LDY &8003.x \LOad Y with 3rd byte of relocation address 4EF LDA &E004,x \Load A with 4th byto of relocation address no reloc
4F2 STA &56 \store accuinulator Yn zero page byte &56 4r4 STY &55 \Store Y in zero flage byte &55 4F6 RTS \Return 4F7 \These addresses are undefined- They are \unused because the code was re-written AFA \for the master so as to use less 'reraory. 4F0 \but the addresses at &500 cannot be moved ArE \therefote these bytes are redundant.
These are indirect j~s taken from the ttte idle loop code at £036 to &0S0- The address in '051 is poked to index' one of the following indirect jump addresses.
500 EQUW &3505 \n2 was a - i~ osrdch_call 502 EOns &6605 was 2 - ii- ouch call 504 FOUW sokos wan 4 - it- short_osbyte SOS EQUW &EBOS \R2 was 6 - j~ lon~-osbyts 508 EQUw ~O7O6 was S - it- OSWORD_call 50A ECUW &3606 was A - j~ OSWORDO-call
50C EQUW &5905 was C - ii- osarga_call
SOE EOtM &2005 was S - j~ osbget_call
510 EQUW &2005 was 10 - ii- csbput_call
512 EQWI &3r05 was 12 - jur~ osfind_call_1
514 EQUW &8205 was 14 - jump osfile_call
5h EQUW &9A05 was 16 - jump osgbpb_call
.t~otary_data SIB EQLM OO 51A EQUW OO Sic tQWI OO SlE EQUW 00
.osbpnt_call 520 JSR read_n_data \toad A with file handle tram rnginter 2 $23 TAY \File handle ~ust be in r 524 asa read ~ data \Load A with tube data tegister 2 527 asa osbput \pnt a single byte to file 52A flRA aSSE \Branch to send completion byte
.osbget_call 52c JSR read_~_data \Load A with file handle from register 2 52F TAY \rile handle mnst be in Y 530 JSa os~et \Get one byte tram file 533 BRA &538 \atanch to transfer_one_byte
.osrdch call 535 JSR osr&h
.tranafar_one_byte 53B ROR A \shift riQht one bit 539 JSa &661 \write A to tube data register 2 53C ROL A \shift left one bit 53n BRA &590 \Branch to send unshifted byte
.osfind_call_1 5SF JsR read_~_data \Load A with tube data register 2 542 nEC &54~ \zero byte means close a file 544 P'h \store A on stack te~orari1y 545 JSR block transfer \transfer file-name from co-pro 546 pLA \Reatora A (Contents - access made 549 JaR csfind \open the named tile 54C BRA &590 \nranch to return tile handle ostind call_2 54E JSfl read_RZ_data \Load A with tube data register 2 551 TAY \rile handAc must be in Y 552 tak \Load A with zero 554 JSR onfind \Clnse file 55, flRA '56& \Jump to send con~1etion byte
.osargs_call 55* asa read_~_data \Load A fror tube data register 2 55C TAX \put file handie in Y 55n ~x .4 \set up loon count 55r Jsn reftasarams \Read parameters into zero page 562 JSR osargs \Rsad~write file attributes 565 asa write ~_data \write returned A value to data register 2 sea 'nx .3 \Set up loon cOunt fat 4 bytes SEA boA O,X \Load A with returned attributes Sec asa write_fl_data \write A to tube data register 2 5SF flEx \Dectenent count 570 Ept &56A \co~1ete? No - loop back and repeat 572 BRA &59e \Indirect branch to tube idle polling loop
.block transfer 574 wx 40 \zeto x 57~ WY *0 \and Y 57$ JsR read_fl_data \Load A from tube data register 2 57B S~A data,Y \Store in 256 byte buffer at &700 57E 'NY \rncrement Y S7F nEO end_block \Fininhad 256 bytes? - Yes 501 cMp ~&D \No - was byte CR (end at transfer 593 EnE &57a \no - Loop back for next byte
end block 5SS ~Y ~7 \rinished! - Load Y with 7 5S7 RTS \flrturn
oseli call sea asa block_transfer \Get cli stting San 3sn ascii \Call "Os car-and line intarpreter
send_cc~letion_byte SeE InA ~&7F \Load A with 127 (co~1etIon byte) 5~O BIT r2 stat \Test tube register 2 status 593 Bvc ~59O \Not ready - repeat 595 STA ri_data \writs A to tnt,. data regimt.r 2 596 WtA LSES \Indirect branch to tube idle polling lo~ -osg~b_call S9A WIC ~sn \Load X counter with length of param- block 59c as,' read~ramn \Raad zero ~age ~aram trO# tube register 2 Sgr w~ 40 \set y to la-byte at parama SAl JSK os~pb \call osg,tbyte~putbyt. 5A4 PHIL \Pr.serv. A on stack 5A5 Lox IaC \set loop count SA7 LnA O,X \Load returned tile information 5A9 JS't write_RQ_data \write A tn tube data register 2 SAC flEx \Decrement count SAD Ert s5A7 \conp1ete? No Loop hack and repeat SAF PTA \nestore A tr~ stack 5B0 BRA &53e \etanch to transfer_one_byte
onfile_call 5B2 Lnx ,&1o \set up for 16 byte transfer in 5n4 Jsn read_~_data \Load A from tube data register 2 5S7 S~A 1,X \Store at romadd+1,X 5B~ fltx \flecrement count SNz t5n4 \co~lete? - No loo~ back and repeat SEC JSa block_transfer \transfet bytes 5Br STX 0 \Raset tijename hi-byte to zero Sal STY 1 \Set tiYename pointer b-byte to Y sca 'fly ~o \set x-Y to point to 16 byte parameter block 505 JSn read_pt2_data \Lcad A tror tube data register 2 505 aSa osfile \Call ostile - A defines re~uired action ScB Jsa write_RZ_data \Nrite result code to tube data register 2 5CR Ifix '&10 \Set u~ for 16 byte transfer ont Sno KnA 1,X \Load tram rmadd+1,X 5n2 JSR write_~_data \write A to tube data register 2 5D5 DEX \flecremCnt count 5D6 SNE s500 \cc~lete? - No loop back and repeat 5DB BRA &5E8 \2 stage in- back to tube_idle_loop
short_osbyte SDA Jsn read_x_and_A \Read X an~ A params for short osbyte 5DD JSR osbyte \ca11 osbyte 5~O nIT r2_stat \Teat register 2 status SES nvc &SEO \not ready - lccp back until it is SES STX r2_data \write teturned X value to tube data reg 2 5E8 JKp 636 to tube idle pol1in~ loop
long-osbyte 5E3 JSR read_x_and A \ncad X and A params for osbyte 5EE TAY \~ove A parameter to Y SEF JsR read_R2_data \Load A from tube data register ~ SF2 JSR osbyte \call osbyte 5F5 Eon *&9D \was it osbyte 157 (fast tube flPUT}? 5F7 BEQ 'SEa \yes - Sranch to idle poll j~ 579 ROR A \Not 157 shift right one bit STA asa write_fl_data \write A to tube data register 2 Sm BIT rZ_3tat \Test tube re4ister 2 status 600 EVa SSFD \Not ready - 100P back until it is 602 STY r2_data \write y to tube data re~ister 2 '05 Sak &5E0 \Branch to write X value to regAster 2 .OSWORD call ~C7 asa read_%2_data \Load A from tube data register 2 60A Thy \save read~write action in Y 603 JSR read_x_n_data \~ad X from tube data register 2 ~OE SM! \61A now &FF? - Yes branch to OSWORD_setup 610 JSR read_n_data \Rsad patanrbera from tube data register 2 613 SZA ~l2S,X \stnre in paranter block at offset x '16 DEX \necrersent connt 617 SPL &610 \c~lete? no - loop back and re~at 619 TYA \aestore read/write action from y
.onward_setup 61A LDX ~$28 \toad 'C with patam. block address low byte 610 KnY 41 \r'oad Y with param- block address high byte EYE JSR osijord \SXecut, O5WO~ using param block at &12e 621 asa read_x_R2_data \Read X from tube data register 2 624 3"' &5Ee \coapl,te? Yea 626 WY &129,x \E1S. read parameter into Y 62g SIT t2_stat \Teat tubs registet 2 status 62c Bvc &62~ \Not ready - 1oo~ back until it is ~2E sty rQ_data \writ. Y to tubs data register 2 631 flEx \D~erement count 632 EPt ~62~ \co~1ete~ No - loop back and tepeat 634 BRA asEe \rndirect branch ~o tube idle polling loop
.cswordO-call 636 ~X \Set loop count to ~ in 'C GSa JSR read_R2_data \Load A tram tube data register 2 E3B sta o,x \Store at rcu-dd+X 63n Dtx \Decremsnt count until X - 'Fr 63t S?t &630 \5 bytes xterred? - No loop back and repeat 640 Ibix \rncrtment X (hack to zero 641 Tm ~set A to zero ~42 TAY \Set Y to zero 643 Jsn caword 'Get character. frorn current Snout stream 646 scc &GAD \Return pressed? - Yen - branch to write 64S LDA i&FF \Escape pressed - load A with 255 and 64A JMP &590 \J~ to write register 2
.read_string SAC Inx *0 \zero loop counter 64F InA 4&7t \Load A with stact string byte &51 3SR write_n_data \write A to tube data register 2 654 WA data.x \Load from 256 byte block at 6700 657 JaR write ~ data \write A to tube data register 2 'SA INX \Incre=flt count CM? ~&fl \tnd of input tarked by CHR$13? CSD ENE &654 \No - loop back for next byte 6SF BRA &634 \Indirect iL- to tube idle polling loop
.write_R2_data 661 BIT r2-stat \test ~ statns GSA Eva write_R2_data \Nat ready loop until it is 665 STA r2_data \write A to tube data register 2 669 RTS \Return
.write R4 tube owner 6~A Ink &15 \Load current tube owner
write nA data Sec BIT r4_stat \Te.t Re status Ser nvc write_RA_data \Not ready - loop until it is 671 STA rC_data \write A to tube data regAster C 674 RTS \Retnrn
.copy_escape_flag 675 LDA #FF \load Accumulator with 255 677 SCF \set carry flag 676 ROR A \Rotate right Acurulator bAts 679 BA write_Ri_data \Braneh on negative flag (bit 7. prev carry) 67B PHA \preserve A on stack 670 LDA #0 \load A with zero 67E JSR write_Ri_data \write A to tube data regist,r 1 601 TYA \transfer contents ot Y to A 602 JsR write_Ri_data \write A to tube data regist.r 1 685 TKA \Trannter contenta of K to A 6as JSR writ._Ri_data \write a to tube data register 1 604 PLA \Ra5tcre A from stack
.write Ri data 65A arT ri_stat \Test Ri status 65D nvc write_Ri_data \n~ps.t - Ri not ready (bit ~ clear) 65F STA ri data \Write Ri data frm A 662 RTS \Return
.read~atams 693 asa read_32_data \load A irm tube data register 2 6SE STA &FT,x \store at bottom of zero page 6~8 flEx \necrermant count 699 ENE rcad~rninn \c~lete? no - loo~ bac~ and tepeat 69B SKA read_fl_data \Branch read Accumulator from ~
read X and A 69D Jsn read_fl_data \Read data register 2 into A and transfer 6A0 TAX \the value to x, then ta~1 througb to..
.read_R1_data SAl SIT rQ_stat \Test ~ status 6A4 flPt read_~_data \Repeat - n not ready (bit 7 clear EAE Efla r~_data \Read register 2 data Into A EAS RTS \neturn
.read_R2_data EAA SIT r2_stat \Test R2 status EAD EPL read_x_w_data \Repeat - ~ not ready bit 7 clear) EAr U)Z r2_data \Read register 2 data into X 6n2 DEX \Decrenent the value 'Ba RTS \Return
700 data \Data buffer for up to 256 bytes