Changes in / [f51359c:ca77925] in buchla-emu
- Location:
- emu
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
emu/all.h
rf51359c rca77925 114 114 extern void lcd_write(uint32_t off, int32_t sz, uint32_t val); 115 115 116 extern void lcd_sdl(void);117 118 116 extern void ser_init(void); 119 117 extern void ser_quit(void); -
emu/lcd.c
rf51359c rca77925 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 8628 #define CON_H 929 30 #define CON_BGR 0x0000000031 #define CON_BEL 0x0080808032 #define CON_CUR 0x00e8700033 #define CON_FGR ((SDL_Color){ .r = 255, .b = 255, .g = 255, .a = 255 })34 35 #define BEL_CYC 1000036 37 #define G_INIT 0x4038 #define G_MWRITE 0x4239 #define G_MREAD 0x4340 #define G_SETSAD 0x4441 #define G_CRSWR 0x4642 #define G_CRSRD 0x4743 #define G_CRSMRT 0x4C44 #define G_CRSMLT 0x4D45 #define G_CRSMUP 0x4E46 #define G_CRSMDN 0x4F47 #define G_ERASE 0x5248 #define G_SLEEP 0x5349 #define G_DSPOFF 0x5850 #define G_DSPON 0x5951 #define G_HSCRL 0x5A52 #define G_OVRLAY 0x5B53 #define G_CGRAM 0x5C54 #define G_CRSFRM 0x5D55 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 84 24 int32_t lcd_verbose = 0; 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 bounds132 }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 bounds142 }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 // TODO198 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_h252 }, 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_h280 })) {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 25 302 26 void lcd_init(void) 303 27 { 304 28 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 350 29 } 351 30 … … 353 32 { 354 33 ver("lcd quit"); 355 356 SDL_FreeSurface(sur);357 TTF_CloseFont(fon);358 359 SDL_DestroyRenderer(ren);360 SDL_DestroyWindow(win);361 34 } 362 35 … … 370 43 { 371 44 ver2("lcd rd %u:%d", off, sz * 8); 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; 45 return 0; 386 46 } 387 47 388 48 void lcd_write(uint32_t off, int32_t sz, uint32_t val) 389 49 { 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 } 50 ver2("lcd wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val); 494 51 } -
emu/sdl.c
rf51359c rca77925 27 27 28 28 static sdl_func_t sdl_funcs[] = { 29 lcd_sdl,ser_sdl, vid_sdl29 ser_sdl, vid_sdl 30 30 }; 31 31
Note:
See TracChangeset
for help on using the changeset viewer.