CHANGED CODE PREVIOUS CODE --------------------------------------------------- *SpecCont: 027C STMDB R13!,{R14} 0280 ADR R1,L0250 ; Point to my name 0284 MOV R0,#2 0288 SWI "OS_Module" ; Run myself 028C LDMIA R13!,{PC} *Spectrum: 0290 STMDB R13!,{R14} 0294 LDR R12,[R12,#0] 0298 ADD R12,R12,#&0200 ; Point to the Z80 memory 029C BL L00000938 ; Zero all registers 02A0 ADR R1,L00000250 ; Point to my name 02A4 MOV R0,#2 02A8 SWI "OS_Module" ; Run myself 02AC LDMIA R13!,{PC} Clear registers: Called by Init, *Spectrum, error on TapeLoad 0938 MOV R0,#0 ; Clear registers ... 0994 B &31E0 ; Continue to do Srv_Z80Reset ; MOV PC,R14 Reset button pressed: 0A74 BL &31DC ; Send Srv_Z80Reset ; MOV R11,R12 B &3260 2D74 ... 72 bytes spare bytes ; D.J.Lawrence copyright string 2DBB ; Not referenced by anything 2FB4 BL &3204 ; ORR R0,R0,R1,LSL #8 2FD0 BL &3218 ; STR R4,[R12,#-84] 306C BL &3218 ; STR R4,[R12,#-84] ; Store PTR 310C MOV R6,R14 ; BIC R1,R1,#&F000 3110 BL &31AC ; EOR R1,R1,#&0700 3114 MOV R14,R6 ; EORS R1,R1,#&0001 3124 ADR R2,3148 ; ADR R2,3174 ; 3148 EQUS "SpecTape:":EQUB 0:ALIGN ; 3154 ...28 spare bytes... ; Previously space to expand 3170 ; Find ModuleBase: 3178 ADR R4,0000 ; Previously space to expand 317C MOV PC,R14 .OUT_A ; r0=port low ; r3=value ; Enter here with R3=data, R0:R3=port 3180 ORR R2,R0,R3,LSL #8 ; R2=port ; Enter here with R3=data, R2=port 3184 STRB R3,[r12,#-256] ; Save R3 ; Enter here with R3 saved, R3=data, R2=port 3188 STRB R4,[r12,#-252] ; Save R4 318C MOV R0,R14 ; Save link 3190 BL &3178 ; Find ModuleBase 3194 MOV R14,R0 ; Get link back 3198 LDR R1,[PC,#3*4] ; R1=Srv_Z80OUT 319C MOV R0,R12 ; R0=mem[0] 31A0 SWI "OS_ServiceCall" ; r0=mem[0], r1=Srv_Z80OUT, r2=port, r3=value, r4=module base 31A4 LDRB R4,[r12,#-252] ; Restore R4 31A8 LDRB R3,[r12,#-256] ; Restore R3 31AC MOV pc,link 31B0 EQUD Srv_Z80TubeOUT 3180 STRB R4,[r12,#-252] ; Save R4 3184 MOV R2,R14 ; Save link 3188 BL &3178 ; Find ModuleBase 318C MOV R14,R2 ; Get link back 3190 ORR R2,R0,R3,LSL #8 ; R2=port 3194 LDR R1,[PC,#3*4] ; R1=Srv_Z80OUT 3198 MOV R0,R12 ; R0=mem[0] 319C SWI "OS_ServiceCall" ; r0=mem[0], r1=Srv_Z80OUT, r2=port, r3=value, r4=module base 31A0 LDRB R4,[r12,#-252] ; Restore R4 31A4 MOV pc,link 31A8 EQUD Srv_Z80TubeOUT 31B4 BIC R1,R1,#&F000 31B8 STR R1,[R12,#-76] ; Store filetype 31BC CMP R1,#&700 31C0 BCS &31C8 31C4 EOR R1,R1,#&0100 ; Check for &11D 31C8 EORS R1,R1,#&1D 31CC MOV R15,R14 31D0 EOR R1,R1,#&700 ; Check for &701 31D4 EORS R1,R1,#1 31D8 MOV R15,R14 ; Overlaps with RESET return RESET: 31D8 MOV PC,R14 ; Remove initialise routine ; ; Send Srv_Z80Reset 31DC MOV R11,R12 ; z80pc=z80mem 31E0 STMDB R13!,{R14} ; Save link 31E4 BL &3178 ; Find ModuleBase 31E8 LDR R1,[PC,#16] 31EC MOV R0,#0 31F0 STR R0,[R12,#&BC-256] ; I=0, IFF=0 31F4 MOV R0,R12 ; R0=mem[0] 31F8 SWI "OS_ServiceCall" ; r0=mem[0], r1=Srv_Z80Reset[, r2=port, r3=value], r4=module base 31FC LDMIA R13!,{PC} 3200 EQUD &80AC2 ; Srv_Z80Reset 3204 ORR R0,R0,R1,LSL #8 3208 LDRB R1,[R12,#-76] 320C ANDS R1,R1,#4 3210 SUBNE R0,R0,#2 3214 MOV R15,R14 3218 LDR R0,[R12,#-76] 321C ANDS R0,R0,#4 3220 ADDNE R4,R4,#1 3224 STR R4,[R12,#-84] 3228 MOV R15,R14 ; just fits! Main code: 322C ; Spare bytes within opcodes Speculator: ; \ &D3 - OUT (nn),A LDRB R0,[R11],#1 CMP R0,#&FE BNE OUT_A ; Was MOVNE PC,R14 LDRB R0,[R12,#-100] AND R1,R3,#&17 EORS R2,R0,R1 SWINE &C0000 ; ULA IN/OUT call MOV PC,R14 : : \ &DB - IN A,(n) LDRB R1,[R11],#1:\ Get n CMP R1,#&FE MOVNV R3,#&FF ; Was MOVNE R3,#&FF BNE IN_Acont ; Was MOVNE PC,R14 ; If not IN A,(254), A=&FF MVN R0,#0 ; r0=-1 MOV R1,R3,LSL #24 ; r1=A in top byte MOV R3,#&FF ; prepare A with &FF .L0000694C ; Scan keyboard by looking at table updated in background by keyboard handler MOVS R1,R1,LSL #1 ; move a scanline bit into carry ADD R0,R0,#1 ; increment scanline pointer BCS L00006964 ; jump if bit set SUB R2,R12,#&20 ; point to keyscan table LDRB R2,[R2,R0] ; get byte from it AND R3,R3,R2 ; mask it into A .L00006964 CMP R0,#7 ; all eight scanlines done? BNE L0000694C ; jump back to check next scanline MOV PC,R14 FNz C2B8 c2D8 \ &C2F8 - &ED41 - OUT (C),B CMP R6,#&FE ; BNE out_CB ; MOVNE PC,R14 LDRB R0,[R12,#-100] AND R1,R5,#&17 EORS R2,R0,R1 SWINE &C0000 ; IN/OUT call MOV PC,R14 .out_CB STRB R3,[r12,#-256] ; Save R3 (A) STRB R4,[r12,#-252] ; Save R4 (F) MOV R2,R14 ; Save link BL &3178 ; Get ModuleBase to R4 MOV R14,R2 ; Get link back MOV R3,R5 ; R3=value ORR R2,R6,R5,LSL #8 ; R2=port B &3194 FNz C4F8 C6F8 C8F8 From Z80Tube: PRINT"\ &ED";~&41+a%*16;" - OUT (C),";LEFT$(FNr2(a%*2),1) PRINT"STRB Areg,[z80mem,#Acopy] :\ Save R3" PRINT"STRB Freg,[z80mem,#Fcopy] :\ Save R4" PRINT"LDR R4,[z80mem,#ModuleBase]:\ r4=my module" PRINT"MOV R3,";FNr2(a%*2);" :\ r3=value" PRINT"ORR Temp2,Creg,Breg,LSL #8 :\ r2=port" PRINT"LDR Temp1,[pc,#4*4] :\ Get service call number" PRINT"MOV Temp0,z80mem :\ r0=mem[0]" PRINT"SWI ""OS_ServiceCall"" :\ Do an OUT call" PRINT"LDRB Freg,[z80mem,#Fcopy] :\ Restore R4" PRINT"LDRB Areg,[z80mem,#Acopy] :\ Restore R3" PRINT"MOV pc,link" PRINT"EQUD Srv_Z80OUT :\ Service call number" PRINT":" PRINT".RestoreED";~a%*16 PRINT"LDRB Areg,[z80mem,#Acopy] :\ Restore R3(A)" PRINT"ORR Freg,Freg,Temp1 :\ Set parity" PRINT"MOV pc,link" PRINT"EQUD Srv_Z80IN :\ Service call number" PRINT"FNz" .OUT_A ; r0=port low ; r3=value ; space for 9 ops ; This needs putting somewhere: .IN_Acont ; r1=port lo ORR R2,R1,R3,LSL #8 LDR R1,[pc,#4*3] MOV R0,R11 MOV R3,#&FF SWI "OS_ServiceCall" MOV pc,link EQUD Srv_Z80TubeIN FNz OUT (C),R CMP R,#&FE BNE DoOUTR ... DoOUTR Z80Tube: \ &D3 - OUT (nn),A LDRB Temp2,[z80pc],#1 ORR Temp2,Temp2,Areg,LSL #8 LDR Temp1,[pc,#4*2] MOV Temp0,z80mem SWI "OS_ServiceCall" MOV pc,link EQUD Srv_Z80TubeOUT \ &DB - IN A,(nn) LDRB Temp2,[z80pc],#1 ORR Temp2,Temp2,Areg,LSL #8 LDR Temp1,[pc,#4*3] MOV Temp0,z80mem MOV Areg,#&FF SWI "OS_ServiceCall" MOV pc,link EQUD Srv_Z80TubeIN FNz \ &ED40 - IN B,(C) STRB Areg,[z80mem,#Acopy] :\ Save R3 MOV Temp0,z80mem :\ r0=mem[0] LDR Temp1,[pc,#4*11] :\ r1=service call number ORR Temp2,Creg,Breg,LSL #8 :\ r2=port MOV Areg,#&FF :\ r3=&FF in case no response SWI "OS_ServiceCall" :\ Do an IN call MOVS Breg,Areg :\ Store returned value AND Freg,Freg,#&29 ORREQ Freg,Freg,#Zflag ORRMI Freg,Freg,#Sflag SUB Temp0,z80mem,#&200 LDRB Temp1,[Temp0,Areg] ORR Freg,Freg,Temp1 :\ Set parity LDRB Areg,[z80mem,#Acopy] :\ Restore Areg MOV pc,link EQUD Srv_Z80TubeIN :\ Service call number FNz \ &ED41 - OUT (C),B STRB Areg,[z80mem,#Acopy] :\ Save R3 MOV Temp0,z80mem :\ r0=mem[0] LDR Temp1,[pc,#4*4] :\ Get service call number ORR Temp2,Creg,Breg,LSL #8 :\ r2=port MOV R3,Breg :\ r3=value SWI "OS_ServiceCall" :\ Do an OUT call LDRB Areg,[z80mem,#Acopy] :\ Restore R3 MOV pc,link EQUD Srv_Z80TubeOUT :\ Service call number FNz Notes: within Z80 code: &DD &DD - fetch byte from tapefile inserted at start of LD_START, &056C &FD &FD - Exit from emulator inserted at start of CAT/ERASE/FORMAT/MOVE at &1793 *SpecCont mustn't do Serv_Z80Reset ROMBox should check current page select and not copy if already correct. DAA doesn't work correctly after SUB, u3 hex output doesn't work ---------- xyDD: &129F8 MOV R0,[R11,-2] ; Get DD/FD byte CMP R0,#&FD BNE &2F30 ; Jump to LD_START with &DDDD B xxxx ; Jump to SV_START with &FDDD