8.c (5382B)
1 #include <err.h> 2 #include <fcntl.h> 3 #include <limits.h> 4 #include <stdint.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <unistd.h> 9 10 #include <sys/types.h> 11 #include <sys/stat.h> 12 13 #include "av.h" 14 15 #define START 0x200 16 17 uint16_t opcode; 18 uint8_t *mem; 19 uint8_t V[16]; 20 uint16_t I; 21 uint16_t pc; 22 uint8_t scene[32*64]; 23 uint8_t delaytmr; 24 uint8_t soundtmr; 25 uint16_t stack[16]; 26 uint16_t *sp = stack; 27 uint8_t keys[16]; 28 29 uint8_t fnt[80] = 30 { 31 0xF0, 0x90, 0x90, 0x90, 0xF0, //0 32 0x20, 0x60, 0x20, 0x20, 0x70, //1 33 0xF0, 0x10, 0xF0, 0x80, 0xF0, //2 34 0xF0, 0x10, 0xF0, 0x10, 0xF0, //3 35 0x90, 0x90, 0xF0, 0x10, 0x10, //4 36 0xF0, 0x80, 0xF0, 0x10, 0xF0, //5 37 0xF0, 0x80, 0xF0, 0x90, 0xF0, //6 38 0xF0, 0x10, 0x20, 0x40, 0x40, //7 39 0xF0, 0x90, 0xF0, 0x90, 0xF0, //8 40 0xF0, 0x90, 0xF0, 0x10, 0xF0, //9 41 0xF0, 0x90, 0xF0, 0x90, 0x90, //A 42 0xE0, 0x90, 0xE0, 0x90, 0xE0, //B 43 0xF0, 0x80, 0x80, 0x80, 0xF0, //C 44 0xE0, 0x90, 0x90, 0x90, 0xE0, //D 45 0xF0, 0x80, 0xF0, 0x80, 0xF0, //E 46 0xF0, 0x80, 0xF0, 0x80, 0x80 //F 47 }; 48 49 static void 50 init(int fd, size_t sz) 51 { 52 size_t r; 53 54 mem = malloc(4096); 55 if (mem == NULL) 56 err(1, "malloc failed"); 57 memset(mem, 0, 4096); 58 59 pc = START; 60 memcpy(mem, fnt, 80); 61 while ((r = read(fd, mem + pc, sz)) != -1) { 62 sz -= r; 63 if (!sz) 64 break; 65 } 66 if (r == -1) 67 err(1, "read failed"); 68 } 69 70 void 71 predraw(unsigned short n, unsigned short x, unsigned y) 72 { 73 uint16_t px; 74 75 V[0xF] = 0; 76 for (int yy = 0; yy < n; ++yy) { 77 px = mem[I + yy]; 78 for (int xx = 0; xx < 8; ++xx) { 79 if ((px & (0x80 >> xx)) != 0) { 80 if (scene[(V[x] + xx + ((V[y] + yy) * 64))] == 1) 81 V[0xF] = 1; 82 scene[V[x] + xx + ((V[y] + yy) * 64)] ^= 1; 83 } 84 } 85 } 86 draw(scene); 87 } 88 89 static void 90 execute(void) 91 { 92 unsigned short x, y, c, n; 93 94 switch (opcode & 0xF000) { 95 case 0x0000: 96 switch (opcode & 0x0FFF) { 97 case 0xe0: 98 memset(scene, 0, 2048); 99 pc += 2; 100 return; 101 case 0xee: 102 pc = *sp--; 103 pc += 2; 104 return; 105 } 106 case 0x1000: 107 pc = opcode & 0x0FFF; 108 return; 109 case 0x2000: 110 *++sp = pc; 111 pc = opcode & 0x0FFF; 112 return; 113 case 0x3000: 114 x = (opcode & 0x0F00) >> 8; 115 c = opcode & 0x00FF; 116 if (V[x] == c) 117 pc += 2; 118 pc += 2; 119 return; 120 case 0x4000: 121 x = (opcode & 0x0F00) >> 8; 122 c = opcode & 0x00FF; 123 if (V[x] != c) 124 pc += 2; 125 pc += 2; 126 return; 127 case 0x5000: 128 x = (opcode & 0x0F00) >> 8; 129 y = (opcode & 0x00F0) >> 4; 130 if (V[x] == V[y]) 131 pc += 2; 132 pc += 2; 133 return; 134 case 0x6000: 135 x = (opcode & 0x0F00) >> 8; 136 c = opcode & 0x00FF; 137 V[x] = c; 138 pc += 2; 139 return; 140 case 0x7000: 141 x = (opcode & 0x0F00) >> 8; 142 c = opcode & 0x00FF; 143 V[x] += c; 144 pc += 2; 145 return; 146 case 0x8000: 147 x = (opcode & 0x0F00) >> 8; 148 y = (opcode & 0x00F0) >> 4; 149 pc += 2; 150 switch(opcode & 0x000F) { 151 case 0x0000: 152 V[x] = V[y]; 153 return; 154 case 0x0001: 155 V[x] |= V[y]; 156 return; 157 case 0x0002: 158 V[x] &= V[y]; 159 return; 160 case 0x0003: 161 V[x] ^= V[y]; 162 return; 163 case 0x0004: 164 V[0xF] = 0; 165 if (V[y] > CHAR_MAX - V[x]) 166 V[0xF] = 1; 167 V[x] += V[y]; 168 return; 169 case 0x0005: 170 V[0xF] = 0; 171 if (V[y] < V[x]) 172 V[0xF] = 1; 173 V[x] -= V[y]; 174 return; 175 case 0x0006: 176 V[0xF] = V[x] & 0x01; 177 V[x] >>= 1; 178 return; 179 case 0x0007: 180 V[0xF] = 0; 181 if (V[x] < V[y]) 182 V[0xF] = 1; 183 V[x] = V[y] - V[x]; 184 return; 185 case 0x000E: 186 V[0xF] = (V[x] >> 7) & 0x01; 187 V[x] <<= 1; 188 return; 189 default: 190 goto err; 191 } 192 case 0x9000: 193 x = (opcode & 0x0F00) >> 8; 194 y = (opcode & 0x00F0) >> 4; 195 if (V[x] != V[y]) 196 pc += 2; 197 pc += 2; 198 return; 199 case 0xA000: 200 I = opcode & 0x0FFF; 201 pc += 2; 202 return; 203 case 0xB000: 204 pc = V[0] + (opcode & 0x0FFF); 205 return; 206 case 0xC000: 207 x = (opcode & 0x0F00) >> 8; 208 c = (opcode & 0x00FF); 209 V[x] = (rand() % 256) & c; 210 pc += 2; 211 return; 212 case 0xD000: 213 n = (opcode & 0x00F); 214 x = (opcode & 0x0F00) >> 8; 215 y = (opcode & 0x00F0) >> 4; 216 predraw(n, x, y); 217 pc += 2; 218 return; 219 case 0xE000: 220 x = (opcode & 0x0F00) >> 8; 221 pc += 2; 222 switch (opcode & 0x00FF) { 223 case 0x009E: 224 if (key[V[x]]) 225 pc += 2; 226 return; 227 case 0x00A1: 228 if (!key[V[x]]) 229 pc += 2; 230 return; 231 default: 232 goto err; 233 } 234 case 0xF000: 235 x = (opcode & 0x0F00) >> 8; 236 pc += 2; 237 switch (opcode & 0x00FF) { 238 case 0x0007: 239 V[x] = delaytmr; 240 return; 241 case 0x000A: 242 for (int i = 0; i < 16; ++i) 243 if (key[i]) { 244 V[x] = i; 245 return; 246 } 247 pc -= 2; 248 return; 249 case 0x0015: 250 delaytmr = V[x]; 251 return; 252 case 0x0018: 253 soundtmr = V[x]; 254 return; 255 case 0x001E: 256 I += V[x]; 257 return; 258 case 0x0029: 259 I = V[x] * 5; 260 return; 261 case 0x0033: 262 mem[I] = (V[x] % 1000) / 100; 263 mem[I + 1] = (V[x] % 100) / 10; 264 mem[I + 2] = V[x] % 10; 265 return; 266 case 0x0055: 267 memcpy(mem + I, V, x+1); 268 return; 269 case 0x0065: 270 memcpy(V, mem + I, x+1); 271 return; 272 default: 273 goto err; 274 } 275 default: 276 goto err; 277 } 278 err: 279 fprintf(stderr, "Unknown opcode: 0x%X\n", opcode); 280 } 281 282 static void 283 die(void) 284 { 285 sdlquit(); 286 free(mem); 287 exit(0); 288 } 289 290 static void 291 cycle() 292 { 293 opcode = mem[pc] << 8 | mem[pc + 1]; 294 execute(); 295 handleev(); 296 if (quit) 297 die(); 298 usleep(1500); 299 } 300 301 static void 302 usage() 303 { 304 fprintf(stderr, "usage: 8 file.rom\n"); 305 exit(1); 306 } 307 308 int 309 main(int argc, char **argv) 310 { 311 struct stat st; 312 int fd; 313 314 if (argc < 2) 315 usage(); 316 317 if (stat(argv[1], &st) != 0) 318 err(1, "stat failed"); 319 320 if ((fd = open(argv[1], O_RDONLY)) == -1) 321 err(1, "open failed"); 322 323 sdlinit(); 324 init(fd, st.st_size); 325 for (;;) 326 cycle(); 327 return 0; 328 }