Changeset c8a92ef in buchla-emu


Ignore:
Timestamp:
09/07/2017 11:42:45 AM (2 years ago)
Author:
Alexander Heinrich <alex.heinrich@…>
Branches:
master
Children:
c9d372a
Parents:
f51359c
Message:

Add graphic output to lcd window

File:
1 edited

Legend:

Unmodified
Added
Removed
  • emu/lcd.c

    rf51359c rc8a92ef  
    2222#define ver3(...) _ver(lcd_verbose, 2, __VA_ARGS__)
    2323
    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
     24#define WIN_W (510 * 2)
     25#define WIN_H (64 * 2)
    2926
    3027#define CON_BGR 0x00000000
    31 #define CON_BEL 0x00808080
    32 #define CON_CUR 0x00e87000
     28#define CON_DRW 0xFFFFFFFF
    3329#define CON_FGR ((SDL_Color){ .r = 255, .b = 255, .g = 255, .a = 255 })
    34 
    35 #define BEL_CYC 10000
    3630
    3731#define G_INIT          0x40
     
    5448#define G_CRSFRM        0x5D
    5549
    56 static uint8_t mem[CON_H][CON_W + 1];
     50#define TXT_W 85
     51#define TXT_H 8
     52
     53#define GFX_W 85
     54#define GFX_H 64
     55
     56#define BASE_TXT 0x0000
     57#define BASE_GFX 0x2000
     58
     59static uint8_t mem_txt[TXT_H * TXT_W];
     60static uint8_t mem_gfx[GFX_H * GFX_W];
    5761
    5862static SDL_Window *win;
    5963static SDL_Renderer *ren;
    6064static SDL_atomic_t frame;
     65static SDL_atomic_t clear;
    6166
    6267static uint32_t render = 0;
     
    6873static SDL_Surface *sur;
    6974
    70 static int32_t cur_x = 0, cur_y = 0;
    71 static int32_t bel = 0;
     75static SDL_Surface *gfx_sur;
     76
     77static int32_t cur = 0;
     78static int32_t cur_c = 0;
     79static int32_t dir = 1;
    7280
    7381static int32_t current_op = 0x00;
    74 static uint32_t cur_ad = 0;
    75 static int32_t cur_ad_c = 0;
    7682
    7783static uint32_t last_val = 0x00;
     
    8086static int32_t mult_val_c = 0;
    8187
    82 static void (*cursdir)(void);
    83 
    8488int32_t lcd_verbose = 0;
    8589
    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;
     90
     91void lcd_sdl(void)
     92{
     93        ver3("lcd_sdl()");
     94
     95        if (SDL_AtomicGet(&clear)) {
     96                if (SDL_SetRenderDrawColor(ren, 0x00, 0x00, 0x00, 0xff) < 0) {
     97                        fail("SDL_SetRenderDrawColor() failed: %s", SDL_GetError());
     98                }
     99
     100                if (SDL_RenderClear(ren) < 0) {
     101                        fail("SDL_RenderClear() failed: %s", SDL_GetError());
     102                }
     103
     104                SDL_RenderPresent(ren);
     105                SDL_AtomicSet(&clear, 0);
    96106                return;
    97107        }
    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()");
    232108
    233109        static int32_t last = 0;
     
    241117        last = now;
    242118
    243         if (SDL_FillRect(sur, NULL, bel == 0 ? CON_BGR : CON_BEL) < 0) {
     119        if (SDL_FillRect(sur, NULL, CON_BGR) < 0) {
    244120                fail("SDL_FillRect() failed: %s", SDL_GetError());
    245121        }
    246122
    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];
     123        for (int32_t y = 0; y < TXT_H; ++y) {
     124                char line[TXT_W + 1];
    258125
    259126                if (SDL_LockMutex(cpu_mutex) < 0) {
     
    261128                }
    262129
    263                 memcpy(line, mem[y], CON_W + 1);
     130                memcpy(line, mem_txt + y * TXT_W, TXT_W);
     131                line[TXT_W] = 0;
    264132
    265133                if (SDL_UnlockMutex(cpu_mutex) < 0) {
     
    276144                        .x = 0,
    277145                        .y = y * fon_h,
    278                         .w = CON_W * fon_w,
     146                        .w = TXT_W * fon_w,
    279147                        .h = fon_h
    280148                })) {
     
    295163        }
    296164
     165        for (int32_t y = 0; y < GFX_H * GFX_W; ++y) {
     166                for (int32_t p = 7; p > 1; --p) {
     167                        uint32_t col = CON_BGR;
     168                        if ((mem_gfx[y] & (1 << p)) > 0) {
     169                                col = CON_DRW;
     170                        }
     171
     172                        if (SDL_FillRect(gfx_sur, &(SDL_Rect){
     173                                .x = y % 85 * fon_w + (8 - p) * fon_w / 6,
     174                                .y = y / 85 * fon_h / 8,
     175                                .w = fon_w / 6 + 1,
     176                                .h = fon_h / 8 + 1
     177                        }, col) < 0) {
     178                                fail("SDL_FillRect() failed: %s", SDL_GetError());
     179                        }
     180                }
     181        }
     182
     183        SDL_Texture *gfx_tex = SDL_CreateTextureFromSurface(ren, gfx_sur);
     184
     185        if (gfx_tex == NULL) {
     186                fail("SDL_CreateTextureFromSurface() failed: %s", SDL_GetError());
     187        }
     188
     189        if (SDL_SetTextureBlendMode(gfx_tex, SDL_BLENDMODE_ADD) < 0) {
     190                fail("SDL_SetTextureBlendMode() failed: %s", SDL_GetError());
     191        }
     192
     193        if (SDL_RenderCopy(ren, gfx_tex, NULL, NULL) < 0) {
     194                fail("SDL_RenderCopy() failed: %s", SDL_GetError());
     195        }
     196
    297197        SDL_DestroyTexture(tex);
     198        SDL_DestroyTexture(gfx_tex);
    298199        SDL_RenderPresent(ren);
    299200}
     
    317218        }
    318219
     220        SDL_AtomicSet(&clear, 0);
     221
    319222        SDL_AtomicSet(&frame, 1);
    320223
     
    337240        }
    338241
    339         sur_w = CON_W * fon_w;
    340         sur_h = CON_H * fon_h;
     242        sur_w = TXT_W * fon_w;
     243        sur_h = TXT_H * fon_h;
    341244
    342245        sur = SDL_CreateRGBSurface(0, sur_w, sur_h, 32, 0, 0, 0, 0);
     
    346249        }
    347250
    348         clear_mem();
    349 
     251        gfx_sur = SDL_CreateRGBSurface(0, sur_w, sur_h, 32, 0, 0, 0, 0);
     252
     253        if (gfx_sur == NULL) {
     254                fail("SDL_CreateRGBSurface() failed: %s", SDL_GetError());
     255        }
     256
     257        for (int32_t y = 0; y < TXT_W * TXT_H; ++y) {
     258                mem_txt[y] = ' ';
     259        }
    350260}
    351261
     
    355265
    356266        SDL_FreeSurface(sur);
     267        SDL_FreeSurface(gfx_sur);
    357268        TTF_CloseFont(fon);
    358269
     
    375286        switch (current_op) {
    376287                case G_MREAD:
    377                         ver2("lcd current op: %d\n", current_op);
    378                         rv = mem[cur_y][cur_x];
     288                        if (cur >= BASE_TXT && cur < BASE_TXT + TXT_W * TXT_H) {
     289                                rv = mem_txt[cur - BASE_TXT];
     290                        }
     291                        else if (cur >= BASE_GFX && cur < BASE_TXT + GFX_W * GFX_H) {
     292                                rv = mem_gfx[cur - BASE_GFX];
     293                        }
     294                        else {
     295                                rv = 0x00;
     296                        }
    379297                        break;
    380298
     
    388306void lcd_write(uint32_t off, int32_t sz, uint32_t val)
    389307{
    390 
    391         if(last_val != val && mult_val_c > 0) {
    392                 if(mult_val_c > 1) {
     308        if (last_val != val && mult_val_c > 0) {
     309                if (mult_val_c > 1) {
    393310                        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);
    394311                }
     
    400317                mult_val_c = 0;
    401318        }
    402         else if(last_val == val && mult_val_c >= 0) {
     319        else if (last_val == val && mult_val_c >= 0) {
    403320                ++mult_val_c;
    404321        }
     
    414331                switch (current_op) {
    415332                        case G_MWRITE:
    416                                         echo((uint8_t)val);
     333                                        if (cur >= BASE_TXT && cur < BASE_TXT + TXT_W * TXT_H) {
     334                                                if (val == 0) {
     335                                                        mem_txt[cur - BASE_TXT] = ' ';
     336                                                }
     337                                                else {
     338                                                        mem_txt[cur - BASE_TXT] = (uint8_t) val;
     339                                                }
     340
     341                                                cur += dir;
     342
     343                                                if (render) {
     344                                                        SDL_AtomicAdd(&frame, 1);
     345                                                }
     346                                        }
     347                                        else if (cur >= BASE_GFX && cur < BASE_GFX + GFX_W * GFX_H) {
     348                                                mem_gfx[cur - BASE_GFX] = (uint8_t) val;
     349                                                cur += dir;
     350
     351                                                if (render) {
     352                                                        SDL_AtomicAdd(&frame, 1);
     353                                                }
     354                                        }
     355                                        else {
     356                                                err("Invalid cur value %d", cur);
     357                                        }
    417358                                break;
    418359
    419360                        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;
     361                                if (cur_c == 0) {
     362                                        cur = (int32_t) val;
     363                                        cur_c++;
    427364                                }
    428                                 break;
    429 
    430                         case G_DSPON:
    431                                 // TODO Configure blinking of cursor(s)
     365                                else if (cur_c == 1) {
     366                                        cur = cur | ((int32_t) val << 8);
     367                                        cur_c = 0;
     368                                }
    432369                                break;
    433370
     
    443380
    444381                        case G_CRSMRT:
    445                                 cursdir = &forw;
     382                                dir = 1;
    446383                                current_op = G_CRSMRT;
    447384                                break;
    448385
    449386                        case G_CRSMUP:
    450                                 cursdir = &up;
     387                                dir = -85;
    451388                                current_op = G_CRSMUP;
    452389                                break;
    453390
    454391                        case G_CRSMDN:
    455                                 cursdir = &down;
     392                                dir = 85;
    456393                                current_op = G_CRSMDN;
    457394                                break;
     
    466403
    467404                        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);
     405                                SDL_AtomicSet(&clear, 1);
    475406                                render = 0;
    476407                                current_op = G_DSPOFF;
     
    482413                                break;
    483414
    484                         case G_CRSFRM:
    485                                 // TODO Setup Cursor Form...
    486                                 current_op = 0x00;
    487                                 break;
    488 
    489415                        default:
    490416                                current_op = 0x00;
Note: See TracChangeset for help on using the changeset viewer.