Changeset 67fecc3 in buchla-emu


Ignore:
Timestamp:
09/09/2017 11:11:32 PM (7 years ago)
Author:
Thomas Lopatic <thomas@…>
Branches:
master
Children:
0d83ce8
Parents:
e26a632 (diff), 18cbd53 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
git-author:
Thomas Lopatic <thomas@…> (09/09/2017 11:11:27 PM)
git-committer:
Thomas Lopatic <thomas@…> (09/09/2017 11:11:32 PM)
Message:

Merge LCD emulation.

Location:
emu
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • emu/all.h

    re26a632 r67fecc3  
    6969extern uint32_t vid_win;
    7070extern uint32_t ser_win;
     71extern uint32_t lcd_win;
    7172
    7273extern void sdl_init(void);
     
    113114extern uint32_t lcd_read(uint32_t off, int32_t sz);
    114115extern void lcd_write(uint32_t off, int32_t sz, uint32_t val);
     116
     117extern void lcd_sdl(void);
    115118
    116119extern void ser_init(void);
     
    162165extern void kbd_write(uint32_t off, int32_t sz, uint32_t val);
    163166
    164 extern void kbd_key(SDL_KeyboardEvent *ev, bool dn);
     167extern void kbd_key(SDL_KeyboardEvent *ev, bool vid, bool dn);
  • emu/kbd.c

    re26a632 r67fecc3  
    104104}
    105105
     106static void slid(int32_t sig, bool on, int32_t val)
     107{
     108        out((uint8_t)(0x80 | sig));
     109        out(on ? 0x01 : 0x00);
     110        out((uint8_t)val);
     111}
     112
    106113#if defined NOT_YET
    107 static void pot_128(int32_t sig, int32_t val)
     114static void pot(int32_t sig, int32_t val)
    108115{
    109116        out((uint8_t)(0x80 | sig));
    110117        out((uint8_t)val);
    111118}
    112 
    113 static void pot_256(int32_t sig, int32_t val)
    114 {
    115         out((uint8_t)(0x80 | sig));
    116         out((uint8_t)((val >> 7) & 0x01));
    117         out((uint8_t)(val & 0x7f));
    118 }
    119119#endif
    120120
    121 void kbd_key(SDL_KeyboardEvent *ev, bool dn)
     121static void vid_key(SDL_KeyboardEvent *ev, bool dn)
    122122{
    123123        if ((ev->keysym.mod & KMOD_SHIFT) != 0 &&
     
    173173}
    174174
     175static void lcd_key(SDL_KeyboardEvent *ev, bool dn)
     176{
     177        if ((ev->keysym.mod & KMOD_CTRL) != 0 &&
     178                        ev->keysym.sym >= SDLK_a && ev->keysym.sym <= SDLK_n) {
     179                int32_t i = ev->keysym.sym - SDLK_a;
     180                ver2("kbd lcd %d %s", i, dn ? "dn" : "up");
     181
     182                if (dn) {
     183                        but_on(39 + i);
     184                }
     185                else {
     186                        but_off(39 + i);
     187                }
     188
     189                return;
     190        }
     191
     192        if (ev->keysym.sym >= SDLK_a && ev->keysym.sym <= SDLK_n) {
     193                static int32_t lev[14] = {
     194                        64, 0, 0, 0, 0, 64, 64, 64, 64, 0, 0, 0, 64, 0
     195                };
     196
     197                int32_t i = ev->keysym.sym - SDLK_a;
     198                int32_t val = lev[i];
     199
     200                if (!dn) {
     201                        if ((ev->keysym.mod & KMOD_SHIFT) != 0) {
     202                                val = val > 10 ? val - 10 : 0;
     203                        }
     204                        else {
     205                                val = val < 117 ? val + 10 : 127;
     206                        }
     207                }
     208
     209                ver2("kbd sli %d %s %d", i, dn ? "dn" : "up", val);
     210                slid(25 + i, dn, val);
     211
     212                lev[i] = val;
     213                return;
     214        }
     215}
     216
     217void kbd_key(SDL_KeyboardEvent *ev, bool vid, bool dn)
     218{
     219        if (vid) {
     220                vid_key(ev, dn);
     221        }
     222        else {
     223                lcd_key(ev, dn);
     224        }
     225}
     226
    175227void kbd_init(void)
    176228{
  • emu/lcd.c

    re26a632 r67fecc3  
    2424int32_t lcd_verbose = 0;
    2525
     26#define WIN_W (1615 * 2 / 3)
     27#define WIN_H (304 * 2 / 3)
     28
     29#define GFX_BGR 0x00000000
     30#define GFX_FGR 0xFFFFFFFF
     31
     32#define TXT_BGR 0x000000FF
     33#define TXT_FGR ((SDL_Color){ .r = 255, .b = 255, .g = 255, .a = 255 })
     34
     35#define REG_ARG 0
     36#define REG_COM 1
     37
     38#define COM_NONE        0x00
     39#define COM_MWRITE      0x42
     40#define COM_MREAD       0x43
     41#define COM_CRSWR       0x46
     42#define COM_CRSMRT      0x4C
     43#define COM_CRSMUP      0x4E
     44#define COM_CRSMDN      0x4F
     45#define COM_DSPOFF      0x58
     46#define COM_DSPON       0x59
     47
     48#define TXT_W 85
     49#define TXT_H 8
     50
     51#define GFX_W 85
     52#define GFX_H 64
     53#define GFX_PIX 6
     54
     55#define BASE_TXT 0x0000
     56#define BASE_GFX 0x2000
     57
     58#define DIR_UP -85
     59#define DIR_DOWN 85
     60#define DIR_RIGHT 1
     61
     62static uint8_t mem_txt[TXT_H * TXT_W];
     63static uint8_t mem_gfx[GFX_H * GFX_W];
     64
     65static SDL_Window *win;
     66uint32_t lcd_win;
     67
     68static SDL_Renderer *ren;
     69static SDL_atomic_t frame;
     70static SDL_atomic_t ena;
     71
     72static TTF_Font *fon;
     73static int32_t fon_w, fon_h;
     74
     75static int32_t txt_w, txt_h;
     76static SDL_Surface *txt;
     77static SDL_Texture *gfx;
     78
     79static int32_t com;
     80static int32_t n_arg;
     81static int32_t cur = BASE_TXT;
     82static int32_t dir = DIR_RIGHT;
     83
     84void lcd_sdl(void)
     85{
     86        ver3("lcd_sdl()");
     87
     88        static int32_t last = 0;
     89        int32_t now = SDL_AtomicGet(&frame);
     90
     91        if (last == now) {
     92                ver3("no update");
     93                return;
     94        }
     95
     96        last = now;
     97
     98        if (SDL_FillRect(txt, NULL, TXT_BGR) < 0) {
     99                fail("SDL_FillRect() failed: %s", SDL_GetError());
     100        }
     101
     102        if (SDL_AtomicGet(&ena) == 0) {
     103                SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, txt);
     104
     105                if (tex == NULL) {
     106                        fail("SDL_CreateTextureFromSurface() failed: %s", SDL_GetError());
     107                }
     108
     109                if (SDL_RenderCopy(ren, tex, NULL, NULL) < 0) {
     110                        fail("SDL_RenderCopy() failed: %s", SDL_GetError());
     111                }
     112
     113                SDL_DestroyTexture(tex);
     114                SDL_RenderPresent(ren);
     115                return;
     116        }
     117
     118        for (int32_t y = 0; y < TXT_H; ++y) {
     119                char line[TXT_W + 1];
     120                line[TXT_W] = 0;
     121
     122                if (SDL_LockMutex(cpu_mutex) < 0) {
     123                        fail("SDL_LockMutex() failed: %s", SDL_GetError());
     124                }
     125
     126                memcpy(line, mem_txt + y * TXT_W, TXT_W);
     127
     128                if (SDL_UnlockMutex(cpu_mutex) < 0) {
     129                        fail("SDL_UnlockMutex() failed: %s", SDL_GetError());
     130                }
     131
     132                for (int32_t x = 0; x < TXT_W; ++x) {
     133                        if (line[x] == 0x00) {
     134                                line[x] = ' ';
     135                        }
     136                }
     137
     138                SDL_Surface *lin = TTF_RenderText_Blended(fon, line, TXT_FGR);
     139
     140                if (lin == NULL) {
     141                        fail("TTF_RenderText_Blended() failed: %s", TTF_GetError());
     142                }
     143
     144                if (SDL_BlitSurface(lin, NULL, txt, &(SDL_Rect){
     145                        .x = 0,
     146                        .y = y * fon_h,
     147                        .w = TXT_W * fon_w,
     148                        .h = fon_h
     149                })) {
     150                        fail("SDL_BlitSurface() failed: %s", SDL_GetError());
     151                }
     152
     153                SDL_FreeSurface(lin);
     154        }
     155
     156        SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, txt);
     157
     158        if (tex == NULL) {
     159                fail("SDL_CreateTextureFromSurface() failed: %s", SDL_GetError());
     160        }
     161
     162        if (SDL_RenderCopy(ren, tex, NULL, NULL) < 0) {
     163                fail("SDL_RenderCopy() failed: %s", SDL_GetError());
     164        }
     165
     166        SDL_DestroyTexture(tex);
     167
     168        void *buf;
     169        int32_t pitch;
     170
     171        if (SDL_LockTexture(gfx, NULL, &buf, &pitch) < 0) {
     172                fail("SDL_LockTexture() failed: %s", SDL_GetError());
     173        }
     174
     175        uint32_t *pix = buf;
     176
     177        for (int32_t y = 0; y < GFX_H; ++y) {
     178                for (int32_t x = 0; x < GFX_W; ++x) {
     179                        uint8_t b = mem_gfx[y * GFX_W + x];
     180
     181                        for (int32_t p = 0; p < GFX_PIX; ++p) {
     182                                bool set = (b & (1 << (7 - p))) != 0;
     183                                *pix++ = set ? GFX_FGR : GFX_BGR;
     184                        }
     185                }
     186
     187                pix += pitch / 4 - GFX_W * GFX_PIX;
     188        }
     189
     190        SDL_UnlockTexture(gfx);
     191
     192        if (SDL_RenderCopy(ren, gfx, NULL, NULL) < 0) {
     193                fail("SDL_RenderCopy() failed: %s", SDL_GetError());
     194        }
     195
     196        SDL_RenderPresent(ren);
     197}
     198
    26199void lcd_init(void)
    27200{
    28201        ver("lcd init");
     202
     203        win = SDL_CreateWindow("LCD", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
     204                        WIN_W, WIN_H, 0);
     205
     206        if (win == NULL) {
     207                fail("SDL_CreateWindow() failed: %s", SDL_GetError());
     208        }
     209
     210        lcd_win = SDL_GetWindowID(win);
     211
     212        if (lcd_win == 0) {
     213                fail("SDL_GetWindowID() failed: %s", SDL_GetError());
     214        }
     215
     216        ren = SDL_CreateRenderer(win, -1, 0);
     217
     218        if (ren == NULL) {
     219                fail("SDL_CreateRenderer() failed: %s", SDL_GetError());
     220        }
     221
     222        gfx = SDL_CreateTexture(ren, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING,
     223                        GFX_W * GFX_PIX, GFX_H);
     224
     225        if (gfx == NULL) {
     226                fail("SDL_CreateTexture() failed: %s", SDL_GetError());
     227        }
     228
     229        if (SDL_SetTextureBlendMode(gfx, SDL_BLENDMODE_BLEND) < 0) {
     230                fail("SDL_SetTextureBlendMode() failed: %s", SDL_GetError());
     231        }
     232
     233        SDL_RWops *ops = SDL_RWFromFile(font, "rb");
     234
     235        if (ops == NULL) {
     236                fail("error while opening font file %s: %s", font, SDL_GetError());
     237        }
     238
     239        fon = TTF_OpenFontRW(ops, 1, 32);
     240
     241        if (fon == NULL) {
     242                fail("error while loading font file %s: %s", font, TTF_GetError());
     243        }
     244
     245        fon_h = TTF_FontLineSkip(fon);
     246
     247        if (TTF_GlyphMetrics(fon, 'X', NULL, NULL, NULL, NULL, &fon_w) < 0) {
     248                fail("error while measuring font width: %s", TTF_GetError());
     249        }
     250
     251        txt_w = TXT_W * fon_w;
     252        txt_h = TXT_H * fon_h;
     253
     254        txt = SDL_CreateRGBSurfaceWithFormat(0, txt_w, txt_h, 32, SDL_PIXELFORMAT_RGBA8888);
     255
     256        if (txt == NULL) {
     257                fail("SDL_CreateRGBSurface() failed: %s", SDL_GetError());
     258        }
     259
     260        for (int32_t i = 0; i < TXT_W * TXT_H; ++i) {
     261                mem_txt[i] = ' ';
     262        }
    29263}
    30264
     
    32266{
    33267        ver("lcd quit");
     268
     269        SDL_FreeSurface(txt);
     270        TTF_CloseFont(fon);
     271
     272        SDL_DestroyTexture(gfx);
     273
     274        SDL_DestroyRenderer(ren);
     275        SDL_DestroyWindow(win);
    34276}
    35277
     
    43285{
    44286        ver2("lcd rd %u:%d", off, sz * 8);
    45         return 0;
     287
     288        if (sz != 1 || off != 1) {
     289                fail("invalid lcd rd %u:%d", off, sz * 8);
     290        }
     291
     292        switch (com) {
     293        case COM_MREAD:
     294                if (cur >= BASE_TXT && cur < BASE_TXT + TXT_W * TXT_H) {
     295                        return mem_txt[cur - BASE_TXT];
     296                }
     297
     298                if (cur >= BASE_GFX && cur < BASE_GFX + GFX_W * GFX_H) {
     299                        return mem_gfx[cur - BASE_GFX];
     300                }
     301
     302                return 0x00;
     303
     304        default:
     305                return 0x00;
     306        }
     307}
     308
     309static void proc_arg(int32_t val)
     310{
     311        switch (com) {
     312        case COM_MWRITE:
     313                if (cur >= BASE_TXT && cur < BASE_TXT + TXT_W * TXT_H) {
     314                        mem_txt[cur - BASE_TXT] = (uint8_t)val;
     315                }
     316                else if (cur >= BASE_GFX && cur < BASE_GFX + GFX_W * GFX_H) {
     317                        mem_gfx[cur - BASE_GFX] = (uint8_t)val;
     318                }
     319
     320                cur += dir;
     321                SDL_AtomicAdd(&frame, 1);
     322                break;
     323
     324        case COM_CRSWR:
     325                if (n_arg == 0) {
     326                        cur = val;
     327                }
     328                else if (n_arg == 1) {
     329                        cur |= val << 8;
     330
     331                        if (cur < BASE_TXT ||
     332                                        (cur >= BASE_TXT + TXT_W * TXT_H && cur < BASE_GFX) ||
     333                                        cur >= BASE_GFX + GFX_W * GFX_H) {
     334                                fail("invalid address 0x%04x", cur);
     335                        }
     336                }
     337
     338                break;
     339
     340        default:
     341                break;
     342        }
     343}
     344
     345static void proc_com(int32_t val)
     346{
     347        switch (val) {
     348        case COM_CRSWR:
     349        case COM_MREAD:
     350        case COM_MWRITE:
     351                com = val;
     352                break;
     353
     354        case COM_CRSMRT:
     355                dir = DIR_RIGHT;
     356                com = COM_NONE;
     357                break;
     358
     359        case COM_CRSMUP:
     360                dir = DIR_UP;
     361                com = COM_NONE;
     362                break;
     363
     364        case COM_CRSMDN:
     365                dir = DIR_DOWN;
     366                com = COM_NONE;
     367                break;
     368
     369        case COM_DSPOFF:
     370                SDL_AtomicSet(&ena, 0);
     371                com = COM_NONE;
     372                break;
     373
     374        case COM_DSPON:
     375                SDL_AtomicSet(&ena, 1);
     376                com = COM_NONE;
     377                break;
     378
     379        default:
     380                com = COM_NONE;
     381                break;
     382        }
    46383}
    47384
     
    49386{
    50387        ver2("lcd wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val);
    51 }
     388
     389        if (sz != 1 || off > 1) {
     390                fail("invalid lcd wr %u:%d", off, sz * 8);
     391        }
     392
     393        switch (off) {
     394        case REG_ARG:
     395                proc_arg((int32_t)val);
     396                ++n_arg;
     397                break;
     398
     399        case REG_COM:
     400                proc_com((int32_t)val);
     401                n_arg = 0;
     402                break;
     403
     404        default:
     405                break;
     406        }
     407}
  • emu/sdl.c

    re26a632 r67fecc3  
    2727
    2828static sdl_func_t sdl_funcs[] = {
    29         ser_sdl, vid_sdl
     29        lcd_sdl, ser_sdl, vid_sdl
    3030};
    3131
     
    161161                                }
    162162                                else if (win == vid_win) {
    163                                         kbd_key(&ev.key, true);
     163                                        kbd_key(&ev.key, true, true);
     164                                }
     165                                else if (win == lcd_win) {
     166                                        kbd_key(&ev.key, false, true);
    164167                                }
    165168
     
    171174
    172175                                if (win == vid_win) {
    173                                         kbd_key(&ev.key, false);
     176                                        kbd_key(&ev.key, true, false);
     177                                }
     178                                else if (win == lcd_win) {
     179                                        kbd_key(&ev.key, false, false);
    174180                                }
    175181
  • emu/vid.c

    re26a632 r67fecc3  
    244244        ver("vid init");
    245245
    246         win = SDL_CreateWindow("Display", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
     246        win = SDL_CreateWindow("Screen", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
    247247                        WIN_W, WIN_H, 0);
    248248
Note: See TracChangeset for help on using the changeset viewer.