Changes in / [4f967e8:5475ecf] in buchla-emu


Ignore:
Location:
emu
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • emu/all.h

    r4f967e8 r5475ecf  
    111111extern void lcd_write(uint32_t off, int32_t sz, uint32_t val);
    112112
     113extern void lcd_sdl(void);
     114
    113115extern void ser_init(void);
    114116extern void ser_quit(void);
  • emu/lcd.c

    r4f967e8 r5475ecf  
    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
     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
     56static uint8_t mem[CON_H][CON_W + 1];
     57
     58static SDL_Window *win;
     59static SDL_Renderer *ren;
     60static SDL_atomic_t frame;
     61
     62static uint32_t render = 0;
     63
     64static TTF_Font *fon;
     65static int32_t fon_w, fon_h;
     66
     67static int32_t sur_w, sur_h;
     68static SDL_Surface *sur;
     69
     70static int32_t cur_x = 0, cur_y = 0;
     71static int32_t bel = 0;
     72
     73static int32_t current_op = 0x00;
     74static uint32_t cur_ad = 0;
     75static int32_t cur_ad_c = 0;
     76
     77static uint32_t last_val = 0x00;
     78static uint32_t last_off = 0;
     79static int32_t last_sz = -1;
     80static int32_t mult_val_c = 0;
     81
     82static void (*cursdir)(void);
     83
    2484int32_t lcd_verbose = 0;
    2585
     86static 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
     92static 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
     109static 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
     124static 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
     134static 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
     144static 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
     168static 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
     219static 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
     229void 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
    26302void lcd_init(void)
    27303{
    28304        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
    29350}
    30351
     
    32353{
    33354        ver("lcd quit");
     355
     356        SDL_FreeSurface(sur);
     357        TTF_CloseFont(fon);
     358
     359        SDL_DestroyRenderer(ren);
     360        SDL_DestroyWindow(win);
    34361}
    35362
     
    43370{
    44371        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;
    46386}
    47387
    48388void lcd_write(uint32_t off, int32_t sz, uint32_t val)
    49389{
    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  
    2727
    2828static sdl_func_t sdl_funcs[] = {
    29         ser_sdl, vid_sdl
     29        lcd_sdl, ser_sdl, vid_sdl
    3030};
    3131
Note: See TracChangeset for help on using the changeset viewer.