Changes in / [4f967e8:5475ecf] in buchla-emu
- Location:
- emu
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
emu/all.h
r4f967e8 r5475ecf 111 111 extern void lcd_write(uint32_t off, int32_t sz, uint32_t val); 112 112 113 extern void lcd_sdl(void); 114 113 115 extern void ser_init(void); 114 116 extern void ser_quit(void); -
emu/lcd.c
r4f967e8 r5475ecf 22 22 #define ver3(...) _ver(lcd_verbose, 2, __VA_ARGS__) 23 23 24 #define WIN_W (1634 * 2 / 3) 25 #define WIN_H (342 * 2 / 3) 26 27 #define CON_W 86 28 #define CON_H 9 29 30 #define CON_BGR 0x00000000 31 #define CON_BEL 0x00808080 32 #define CON_CUR 0x00e87000 33 #define CON_FGR ((SDL_Color){ .r = 255, .b = 255, .g = 255, .a = 255 }) 34 35 #define BEL_CYC 10000 36 37 #define G_INIT 0x40 38 #define G_MWRITE 0x42 39 #define G_MREAD 0x43 40 #define G_SETSAD 0x44 41 #define G_CRSWR 0x46 42 #define G_CRSRD 0x47 43 #define G_CRSMRT 0x4C 44 #define G_CRSMLT 0x4D 45 #define G_CRSMUP 0x4E 46 #define G_CRSMDN 0x4F 47 #define G_ERASE 0x52 48 #define G_SLEEP 0x53 49 #define G_DSPOFF 0x58 50 #define G_DSPON 0x59 51 #define G_HSCRL 0x5A 52 #define G_OVRLAY 0x5B 53 #define G_CGRAM 0x5C 54 #define G_CRSFRM 0x5D 55 56 static uint8_t mem[CON_H][CON_W + 1]; 57 58 static SDL_Window *win; 59 static SDL_Renderer *ren; 60 static SDL_atomic_t frame; 61 62 static uint32_t render = 0; 63 64 static TTF_Font *fon; 65 static int32_t fon_w, fon_h; 66 67 static int32_t sur_w, sur_h; 68 static SDL_Surface *sur; 69 70 static int32_t cur_x = 0, cur_y = 0; 71 static int32_t bel = 0; 72 73 static int32_t current_op = 0x00; 74 static uint32_t cur_ad = 0; 75 static int32_t cur_ad_c = 0; 76 77 static uint32_t last_val = 0x00; 78 static uint32_t last_off = 0; 79 static int32_t last_sz = -1; 80 static int32_t mult_val_c = 0; 81 82 static void (*cursdir)(void); 83 24 84 int32_t lcd_verbose = 0; 25 85 86 static void scroll(void) 87 { 88 memmove(mem, mem + 1, (CON_H - 1) * (CON_W + 1)); 89 memset(mem + (CON_H - 1), ' ', CON_W); 90 } 91 92 static void forw(void) 93 { 94 if (cur_x < CON_W - 1) { 95 ++cur_x; 96 return; 97 } 98 99 if (cur_y == CON_H - 1) { 100 cur_x = 0; 101 scroll(); 102 return; 103 } 104 105 cur_x = 0; 106 ++cur_y; 107 } 108 109 static void back(void) 110 { 111 if (cur_x > 0) { 112 --cur_x; 113 return; 114 } 115 116 if (cur_y == 0) { 117 return; 118 } 119 120 cur_x = CON_W - 1; 121 --cur_y; 122 } 123 124 static void up(void) 125 { 126 if (cur_y > 0) { 127 --cur_y; 128 return; 129 } 130 131 // TODO: What happens when cursor out of bounds 132 } 133 134 static void down(void) 135 { 136 if (cur_y < CON_H - 1) { 137 ++cur_y; 138 return; 139 } 140 141 // TODO: What happens when cursor out of bounds 142 } 143 144 static void mvcur(uint32_t cur_addr) { 145 uint32_t n_cur_x = cur_addr % 85; 146 uint32_t n_cur_y = cur_addr / 85; 147 148 ver2("lcd cur x %u\n", n_cur_x); 149 ver2("lcd cur y %u\n", n_cur_y); 150 151 if (n_cur_x < CON_W - 1) { 152 cur_x = (int32_t) n_cur_x; 153 } 154 else { 155 err("invalid x cursor pos in lcd %u:%d", n_cur_x, CON_W); 156 } 157 158 if (n_cur_y < CON_H - 1) { 159 cur_y = (int32_t) n_cur_y; 160 } 161 else { 162 cur_x = 0; 163 cur_y = 9; 164 err("invalid y cursor pos in lcd %u:%d", n_cur_y, CON_H); 165 } 166 } 167 168 static void echo(uint8_t c) 169 { 170 if (c >127) { 171 return; 172 } 173 else if (c < 32) { 174 switch (c) { 175 case '\r': 176 cur_x = 0; 177 break; 178 179 case '\n': 180 down(); 181 break; 182 183 case '\b': 184 back(); 185 break; 186 187 case '\a': 188 bel = BEL_CYC; 189 break; 190 191 case 0: 192 mem[cur_y][cur_x] = ' '; 193 (*cursdir)(); 194 break; 195 196 case 28: 197 // TODO 198 echo('^'); 199 echo((uint8_t)(c + '@')); 200 break; 201 202 default: 203 echo('^'); 204 echo((uint8_t)(c + '@')); 205 ver2("lcd default case echo %u", c); 206 return; 207 } 208 } 209 else { 210 mem[cur_y][cur_x] = c; 211 (*cursdir)(); 212 } 213 214 if (render) { 215 SDL_AtomicAdd(&frame, 1); 216 } 217 } 218 219 static void clear_mem(void) { 220 for (int32_t y = 0; y < CON_H; ++y) { 221 for (int32_t x = 0; x < CON_W; ++x) { 222 mem[y][x] = ' '; 223 } 224 225 mem[y][CON_W] = 0; 226 } 227 } 228 229 void lcd_sdl(void) 230 { 231 ver3("lcd_sdl()"); 232 233 static int32_t last = 0; 234 int32_t now = SDL_AtomicGet(&frame); 235 236 if (last == now) { 237 ver3("no update"); 238 return; 239 } 240 241 last = now; 242 243 if (SDL_FillRect(sur, NULL, bel == 0 ? CON_BGR : CON_BEL) < 0) { 244 fail("SDL_FillRect() failed: %s", SDL_GetError()); 245 } 246 247 if (SDL_FillRect(sur, &(SDL_Rect){ 248 .x = cur_x * fon_w, 249 .y = cur_y * fon_h, 250 .w = fon_w, 251 .h = fon_h 252 }, CON_CUR) < 0) { 253 fail("SDL_FillRect() failed: %s", SDL_GetError()); 254 } 255 256 for (int32_t y = 0; y < CON_H; ++y) { 257 char line[CON_W + 1]; 258 259 if (SDL_LockMutex(cpu_mutex) < 0) { 260 fail("SDL_LockMutex() failed: %s", SDL_GetError()); 261 } 262 263 memcpy(line, mem[y], CON_W + 1); 264 265 if (SDL_UnlockMutex(cpu_mutex) < 0) { 266 fail("SDL_UnlockMutex() failed: %s", SDL_GetError()); 267 } 268 269 SDL_Surface *lin = TTF_RenderText_Blended(fon, line, CON_FGR); 270 271 if (lin == NULL) { 272 fail("TTF_RenderText_Blended() failed: %s", TTF_GetError()); 273 } 274 275 if (SDL_BlitSurface(lin, NULL, sur, &(SDL_Rect){ 276 .x = 0, 277 .y = y * fon_h, 278 .w = CON_W * fon_w, 279 .h = fon_h 280 })) { 281 fail("SDL_BlitSurface() failed: %s", SDL_GetError()); 282 } 283 284 SDL_FreeSurface(lin); 285 } 286 287 SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, sur); 288 289 if (tex == NULL) { 290 fail("SDL_CreateTextureFromSurface() failed: %s", SDL_GetError()); 291 } 292 293 if (SDL_RenderCopy(ren, tex, NULL, NULL) < 0) { 294 fail("SDL_RenderCopy() failed: %s", SDL_GetError()); 295 } 296 297 SDL_DestroyTexture(tex); 298 SDL_RenderPresent(ren); 299 } 300 301 26 302 void lcd_init(void) 27 303 { 28 304 ver("lcd init"); 305 306 win = SDL_CreateWindow("Front LCD", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 307 WIN_W, WIN_H, 0); 308 309 if (win == NULL) { 310 fail("SDL_CreateWindow() failed: %s", SDL_GetError()); 311 } 312 313 ren = SDL_CreateRenderer(win, -1, 0); 314 315 if (ren == NULL) { 316 fail("SDL_CreateRenderer() failed: %s", SDL_GetError()); 317 } 318 319 SDL_AtomicSet(&frame, 1); 320 321 SDL_RWops *ops = SDL_RWFromFile(font, "rb"); 322 323 if (ops == NULL) { 324 fail("error while opening font file %s: %s", font, SDL_GetError()); 325 } 326 327 fon = TTF_OpenFontRW(ops, 1, 32); 328 329 if (fon == NULL) { 330 fail("error while loading font file %s: %s", font, TTF_GetError()); 331 } 332 333 fon_h = TTF_FontLineSkip(fon); 334 335 if (TTF_GlyphMetrics(fon, 'X', NULL, NULL, NULL, NULL, &fon_w) < 0) { 336 fail("error while measuring font width: %s", TTF_GetError()); 337 } 338 339 sur_w = CON_W * fon_w; 340 sur_h = CON_H * fon_h; 341 342 sur = SDL_CreateRGBSurface(0, sur_w, sur_h, 32, 0, 0, 0, 0); 343 344 if (sur == NULL) { 345 fail("SDL_CreateRGBSurface() failed: %s", SDL_GetError()); 346 } 347 348 clear_mem(); 349 29 350 } 30 351 … … 32 353 { 33 354 ver("lcd quit"); 355 356 SDL_FreeSurface(sur); 357 TTF_CloseFont(fon); 358 359 SDL_DestroyRenderer(ren); 360 SDL_DestroyWindow(win); 34 361 } 35 362 … … 43 370 { 44 371 ver2("lcd rd %u:%d", off, sz * 8); 45 return 0; 372 373 uint32_t rv; 374 375 switch (current_op) { 376 case G_MREAD: 377 ver2("lcd current op: %d\n", current_op); 378 rv = mem[cur_y][cur_x]; 379 break; 380 381 default: 382 rv = 0x00; 383 break; 384 } 385 return rv; 46 386 } 47 387 48 388 void lcd_write(uint32_t off, int32_t sz, uint32_t val) 49 389 { 50 ver2("lcd wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val); 51 } 390 391 if(last_val != val && mult_val_c > 0) { 392 if(mult_val_c > 1) { 393 ver2("lcd wr %u:%d 0x%0*x was called %u more times", last_off, last_sz * 8, last_sz * 2, last_val, mult_val_c); 394 } 395 else { 396 ver2("lcd wr %u:%d 0x%0*x", last_off, last_sz * 8, last_sz * 2, last_val); 397 } 398 399 ver2("lcd wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val); 400 mult_val_c = 0; 401 } 402 else if(last_val == val && mult_val_c >= 0) { 403 ++mult_val_c; 404 } 405 else { 406 ver2("lcd wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val); 407 } 408 409 last_val = val; 410 last_off = off; 411 last_sz = sz; 412 413 if (off == 0) { 414 switch (current_op) { 415 case G_MWRITE: 416 echo((uint8_t)val); 417 break; 418 419 case G_CRSWR: 420 if (cur_ad_c == 0) { 421 cur_ad = val; 422 cur_ad_c++; 423 } else if (cur_ad_c == 1) { 424 cur_ad = cur_ad | (val << 8); 425 mvcur(cur_ad); 426 cur_ad_c = 0; 427 } 428 break; 429 430 case G_DSPON: 431 // TODO Configure blinking of cursor(s) 432 break; 433 434 default: 435 break; 436 } 437 } 438 else { 439 switch (val) { 440 case G_MWRITE: 441 current_op = G_MWRITE; 442 break; 443 444 case G_CRSMRT: 445 cursdir = &forw; 446 current_op = G_CRSMRT; 447 break; 448 449 case G_CRSMUP: 450 cursdir = &up; 451 current_op = G_CRSMUP; 452 break; 453 454 case G_CRSMDN: 455 cursdir = &down; 456 current_op = G_CRSMDN; 457 break; 458 459 case G_CRSWR: 460 current_op = G_CRSWR; 461 break; 462 463 case G_MREAD: 464 current_op = G_MREAD; 465 break; 466 467 case G_DSPOFF: 468 if (SDL_SetRenderDrawColor(ren, 0x00, 0x00, 0x00, 0xff) < 0) { 469 fail("SDL_SetRenderDrawColor() failed: %s", SDL_GetError()); 470 } 471 if (SDL_RenderClear(ren) < 0) { 472 fail("SDL_RenderClear() failed: %s", SDL_GetError()); 473 } 474 SDL_RenderPresent(ren); 475 render = 0; 476 current_op = G_DSPOFF; 477 break; 478 479 case G_DSPON: 480 render = 1; 481 current_op = G_DSPON; 482 break; 483 484 case G_CRSFRM: 485 // TODO Setup Cursor Form... 486 current_op = 0x00; 487 break; 488 489 default: 490 current_op = 0x00; 491 break; 492 } 493 } 494 } -
emu/sdl.c
r4f967e8 r5475ecf 27 27 28 28 static sdl_func_t sdl_funcs[] = { 29 ser_sdl, vid_sdl29 lcd_sdl, ser_sdl, vid_sdl 30 30 }; 31 31
Note:
See TracChangeset
for help on using the changeset viewer.