ZA80 Z80 Cross Assembler V1.14 (Amiga) 20-Oct-1993 21:03 Page 1 1 ; MULTISEARCH - ZX BASIC SEARCH & REPLACE tool 2 ; Copyright 1985,1993 Simon N Goodwin. 3 ; Relocatable Z80 code, 225 bytes long 4 ; 5 0000 LFMT 64,96,3  6 0000 LPRT 1,27,91,50,119 7 ; 8 ; The above assembler directives for the ZA80 printer/list 9 ; file select Elite pitch on the HP Deskjet 500 printer. 10 ; 11 ; Based on my article in YOUR SPECTRUM #12, pages 47-53 12 ; Test file for ZA80 cross assembler, version 1.06 13 ; This file may be freely distributed only as part of 14 ; the SPECULATOR Amiga Spectrum emulator release. 15 ; 16 ;-------------------------------------------------------- 17 ; 18 ; USAGE: Set S$ to the string you want to find (1-255 19 ; bytes) and R$ to the replacement string (0-255 bytes) 20 ; Call the start of the code (e.g. with PRINT USR 23296 21 ; if loaded in the printer buffer) to replace all cases 22 ; of the text in S$ in the program with the text in R$. 23 ; For example: 24 ; 25 ; 10 LET S$="S$=" 26 ; 20 LET R$="X$=" 27 ; 30 LOAD "MULTISEARCH" CODE 23296 28 ; 40 RANDOMIZE USR 23296 29 ; 30 ; When you run this, line 10 will be changed to read: 31 ; 32 ; 10 LET X$="X$=" 33 ; 34 ; NOTES: MULTISEARCH does not replace the floating-point 35 ; form of numbers unless you specify it in both strings. The 36 ; YS article explains how to add the f.p. form to the digits. 37 ; 38 ; The changed lines are not error-checked so you may get a 39 ; 'nonsense in BASIC' or other error reports at run-time if 40 ; the altered line is not correct ZX BASIC. 41 ; 42 ; REPORTS: 43 ; 44 ; BREAK IN PROGRAM User pressed SPACE while searching. Some 45 ; changes may not have been made. 46 ; 47 ; NONSENSE IN BASIC The altered program does not pass the ZX 48 ; BASIC syntax checker. Change it back, or 49 ; reload the original version! 50 ; 51 ; OK The requested changes have been made. 52 ; 53 ; OUT OF MEMORY the replacement is longer than the 54 ; pattern and MULTISEARCH ran out of memory 55 ; before it reached the end of the program. 56 57 ; PARAMETER ERROR Search string is null, or either string 58 ; is more than 255 characters long. 59 ; 60 ; VARIABLE NOT FOUND Either S$ or R$ is not assigned. 61 ; 62 ; The value returned by the USR call is not meaningful. ZA80 Z80 Cross Assembler V1.14 (Amiga) 20-Oct-1993 21:03 Page 2 63 ; 64 ;-------------------------------------------------------- 65 ; 66 ; Spectrum ZX BASIC system variable addresses 67 ; 68 = 5C53 PROG: EQU 23635 ; Points to start of program 69 = 5C4B VARS: EQU 23627 ; Points to start of variables 70 ; 71 ; Temporary variables, allocated in ZX BASIC's MEM area 72 ; 73 = 5CAE R_LEN: EQU 23726 ; Pointer to replacement 74 = 5CAC L_LEN: EQU 23724 ; Pointer to line length word 75 ; 76 ; 16K ZX ROM routine addresses 77 ; 78 ; SHRINK and EXPAND allocate or deallocate BC bytes at HL 79 ; If space is tight EXPAND may return an 'out of memory' error 80 ; 81 = 19E8 SHRINK: EQU 19E8H ; Deallocate BASIC space 82 = 1655 EXPAND: EQU 1655H ; Allocate more BASIC space 83 = 19B8 F_VAR: EQU 19B8H ; Find next variable 84 ; 85 ; Byte constants 86 ; 87 = 0003 CODE: EQU 3 ; ZX file type 88 = 000E NUMBER: EQU 14 ; Code prefix of imbedded numbers 89 = 000D ENTER: EQU 13 ; ASCII code of line end character 90 = 0080 T_END: EQU 128 ; Marker at end of variable table 91 ; 92 ; Amiga Speculator header - N.B. word values are Big Endian 93 ; 94 0000 5A583832 HEADER: DB "ZX82" ; Header signature 95 0004 0300 DB CODE,0 ; File type, uncompressed 96 0006 00E1 DB 0,LAST-FIND_S ; Length - high byte (0) first 97 0008 5B00 DB FIND_S/256,FIND_S & 255 ; Start (relocatable) 98 000A 8000 DW 80H ; BASIC variable offset (unused) 99 ; 100 000C ORG 23296 ; Start in the printer buffer 101 ; 102 5B00 2A4B5C FIND_S: LD HL,(VARS) ; Find search string S$ 103 5B03 7E NEXT1: LD A,(HL) 104 5B04 FE53 CP "S" ; Capital S signifies S$ 105 5B06 280E JR Z,GOT_S 106 5B08 FE80 CP T_END 107 5B0A 2806 JR Z,ERROR 108 5B0C CDB819 CALL F_VAR ; Find the next variable 109 5B0F EB EX DE,HL 110 5B10 18F1 JR NEXT1 111 ; 112 5B12 CF ERROR: RST 8 113 5B13 01 DB 1 ; Variable not found 114 ; 115 5B14 CF LEN_ERR: RST 8 116 5B15 19 DB 25 ; Parameter error (wrong string lengt h) 117 ; 118 ; Now HL points at the string name S$, check its length 119 ; 120 5B16 23 GOT_S: INC HL 121 5B17 7E LD A,(HL) ; Check it is not null 122 5B18 B7 OR A 123 5B19 28F9 JR Z,LEN_ERR ZA80 Z80 Cross Assembler V1.14 (Amiga) 20-Oct-1993 21:03 Page 3 124 5B1B 23 INC HL 125 5B1C 7E LD A,(HL) ; and not more than 255 bytes long 126 5B1D B7 OR A 127 5B1E 20F4 JR NZ,LEN_ERR 128 5B20 23 INC HL 129 5B21 E5 PUSH HL 130 5B22 DDE1 POP IX ; Now IX -> text of S$ 131 ; 132 5B24 2A4B5C FINDR: LD HL,(VARS) ; Find search string S$ 133 5B27 7E NEXT2: LD A,(HL) 134 5B28 FE52 CP "R" ; Capital R signifies R$ 135 5B2A 280A JR Z,GOT_R 136 5B2C FE80 CP T_END ; Any more variables? 137 5B2E 28E2 JR Z,ERROR 138 5B30 CDB819 CALL F_VAR ; Find the next one 139 5B33 EB EX DE,HL 140 5B34 18F1 JR NEXT2 141 ; 142 5B36 23 GOT_R: INC HL 143 5B37 22AE5C LD (R_LEN),HL 144 5B3A 23 INC HL 145 5B3B 7E LD A,(HL) ; Not more than 255 bytes 146 5B3C B7 OR A 147 5B3D 20D5 JR NZ,LEN_ERR 148 ; 149 ; Prepare to search program 150 ; 151 5B3F ED5B535C LD DE,(PROG) 152 5B43 1B DEC DE ; Dummy line-end 153 ; 154 ; Main search loop; first find line-length 155 ; 156 5B44 13 LINE: INC DE ; Skip past line end marker 157 5B45 13 INC DE ; Skip past line number 158 5B46 13 INC DE 159 5B47 ED53AC5C LD (L_LEN),DE 160 5B4B 13 INC DE 161 5B4C 13 INC DE 162 5B4D D5 FIND: PUSH DE 163 5B4E DD46FE LD B,(IX-2) ; Pattern length in B 164 5B51 DDE5 PUSH IX 165 5B53 E1 POP HL 166 5B54 1A MATCH: LD A,(DE) 167 5B55 BE CP (HL) 168 5B56 2067 JR NZ,GO_ON 169 5B58 23 INC HL 170 5B59 13 INC DE 171 5B5A 10F8 DJNZ MATCH 172 ; 173 ; Match found, work out delta length 174 ; 175 5B5C 2AAE5C LD HL,(R_LEN) 176 5B5F 7E LD A,(HL) 177 5B60 DD96FE SUB (IX-2) ; A is extra space needed 178 5B63 2849 JR Z,LEN_OK 179 5B65 302C JR NC,ADD_A 180 ; 181 ; Discard 256-A bytes from program 182 ; 183 5B67 ED44 NEG 184 5B69 4F LD C,A 185 5B6A 2AAC5C LD HL,(L_LEN) ZA80 Z80 Cross Assembler V1.14 (Amiga) 20-Oct-1993 21:03 Page 4 186 5B6D 5E LD E,(HL) 187 5B6E 23 INC HL 188 5B6F 56 LD D,(HL) 189 5B70 EB EX DE,HL 190 5B71 B7 OR A 191 5B72 ED42 SBC HL,BC ; New line length 192 5B74 EB EX DE,HL 193 5B75 72 LD (HL),D 194 5B76 2B DEC HL 195 5B77 73 LD (HL),E 196 ; 197 ; Adjust pointers to R$ and S$ 198 ; 199 5B78 DDE5 PUSH IX 200 5B7A E1 POP HL 201 5B7B ED42 SBC HL,BC 202 5B7D E5 PUSH HL 203 5B7E DDE1 POP IX 204 5B80 2AAE5C LD HL,(R_LEN) 205 5B83 ED42 SBC HL,BC 206 5B85 22AE5C LD (R_LEN),HL 207 5B88 E1 POP HL 208 5B89 E5 PUSH HL ; Shrink from start 209 5B8A CDE819 CALL SHRINK 210 5B8D 181F JR LEN_OK 211 ; 212 ; Extended jumps to ensure relocatability 213 ; 214 5B8F 18BC FINDX: JR FIND 215 5B91 18B1 LINEX: JR LINE 216 ; 217 ; Add A bytes to program 218 ; 219 5B93 4F ADD_A: LD C,A 220 5B94 D5 PUSH DE 221 5B95 2AAC5C LD HL,(L_LEN) 222 5B98 5E LD E,(HL) 223 5B99 23 INC HL 224 5B9A 56 LD D,(HL) 225 5B9B EB EX DE,HL 226 5B9C 09 ADD HL,BC ; New line length 227 5B9D EB EX DE,HL 228 5B9E 72 LD (HL),D 229 5B9F 2B DEC HL 230 5BA0 73 LD (HL),E 231 ; 232 ; Adjust pointers to R$ and S$ 233 ; 234 5BA1 DD09 ADD IX,BC 235 5BA3 2AAE5C LD HL,(R_LEN) 236 5BA6 09 ADD HL,BC 237 5BA7 22AE5C LD (R_LEN),HL 238 5BAA E1 POP HL 239 5BAB CD5516 CALL EXPAND 240 ; 241 ; Copy new data to the space in the program 242 ; 243 5BAE D1 LEN_OK: POP DE 244 5BAF 2AAE5C LD HL,(R_LEN) 245 5BB2 0600 LD B,0 246 5BB4 4E LD C,(HL) 247 5BB5 79 LD A,C ZA80 Z80 Cross Assembler V1.14 (Amiga) 20-Oct-1993 21:03 Page 5 248 5BB6 B7 OR A ; Check if replacement is null 249 5BB7 2808 JR Z,NEXT 250 5BB9 23 INC HL ; Bump HL past length word 251 5BBA 23 INC HL 252 5BBB EDB0 LDIR 253 5BBD 1802 JR NEXT ; Search on from (DE) 254 ; 255 ; Check the next position 256 ; 257 5BBF D1 GO_ON: POP DE 258 5BC0 13 INC DE 259 5BC1 3E7F NEXT: LD A,127 ; Poll last keyboard row 260 5BC3 DBFE IN A,(254) ; Via the ZX82 ULA port 261 5BC5 1F RRA 262 5BC6 3802 JR C,CONTINUE 263 5BC8 CF RST 8 264 5BC9 14 DB 20 265 ; 266 5BCA 2A4B5C CONTINUE: LD HL,(VARS) 267 5BCD B7 OR A ; Ensure carry is clear 268 5BCE ED52 SBC HL,DE 269 5BD0 D8 RET C ; Return at end of program 270 5BD1 1A LD A,(DE) 271 5BD2 FE0D CP ENTER ; End of line? 272 5BD4 28BB JR Z,LINEX 273 5BD6 FE0E CP NUMBER 274 5BD8 20B5 JR NZ,FINDX ; Keep looking 275 5BDA 210600 LD HL,6 276 5BDD 19 ADD HL,DE ; Skip marker & 5 binary bytes 277 5BDE EB EX DE,HL 278 5BDF 18E9 JR CONTINUE 279 ; 280 5BE1 LAST: END ZA80 Z80 Cross Assembler V1.14 (Amiga) 20-Oct-1993 21:03 Page 6 ADD_A 5B93H 23443 CODE 0003H 3 CONTINUE 5BCAH 23498 ENTER 000DH 13 ERROR 5B12H 23314 EXPAND 1655H 5717 FIND 5B4DH 23373 FINDR 5B24H 23332 FINDX 5B8FH 23439 F_VAR 19B8H 6584 FIND_S 5B00H 23296 GOT_R 5B36H 23350 GOT_S 5B16H 23318 GO_ON 5BBFH 23487 HEADER 0000H 0 LAST 5BE1H 23521 LINE 5B44H 23364 LINEX 5B91H 23441 L_LEN 5CACH 23724 LEN_OK 5BAEH 23470 LEN_ERR 5B14H 23316 MATCH 5B54H 23380 NEXT 5BC1H 23489 NEXT1 5B03H 23299 NEXT2 5B27H 23335 NUMBER 000EH 14 PROG 5C53H 23635 R_LEN 5CAEH 23726 SHRINK 19E8H 6632 ZA80 Z80 Cross Assembler V1.14 (Amiga) 20-Oct-1993 21:03 Page 7 T_END 0080H 128 VARS 5C4BH 23627