15PUZZLE.SRC (7856B)
1 ; From: SLSW2@cc.usu.edu (Roger Ivie) 2 ; 3 ; Here's PUZZLE.SRC, the infamous "15" puzzle for the calculator. I'm including 4 ; it mainly as an example of how to use my CHIP8 macros. 5 ; 6 ; When running PUZZLE, the 4x4 keyboard area used by CHIP8 corresponds to the 7 ; screen in the obvious manner. Simply press the key corresponding to the 8 ; location that you want the hole to be moved and it will migrate there. The 9 ; hole is moved up, down, left, then right until it winds up at the requested 10 ; location. 11 ; 12 ; Once the program is started, pressing ENTER randomizes the board (the magic 13 ; of self-modifying code). 14 ; 15 ; The program has absolutely no idea whether or not you've solved the puzzle, 16 ; so it doesn't do anything special. 17 ; 18 ; Enjoy, 19 ; 20 ; Roger Ivie 21 ; slsw2@cc.usu.edu 22 ; 23 ; PS: I'll post a binary as soon as I can get to my local Unix box again (the 24 ; hardware hackers have taken over). 25 26 27 ; Register usage: 28 ; 29 ; V0 - Used to grab things from memory 30 ; V1 - Current piece to be displayed 31 ; V2 - X coordinate where it is to be displayed 32 ; V3 - Y coordinate where it is to be displayed 33 ; V4 - General work; new hole position for swap_hole 34 ; V5 - General work 35 ; V6 - 36 ; V7 - 37 ; V8 - 38 ; V9 - 39 ; VA - 40 ; VB - 41 ; VC - Number of random moves to insert into the puzzle 42 ; VD - Desired position of the hole 43 ; VE - Current position of the hole 44 ; VF - 45 46 47 option binary 48 align off 49 50 CLS 51 52 START: 53 LD VC, 0 54 SNE VC, 0 55 DB #6E ; 6E0F -> VE = 15: number of moves to randomize 56 START+1: 57 DB #0F 58 LD I, START+1 ; Plug the number of moves to randomize 59 LD V0, 32 60 LD [I], V0 61 CLS ; Clear the screen 62 63 LOOP: 64 CALL GET_MOVE 65 CALL MOVE_UP 66 CALL MOVE_DOWN 67 CALL MOVE_LEFT 68 CALL MOVE_RIGHT 69 JP LOOP 70 71 ;------------------ 72 73 XSTART EQU 23 ; Horizontal position of board 74 YSTART EQU 4 ; Vertical position of board 75 XOFF EQU 5 ; Horizontal offset to next piece 76 YOFF EQU 6 ; Vertical offset to next piece 77 78 DISPLAY: 79 80 ; State 1: Initialize everything to be about the first piece on the board 81 ; and go to state 2. 82 83 DISPLAY_1: 84 LD V1,0 85 LD V2,XSTART 86 LD V3,YSTART 87 88 ; State 2: If all pieces have been displayed, exit. Otherwise, go to state 3. 89 90 DISPLAY_2: 91 SNE V1, #10 92 RET 93 94 ; State 3: Get the next piece to be displayed. If it's the hole (and therefore 95 ; shouldn't be displayed), go to state 5. Otherwise go to state 4. 96 97 DISPLAY_3: 98 LD I,BOARD 99 ADD I,V1 100 LD V0,[I] 101 SNE V0,0 102 JP DISPLAY_5 103 104 ; State 4: Display the current piece and go to state 5. 105 106 DISPLAY_4: 107 LD F, V0 108 DRW V2,V3,5 109 110 ; State 5: Advance the piece pointer and the horizontal position of the 111 ; display to the next piece. If the new piece is the first in a new row, 112 ; go to state 6. Otherwise go to state 2. 113 114 DISPLAY_5: 115 ADD V1,1 116 ADD V2,XOFF 117 LD V4,3 118 AND V4,V1 119 SE V4,0 120 JP DISPLAY_2 121 122 ; State 6: The piece is the first of a new row. Reinitialize the horizontal 123 ; position to the first of the row and advance the vertical position to the 124 ; next row. Go to state 2. 125 126 DISPLAY_6: 127 LD V2,XSTART ; Start at beginning of next row. 128 ADD V3,YOFF 129 JP DISPLAY_2 130 131 ;------- 132 133 MOVE_RIGHT: 134 135 ; State 1: Check to see if the desired hole position and the current hole 136 ; position are in the same column. If so, exit. Otherwise, go to state 2. 137 138 MOVE_RIGHT_1: 139 LD V4,3 ; Get horizontal position of hole 140 AND V4,VE 141 LD V5,3 ; Get horizontal position of new hole 142 AND V5,VD 143 SNE V4,V5 144 RET 145 146 ; State 2: If the hole cannot be moved any farther right, exit. Otherwise 147 ; go to state 3. 148 149 MOVE_RIGHT_2: 150 SNE V4,3 151 RET 152 153 ; State 3: Move the hole right one position and go back to state 1. 154 155 MOVE_RIGHT_3: 156 LD V4,1 157 ADD V4,VE 158 CALL SWAP_HOLE 159 JP MOVE_RIGHT_1 160 161 ;------- 162 163 MOVE_LEFT: 164 165 ; State 1: Check to see if the desired hole position and the current hole 166 ; position are in the same column. If so, exit. Otherwise, go to state 2. 167 168 MOVE_LEFT_1: 169 LD V4,3 ; Get horizontal position of hole 170 AND V4,VE 171 LD V5,3 ; Get horizontal position of new hole 172 AND V5,VD 173 SNE V4,V5 174 RET 175 176 ; State 2: If the hole cannot be moved any farther left, exit. Otherwise 177 ; go to state 3. 178 179 MOVE_LEFT_2: 180 SNE V4,0 181 RET 182 183 ; State 3: Move the hole left one position and go back to state 1. 184 185 MOVE_LEFT_3: 186 LD V4, #FF ; <LOW -1> 187 ADD V4,VE 188 CALL SWAP_HOLE 189 JP MOVE_LEFT_1 190 191 ;------- 192 193 MOVE_UP: 194 195 ; State 1: Check to see if the desired hole position and the current hole 196 ; position are in the same row. If so, exit. Otherwise, go to state 2. 197 198 MOVE_UP_1: 199 LD V4, #0C ; Get vertical position of hole 200 AND V4,VE 201 LD V5, #0C ; Get vertical position of new hole 202 AND V5,VD 203 SNE V4,V5 204 RET 205 206 ; State 2: If the hole cannot be moved any farther up, exit. Otherwise 207 ; go to state 3. 208 209 MOVE_UP_2: 210 SNE V4,0 211 RET 212 213 ; State 3: Move the hole up one position and go back to state 1. 214 215 MOVE_UP_3: 216 LD V4, #FC ;<LOW -4> Up = left 4 217 ADD V4,VE 218 CALL SWAP_HOLE 219 JP MOVE_UP_1 220 221 ;------- 222 223 MOVE_DOWN: 224 225 ; State 1: Check to see if the desired hole position and the current hole 226 ; position are in the same row. If so, exit. Otherwise, go to state 2. 227 228 MOVE_DOWN_1: 229 LD V4, #0C ; Get vertical position of hole 230 AND V4,VE 231 LD V5, #0C ; Get vertical position of new hole 232 AND V5,VD 233 SNE V4,V5 234 RET 235 236 ; State 2: If the hole cannot be moved any farther down, exit. Otherwise 237 ; go to state 3. 238 239 MOVE_DOWN_2: 240 SNE V4, #0C 241 RET 242 243 ; State 3: Move the hole down one position and go back to state 1. 244 245 MOVE_DOWN_3: 246 LD V4,4 ; Down = right 4 247 ADD V4,VE 248 CALL SWAP_HOLE 249 JP MOVE_DOWN_1 250 251 ;------- 252 253 SWAP_HOLE: 254 LD I,BOARD ; Get the piece at the new hole position 255 ADD I,V4 256 LD V0,[I] 257 LD I,BOARD ; Put it at the old hole position 258 ADD I,VE 259 LD [I],V0 260 LD V0,0 ; Put a hole... 261 LD I,BOARD ; ...at the new hole position 262 ADD I,V4 263 LD [I],V0 264 LD VE,V4 ; Move the hole marker to the new position 265 RET 266 267 ;------- 268 269 GET_MOVE: 270 271 ; State 1: Check to see if there are any more random moves to select. If so, 272 ; go to state 5. Otherwise go to state 2. 273 GET_MOVE_1: 274 SE VC,0 275 JP GET_MOVE_5 276 277 ; State 2: Prompt for and obtain a keystroke: display the board, wait for 278 ; a keystroke, and then erase the board. Go to state 4. 279 280 GET_MOVE_2: 281 CALL DISPLAY 282 CALL MYKEY 283 CALL DISPLAY 284 285 ; State 3: <deleted> 286 287 ; State 4: Translate the keystroke to the new hole position and exit. 288 289 GET_MOVE_4: 290 LD I,KEYTABLE 291 ADD I,VD 292 LD V0,[I] 293 LD VD,V0 294 RET 295 296 ; State 5: Decrement the count of random moves remaining, select a random 297 ; hole position, and exit. 298 299 GET_MOVE_5: 300 ADD VC, #FF ;<LOW -1> 301 RND VD, #0F 302 RET 303 304 ;------- 305 306 MYKEY: 307 308 ; State 1: Continuously scan the keyboard until a key is pressed. When a 309 ; key is pressed, go to state 2. 310 311 MYKEY_1: 312 ADD VD,1 ; Advance to next key number. 313 LD V0, #0F ; Make certain that it's not bigger than 0FH 314 AND VD,V0 315 SKP VD ; If this key is down, go to state 2. 316 JP MYKEY_1 ; Otherwise stay in state 1. 317 318 ; State 2: Wait for the key to be released. When it is, exit. 319 320 MYKEY_2: 321 SKNP VD 322 JP MYKEY_2 323 RET 324 325 ;------- 326 327 ; The puzzle board 328 329 BOARD: 330 DB 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 331 332 ; Translation table from key number to hole position 333 334 KEYTABLE: 335 DB #0D, #00, #01, #02 336 DB #04, #05, #06, #08 337 DB #09, #0A, #0C, #0E 338 DB #03, #07, #0B, #0F 339 340 END