- Timestamp:
- 09/09/2017 12:30:42 PM (7 years ago)
- Branches:
- master
- Children:
- cd50b8c
- Parents:
- a86b3ab
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
emu/lcd.c
ra86b3ab r18e37d6 22 22 #define ver3(...) _ver(lcd_verbose, 2, __VA_ARGS__) 23 23 24 int32_t lcd_verbose = 0; 25 24 26 #define WIN_W (510 * 2) 25 27 #define WIN_H (64 * 2) … … 29 31 #define CON_FGR ((SDL_Color){ .r = 255, .b = 255, .g = 255, .a = 255 }) 30 32 33 #define REG_ARG 0 34 #define REG_COM 1 35 36 #define G_NONE 0x00 31 37 #define G_INIT 0x40 32 38 #define G_MWRITE 0x42 … … 57 63 #define BASE_GFX 0x2000 58 64 65 #define DIR_UP -85 66 #define DIR_DOWN 85 67 #define DIR_RIGHT 1 68 59 69 static uint8_t mem_txt[TXT_H * TXT_W]; 60 70 static uint8_t mem_gfx[GFX_H * GFX_W]; … … 63 73 static SDL_Renderer *ren; 64 74 static SDL_atomic_t frame; 65 static SDL_atomic_t clear; 66 67 static uint32_t render = 0; 75 static SDL_atomic_t ena; 68 76 69 77 static TTF_Font *fon; … … 74 82 static SDL_Surface *gfx_sur; 75 83 76 static int32_t cur = 0; 77 static int32_t cur_c = 0; 78 static int32_t dir = 1; 79 80 static int32_t current_op = 0x00; 81 82 static uint32_t last_val = 0x00; 83 static uint32_t last_off = 0; 84 static int32_t last_sz = -1; 85 static int32_t mult_val_c = 0; 86 87 int32_t lcd_verbose = 0; 84 static int32_t com; 85 static int32_t n_arg; 86 static int32_t cur = BASE_TXT; 87 static int32_t dir = DIR_RIGHT; 88 88 89 89 void lcd_sdl(void) 90 90 { 91 91 ver3("lcd_sdl()"); 92 93 if (SDL_AtomicGet(&clear)) {94 if (SDL_SetRenderDrawColor(ren, 0x00, 0x00, 0x00, 0xff) < 0) {95 fail("SDL_SetRenderDrawColor() failed: %s", SDL_GetError());96 }97 98 if (SDL_RenderClear(ren) < 0) {99 fail("SDL_RenderClear() failed: %s", SDL_GetError());100 }101 102 SDL_RenderPresent(ren);103 SDL_AtomicSet(&clear, 0);104 return;105 }106 92 107 93 static int32_t last = 0; … … 119 105 } 120 106 107 if (SDL_AtomicGet(&ena) == 0) { 108 return; 109 } 110 121 111 for (int32_t y = 0; y < TXT_H; ++y) { 122 112 char line[TXT_W + 1]; … … 126 116 } 127 117 128 memcpy(line, mem_txt + y * TXT_W, TXT_W); 118 for (int32_t x = 0; x < TXT_W; ++x) { 119 uint8_t c = mem_txt[y * TXT_W + x]; 120 line[x] = (char)(c == 0x00 ? ' ' : c); 121 } 122 129 123 line[TXT_W] = 0; 130 124 … … 215 209 } 216 210 217 SDL_AtomicSet(&clear, 0);218 219 211 SDL_AtomicSet(&frame, 1); 212 SDL_AtomicSet(&ena, 0); 220 213 221 214 SDL_RWops *ops = SDL_RWFromFile(font, "rb"); … … 279 272 ver2("lcd rd %u:%d", off, sz * 8); 280 273 281 uint32_t rv; 282 283 switch (current_op) { 284 case G_MREAD: 285 if (cur >= BASE_TXT && cur < BASE_TXT + TXT_W * TXT_H) { 286 rv = mem_txt[cur - BASE_TXT]; 274 if (sz != 1 || off > 0) { 275 fail("invalid lcd rd %u:%d", off, sz * 8); 276 } 277 278 switch (com) { 279 case G_MREAD: 280 if (cur >= BASE_TXT && cur < BASE_TXT + TXT_W * TXT_H) { 281 return mem_txt[cur - BASE_TXT]; 282 } 283 284 if (cur >= BASE_GFX && cur < BASE_GFX + GFX_W * GFX_H) { 285 return mem_gfx[cur - BASE_GFX]; 286 } 287 288 return 0x00; 289 290 default: 291 return 0x00; 292 } 293 } 294 295 static void proc_arg(int32_t val) 296 { 297 switch (com) { 298 case G_MWRITE: 299 if (cur >= BASE_TXT && cur < BASE_TXT + TXT_W * TXT_H) { 300 mem_txt[cur - BASE_TXT] = (uint8_t)val; 301 } 302 else if (cur >= BASE_GFX && cur < BASE_GFX + GFX_W * GFX_H) { 303 mem_gfx[cur - BASE_GFX] = (uint8_t)val; 304 } 305 306 cur += dir; 307 SDL_AtomicAdd(&frame, 1); 308 break; 309 310 case G_CRSWR: 311 if (n_arg == 0) { 312 cur = val; 313 } 314 else if (n_arg == 1) { 315 cur |= val << 8; 316 317 if (cur < BASE_TXT || 318 (cur >= BASE_TXT + TXT_W * TXT_H && cur < BASE_GFX) || 319 cur >= BASE_GFX + GFX_W * GFX_H) { 320 fail("invalid address 0x%04x", cur); 287 321 } 288 else if (cur >= BASE_GFX && cur < BASE_GFX + GFX_W * GFX_H) { 289 rv = mem_gfx[cur - BASE_GFX]; 290 } 291 else { 292 rv = 0x00; 293 } 294 break; 295 296 default: 297 rv = 0x00; 298 break; 299 } 300 return rv; 322 } 323 324 break; 325 326 default: 327 break; 328 } 329 } 330 331 static void proc_com(int32_t val) 332 { 333 switch (val) { 334 case G_CRSWR: 335 case G_MREAD: 336 case G_MWRITE: 337 com = val; 338 break; 339 340 case G_CRSMRT: 341 dir = DIR_RIGHT; 342 com = G_NONE; 343 break; 344 345 case G_CRSMUP: 346 dir = DIR_UP; 347 com = G_NONE; 348 break; 349 350 case G_CRSMDN: 351 dir = DIR_DOWN; 352 com = G_NONE; 353 break; 354 355 case G_DSPOFF: 356 SDL_AtomicSet(&ena, 0); 357 com = G_NONE; 358 break; 359 360 case G_DSPON: 361 SDL_AtomicSet(&ena, 1); 362 com = G_NONE; 363 break; 364 365 default: 366 com = G_NONE; 367 break; 368 } 301 369 } 302 370 303 371 void lcd_write(uint32_t off, int32_t sz, uint32_t val) 304 372 { 305 if (last_val != val && mult_val_c > 0) { 306 if (mult_val_c > 1) { 307 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); 308 } 309 else { 310 ver2("lcd wr %u:%d 0x%0*x", last_off, last_sz * 8, last_sz * 2, last_val); 311 } 312 313 ver2("lcd wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val); 314 mult_val_c = 0; 315 } 316 else if (last_val == val && mult_val_c >= 0) { 317 ++mult_val_c; 318 } 319 else { 320 ver2("lcd wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val); 321 } 322 323 last_val = val; 324 last_off = off; 325 last_sz = sz; 326 327 if (off == 0) { 328 switch (current_op) { 329 case G_MWRITE: 330 if (cur >= BASE_TXT && cur < BASE_TXT + TXT_W * TXT_H) { 331 if (val == 0) { 332 mem_txt[cur - BASE_TXT] = ' '; 333 } 334 else { 335 mem_txt[cur - BASE_TXT] = (uint8_t) val; 336 } 337 338 cur += dir; 339 340 if (render) { 341 SDL_AtomicAdd(&frame, 1); 342 } 343 } 344 else if (cur >= BASE_GFX && cur < BASE_GFX + GFX_W * GFX_H) { 345 mem_gfx[cur - BASE_GFX] = (uint8_t) val; 346 cur += dir; 347 348 if (render) { 349 SDL_AtomicAdd(&frame, 1); 350 } 351 } 352 break; 353 354 case G_CRSWR: 355 if (cur_c == 0) { 356 cur = (int32_t) val; 357 cur_c++; 358 } 359 else if (cur_c == 1) { 360 cur = cur | ((int32_t) val << 8); 361 if (cur < BASE_TXT || (cur >= BASE_TXT + TXT_W * TXT_H && cur < BASE_GFX) || cur >= BASE_GFX + GFX_W * GFX_H) { 362 err("Invalid cur value %d", cur); 363 } 364 cur_c = 0; 365 } 366 break; 367 368 default: 369 break; 370 } 371 } 372 else { 373 switch (val) { 374 case G_MWRITE: 375 current_op = G_MWRITE; 376 break; 377 378 case G_CRSMRT: 379 dir = 1; 380 current_op = G_CRSMRT; 381 break; 382 383 case G_CRSMUP: 384 dir = -85; 385 current_op = G_CRSMUP; 386 break; 387 388 case G_CRSMDN: 389 dir = 85; 390 current_op = G_CRSMDN; 391 break; 392 393 case G_CRSWR: 394 current_op = G_CRSWR; 395 break; 396 397 case G_MREAD: 398 current_op = G_MREAD; 399 break; 400 401 case G_DSPOFF: 402 SDL_AtomicSet(&clear, 1); 403 render = 0; 404 current_op = G_DSPOFF; 405 break; 406 407 case G_DSPON: 408 render = 1; 409 current_op = G_DSPON; 410 break; 411 412 default: 413 current_op = 0x00; 414 break; 415 } 416 } 417 } 373 ver2("lcd wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val); 374 375 if (sz != 1 || off > 1) { 376 fail("invalid lcd wr %u:%d", off, sz * 8); 377 } 378 379 switch (off) { 380 case REG_ARG: 381 proc_arg((int32_t)val); 382 ++n_arg; 383 break; 384 385 case REG_COM: 386 proc_com((int32_t)val); 387 n_arg = 0; 388 break; 389 390 default: 391 break; 392 } 393 }
Note:
See TracChangeset
for help on using the changeset viewer.