> IDE/s  IDE interface at &FC40-4F : (= 01-May-2004 v0.10 JGH: Initial version based on RAMCard 2* 24-May-2004 v0.11 JGH: Reading works <: F : : P: Z Workspace contents: d ws+&000 - RAMCard b0-b7 n ws+&001 - RAMCard b0-b7 x ws+&002 - RAMCard b0-b7  ws+&003 -> intercepted  ws+&004 - RAMCard size 2 ws+&008 - RAMCard memory address/file buffer ws+&00C - RAMCard pathname - ws+&010 - File PTR, byte 0 holds flags: 7 b0=buffer read, b1=buffer needs writing  ! ws+&020 - IDE device 0 size 7 ws+&024 - IDE device 0 memory address/file buffer % ws+&028 - IDE device 0 pathname ws+&02C - IDE device 0 PTR  ! ws+&030 - IDE device 1 size 7 ws+&034 - IDE device 1 memory address/file buffer % ws+&038 - IDE device 1 pathname  ws+&03C - IDE device 1 PTR " ,K ws+&040 -> intercepted -> IDE data even bytes (holds current command) 6 ws+&041 - IDE Error @ ws+&042 - IDE Count J, ws+&043 - IDE Sector LBA b0-b7 T- ws+&044 - IDE Cylinder Low LBA b8-b15 ^. ws+&045 - IDE Cylinder High LBA b16-b23 h. ws+&046 - IDE Head+Drive LBA b24-b27 r ws+&047 - IDE Status |1 ws+&048 -> intecepted -> IDE data odd bytes  ws+&049 -  ws+&04A -  ws+&04B -  ws+&04C -  ws+&04D - $ ws+&04E - [Alternative Status]  ws+&04F - [Drive Data] : Service_6502Base=&80AD0  mcode% &8000:ver$="0.10" sp=13:link=14:pc=15  p=0 1 P%=0:O%=mcode% [OPT p*3+4 EQUD 0:\start EQUD Initialise &EQUD Finalise 0EQUD Service :EQUD TitleStr DEQUD HelpStr NEQUD CommandTable XEQUD 0:\ SWI chunk number bEQUD 0:\ SWI chunk handler lEQUD 0:\ SWI decoding table vEQUD 0:\ SWI decoding code :  .TitleStr EQUS "BBCIDECard"  EQUB 0  ALIGN  .HelpStr 0EQUS "BBCIDECard"+9+ver$+" ("+$,5,11)+")"  EQUB 0  ALIGN : .CommandTable *EQUS "BBCIDE":EQUB 0:ALIGN:EQUD BBCIDE 6EQUD &00010001:EQUD BBCIDE_Syntax:EQUD BBCIDE_Help :  2EQUS "BBCIDELoad":EQUB 0:ALIGN:EQUD BBCIDELoad >EQUD &00010001:EQUD BBCIDELoad_Syntax:EQUD BBCIDELoad_Help  : *2EQUS "BBCIDESave":EQUB 0:ALIGN:EQUD BBCIDESave 4>EQUD &00010001:EQUD BBCIDESave_Syntax:EQUD BBCIDESave_Help >EQUB 0:ALIGN H: R.BBCIDE_Help \5EQUS "Specifies a BBCIDE image to access":EQUB 13 f.BBCIDE_Syntax p(EQUS "Syntax: BBCIDE ":EQUB 13 zEQUB 0:ALIGN : .BBCIDELoad_Help +EQUS "Loads data into a BBCIDE":EQUB 13 .BBCIDELoad_Syntax ,EQUS "Syntax: BBCIDELoad ":EQUB 13 EQUB 0:ALIGN : .BBCIDESave_Help +EQUS "Saves data from a BBCIDE":EQUB 13 .BBCIDESave_Syntax ,EQUS "Syntax: BBCIDESave ":EQUB 13 EQUB 0:ALIGN : : .Initialise stmfd (sp)!,{link} $ldr r0,[r12] .orrs r0,r0,#0 84bne Reinitialise ; We already have workspace B,mov r3,#256 ; We want 256 bytes Lmov r0,#6 Vswi "XOS_Module" `.ldmvsfd (sp)!,{pc} ; Memory claim failed j/str r2,[r12] ; Store in w/s pointer tmov r0,#0 ~/mov r1,#256/4 ; Loop for 256/4 words  .InitLoop 0str r0,[r2],#4 ; Zero workspace values subs r1,r1,#1 bne InitLoop .Reinitialise +cmp r0,r0 ; Clear flags, etc ldmfd (sp)!,{pc} : :  .Finalise stmfd (sp)!,{link}  - should have parameter 6stmfd (sp)!,{r0-r5,link} @* ; r0=>parameters J4ldr r12,[r12] ; Get address of workspace T6stmfd (sp)!,{r0} ; Save pointer to parameters ^6ldr r2,[r12,#&24] ; Get address of file buffer h.orrs r2,r2,r2 ; Does buffer exist? rbne BBCIDEBuffer |mov r3,#512 mov r0,#6 7swi "XOS_Module" ; Claim space for file buffer 3str r2,[r12,#&24] ; Store address of buffer .BBCIDEBuffer 3ldr r2,[r12,#&28] ; Get address of pathname 6orrs r2,r2,r2 ; Does pathname space exist? bne BBCIDEPathname mov r3,#256 mov r0,#6 4swi "XOS_Module" ; Claim space for pathname 5str r2,[r12,#&28] ; Store address of pathname .BBCIDEPathname :ldmfd (sp)!,{r0} ; Get pointer to parameters back ,mov r3,#0 ; Offset into name .BBCIDELoop )ldrb r1,[r0,r3] ; Get character &+strb r1,[r2,r3] ; Store character 0,cmp r1,#"!" ; Found char? :%bcc BBCIDENameDone ; Yes, stop D(add r3,r3,#1 ; Update index Ncmp r3,#255 X+bcc BBCIDELoop ; Loop while <256 b.BBCIDENameDone lmov r1,#13 v2strb r1,[r2,r3] ; Store terminating : /ldrb r0,[r2,#0] ; Get first character (cmp r0,#"!" ; Null filename? ,movcc r4,#0 ; Set size to zero ,bcc BBCIDENull ; Jump to set size 'mov r0,#5 ; r0=ReadInfo (mov r1,r2 ; r1=>filename 1swi "XOS_File" ; Read file information )ands r0,r0,#1 ; Is it a file? ;moveq r4,#0 ; Not a file - set length to zero .BBCIDENull &str r4,[r12,#&20] ; Store size mov r4,#0 ,str r4,[r12,#&2C] ; Zero and flags  ldmfd (sp)!,{r0-r5,pc} :  : *1.BBCIDELoad ; *BBCIDELoad 4stmfd (sp)!,{r0-r5,link} >4;ldr r12,[r12] ; Get address of workspace H.;add r2,r12,#512 ; Point to variables R0;add r2,r2,#20 ; Point to RAM address \+;ldr r1,[r2] ; Get RAM address f;orrs r1,r1,#0 p,;beq BBCIDENoRAM ; No RAM to load to z&;mov r3,#0 ; Load to r2 1;mov r2,r1 ; r2=address to load to (;mov r1,r0 ; r1=>filename !;mov r0,#&FF ; r0=Ǖ 4;swi "OS_File" ; Load the specified file ldmfd (sp)!,{r0-r5,pc} : : .BBCIDESave stmfd (sp)!,{r0-r5,link} 4;ldr r12,[r12] ; Get address of workspace .;add r2,r12,#512 ; Point to variables -;add r2,r2,#16 ; Point to RAM size +;ldr r3,[r2],#4 ; Set BBCIDE size +;ldr r1,[r2] ; Get RAM address ;orrs r1,r1,#0 ,;beq BBCIDENoRAM ; No RAM to load to $*;add r5,r1,r3 ; r5=end address .,;mov r4,r1 ; r4=start address 8;mov r2,#&FD B);orr r2,r2,#&0F00 ; r2=&FFD - '' L(;mov r1,r0 ; r1=>filename V);mov r0,#&0A ; r0=ǚ as type `4;swi "OS_File" ; Save the specified file jldmfd (sp)!,{r0-r5,pc} t: ~: .BBCIDENoRAM adr r0,Error_NoRAM swi "OS_GenerateError" ldmfd (sp)!,{r0-r5,pc} .Error_NoRAM equd &80AD0 equs "No BBCIDE memory" equb 0 align : : .Service ; In r0=mem[0] &; r1=Service_6502IN - &80AD0 &; r1=Service_6502OUT - &80AD1 &; r1=Service_6502Reset - &80AD2 (; r2=port 2; r3=value <; r4=Module base F; P5stmfd (sp)!,{r1} ; Save service call number Z*and r1,r1,#&FF000 ; Check b12-b19 d%cmp r1,#&80000 ; &80xxx ? n8ldmfd (sp)!,{r1} ; Restore service call number x1movne pc,link ; No -> exit unclaimed : stmfd (sp)!,{r1} and r1,r1,#&FF0 %cmp r1,#&AD0 ; &80ADx ? ldmfd (sp)!,{r1} movne pc,link ; No : stmfd (sp)!,{r1} and r1,r1,#&F -cmp r1,#&3 ; &80AD0..&80AD2 ? ldmfd (sp)!,{r1} movcs pc,link ; No : -stmfd (sp)!,{r2} ; Save port number -and r2,r2,#&FF00 ; Lose bottom byte )cmp r2,#&FC00 ; Port &FCxx ? "0ldmfd (sp)!,{r2} ; Restore port number ,1movne pc,link ; No -> exit unclaimed 6: @-stmfd (sp)!,{r2} ; Save port number J*and r2,r2,#&F0 ; Lose top byte T)cmp r2,#&40 ; Port &FC4x ? ^0ldmfd (sp)!,{r2} ; Restore port number h1movne pc,link ; No -> exit unclaimed r: |2ldr r12,[r12] ; Get workspace address 0stmfd (sp)!,{r1} ; Save service number 1and r1,r1,#&F ; Check service number %cmp r1,#&1 ; &80AD0 ? bcc Service_6502IN beq Service_6502OUT 2 ; Fall through to Reset : .Service_6502Reset ?ldmfd (sp)!,{r1} ; Restore call number, balance stack ;stmfd (sp)!,{link} ;ldmfd (sp)!,{link} (mov pc,link ; Don't claim : : ,.Service_6502IN ; Read from &FC4x ?ldmfd (sp)!,{r1} ; Restore call number, balance stack &; r0=z80mem[0] 0; r1=corruptable :"; r2=port number - corruptable D; r3=returns Read value N; r4=corruptable X; stack balanced b; l(and r2,r2,#&FF ; r2=low byte vcmp r2,#&40 ,beq ReadIDEByteLow ; Read from &FC40 cmp r2,#&48 ,beq ReadIDEByteHigh ; Read from &FC48 5ldrb r3,[r12,r2] ; Fetch byte from register +mov r1,#0 ; Claim the call mov pc,link : .ReadIDEByteLow .ReadIDEByteHigh (ldrb r1,[r12,#&46] ; Get IDEHead /ands r1,r1,#&10 ; Device 1 selected? /movne r1,#&20 ; Device not present 2bne WriteIDEStatus ; Return with error set 1ldr r1,[r12,#&2C] ; Get current offset 'orrs r1,r1,r1 ; Is zero? 2bne ReadByteClean ; No, buffer holds data : */ldr r1,[r12,#&24] ; Get buffer address 41orrs r1,r1,r1 ; Does a buffer exist? >2beq ReadByteEnd ; No buffer, exit early H: Rldr r1,[r12,#&40] \1and r1,r1,#&FF000000; LBA b0-b7 in b24-b31 f1ldr r0,[r12,#&44] ; LBA b8-b27 in b0-b19 p2mov r0,r0,lsl #16 ; LBA b8-b23 in b16-b31 z>orr r0,r0,r1,lsr #16; r1=++<&00> / ; r1=file required 'ldr r1,[r12,#&20] ; Drive size filename ; r2=spare ; r3=byte read ; r4=spare Bstmfd (sp)!,{link} ; Save link as we're going to use SWIs ,mov r4,r0 ; to read from $mov r0,#&40 .,swi "XOS_Find" ; Open for input 8/mov r3,#256 ; 256 bytes to read B(ldr r2,[r12,#&24] ; r2=>buffer L'mov r1,r0 ; r1=handle V4mov r0,#3 ; Read using specified `,swi "XOS_GBPB" ; Read to buffer jmov r0,#0 t(swi "XOS_Find" ; Close file ~*ldmfd (sp)!,{link} ; Restore link : .ReadByteClean ,ldr r1,[r12,#&24] ; Point to buffer 1ldr r0,[r12,#&2C] ; Get current offset 1ldrb r3,[r1,r0] ; Get byte from buffer /add r0,r0,#1 ; Increment offset 3str r0,[r12,#&2C] ; Store updated offset .ReadByteEnd +mov r1,#0 ; Claim the call mov pc,link : : +.Service_6502OUT ; Write to &FC4x  ?ldmfd (sp)!,{r1} ; Restore call number, balance stack ; r0=z80mem[0] ; r1=corruptable ("; r2=port number - corruptable 2; r3=Write value <; r4=corruptable F; stack balanced P; Z(and r2,r2,#&FF ; r2=low byte dcmp r2,#&40 n+beq WriteIDEByteLow ; Write to &FC40 xcmp r2,#&47 +beq WriteIDECommand ; Write to &FC47 cmp r2,#&48 +beq WriteIDEByteHigh; Write to &FC48 3strb r3,[r12,r2] ; Store byte to register +mov r1,#0 ; Claim the call mov pc,link : .WriteIDECommand 2strb r3,[r12,#&40] ; Store current command mov r1,#0 1str r1,[r12,#&2C] ; Clear current buffer .WriteIDEStatus *strb r1,[r12,#&47] ; Set IDEstatus mov r1,#0 +mov pc,link ; Claim the call ; ".WriteIDEByteLow ,.WriteIDEByteHigh 6(ldrb r1,[r12,#&46] ; Get IDEHead @/ands r1,r1,#&10 ; Device 1 selected? J/movne r1,#&20 ; Device not present T2bne WriteIDEStatus ; Return with error set ^1ldr r1,[r12,#&2C] ; Get current offset h,cmp r1,#256 ; Is buffer full? r+bcs WriteByteClean ; Buffer overrun |: /ldr r1,[r12,#&24] ; Get buffer address 1orrs r1,r1,r1 ; Does a buffer exist? 2beq WriteByteEnd ; No buffer, exit early : .WriteByteClean ,ldr r1,[r12,#&24] ; Point to buffer 1ldr r0,[r12,#&2C] ; Get current offset 1strb r3,[r1,r0] ; Put byte into buffer /add r0,r0,#1 ; Increment offset 3str r0,[r12,#&2C] ; Store updated offset ,cmp r0,#256 ; Is buffer full? 2bcc WriteByteEnd ; Buffer not full, exit : 6ldr r1,[r12,#&40] ; Get LBA b0-b7 in top byte 1and r1,r1,#&FF000000; LBA b0-b7 in b24-b31 1ldr r0,[r12,#&44] ; LBA b8-b27 in b0-b19 &2mov r0,r0,lsl #16 ; LBA b8-b23 in b16-b31 0>orr r0,r0,r1,lsr #16; r1=++<&00> :/ ; r1=file required D'ldr r1,[r12,#&20] ; Drive size Nfilename ; r2=spare !; r3=byte to write, now spare ; r4=spare Bstmfd (sp)!,{link} ; Save link as we're going to use SWIs +mov r4,r0 ; to write to mov r0,#&C0 -swi "XOS_Find" ; Open for update 0mov r3,#256 ; 256 bytes to write (ldr r2,[r12,#&24] ; r2=>buffer 'mov r1,r0 ; r1=handle  5mov r0,#1 ; Write using specified /swi "XOS_GBPB" ; Write from buffer  mov r0,#0 *(swi "XOS_Find" ; Close file 4*ldmfd (sp)!,{link} ; Restore link >: H.WriteByteEnd R+mov r1,#0 ; Claim the call \mov pc,link f: p: z ALIGN ] %"SAVE BBCIDE "+~mcode%+" "+~O% *SetType BBCIDE Module *Stamp BBCIDE