#include "pdp6.h" #include #include #include #include "args.h" #include "../art/panelart.inc" typedef struct Point Point; struct Point { float x, y; }; typedef struct Image Image; struct Image { SDL_Texture *tex; int w, h; }; typedef struct Panel Panel; struct Panel { Image *surf; SDL_Rect pos; }; typedef struct Grid Grid; struct Grid { float xoff, yoff; float xscl, yscl; Panel *panel; }; typedef struct Element Element; struct Element { Image **surf; Grid *grid; Point pos; int state; int active; }; typedef struct SwDigit SwDigit; struct SwDigit { Element *sw; // these 3 switch Element *first; // the first one SwDigit *prev; SwDigit *next; }; static SDL_Window *window; static SDL_Renderer *renderer; Lock initlock; volatile int awaitinit; Image* mustloadimg(const char *path) { Image *img; SDL_Texture *s; s = IMG_LoadTexture(renderer, path); if(s == nil) err("Couldn't load %s", path); img = malloc(sizeof(Image)); img->tex = s; SDL_QueryTexture(img->tex, nil, nil, &img->w, &img->h); return img; } Image* loadresimg(u8 *data, int sz) { SDL_RWops *f; Image *img; SDL_Texture *s; f = SDL_RWFromConstMem(data, sz); if(f == nil) err("Couldn't load resource"); s = IMG_LoadTexture_RW(renderer, f, 0); if(s == nil) err("Couldn't load image"); img = malloc(sizeof(Image)); img->tex = s; SDL_QueryTexture(img->tex, nil, nil, &img->w, &img->h); return img; } Image *lampsurf[2]; Image *switchsurf[2]; Image *keysurf[3]; Panel oppanel; Grid opgrid1; /* the smaller base grid */ Grid opgrid2; /* the key grid */ Panel iopanel; Grid iogrid; Panel indpanel1, indpanel2; Grid indgrid1; Grid indgrid2; Panel extrapanel; Grid extragrid; /* operator panel */ Element *data_sw, *ma_sw, *misc_sw; Element *ir_l, *mi_l, *pc_l, *ma_l, *pih_l, *pir_l, *pio_l, *misc_l; /* bay indicator panel */ Element *mb_l, *ar_l, *mq_l; Element *ff_l; /* flip flops */ /* io panel */ Element *iobus_l, *cr_l, *crbuf_l, *ptr_l, *ptrbuf_l, *ptp_l, *ptpbuf_l, *tty_l, *ttibuf_l, *pr_l, *rlr_l, *rla_l; /* extra panel */ Element *extra_sw; Element *extra_l; SwDigit data_digits[12]; SwDigit addr_digits[6]; SwDigit *curdigit; SDL_Rect digitindline; #include "elements.inc" void setelements(word w, Element *l, int n) { int i; for(i = 0; i < n; i++) l[n-i-1].state = !!(w & 1L<k && !oldapr.k) Lock panellock; Rendez panelsynch; /* Set panel from internal APR state */ void updatepanel(Apr *apr) { setelements(apr->data, data_sw, 36); setelements(apr->mas, ma_sw, 18); extra_sw[0].state = apr->sw_rim_maint; extra_sw[1].state = apr->sw_rpt_bypass; extra_sw[2].state = apr->sw_art3_maint; extra_sw[3].state = apr->sw_sct_maint; extra_sw[4].state = apr->sw_spltcyc_override; } static void updateapr(Apr *apr, Ptr *ptr) { Apr oldapr; if(apr == nil) return; oldapr = *apr; setelements(apr->ir, ir_l, 18); setelements(apr->mi, mi_l, 36); setelements(apr->pc, pc_l, 18); setelements(apr->ma, ma_l, 18); setelements(apr->pih, pih_l, 7); setelements(apr->pir, pir_l, 7); setelements(apr->pio, pio_l, 7); misc_l[0].state = apr->pi_active; misc_l[1].state = apr->mc_stop; misc_l[2].state = apr->run; misc_l[3].state = apr->sw_repeat = misc_sw[0].state; misc_l[4].state = apr->sw_addr_stop = misc_sw[1].state; misc_l[5].state = apr->sw_power = misc_sw[2].state; misc_l[6].state = apr->sw_mem_disable = misc_sw[3].state; apr->data = getelements(data_sw, 36); apr->mas = getelements(ma_sw, 18); apr->sw_rim_maint = extra_sw[0].state; if(apr->sw_rim_maint) apr->key_rim_sbr = 1; apr->sw_rpt_bypass = extra_sw[1].state; apr->sw_art3_maint = extra_sw[2].state; apr->sw_sct_maint = extra_sw[3].state; apr->sw_spltcyc_override = extra_sw[4].state; apr->key_start = keys[0].state == 1; apr->key_readin = keys[0].state == 2; apr->key_inst_cont = keys[1].state == 1; apr->key_mem_cont = keys[1].state == 2; apr->key_inst_stop = keys[2].state == 1; apr->key_mem_stop = keys[2].state == 2; apr->key_io_reset = keys[3].state == 1; apr->key_exec = keys[3].state == 2; apr->key_dep = keys[4].state == 1; apr->key_dep_nxt = keys[4].state == 2; apr->key_ex = keys[5].state == 1; apr->key_ex_nxt = keys[5].state == 2; apr->key_rd_off = keys[6].state == 1; apr->key_rd_on = keys[6].state == 2; apr->key_pt_rd = keys[7].state == 1; apr->key_pt_wr = keys[7].state == 2; if(apr->sw_power){ if(KEYPULSE(key_start) || KEYPULSE(key_readin) || KEYPULSE(key_inst_cont) || KEYPULSE(key_mem_cont) || KEYPULSE(key_io_reset) || KEYPULSE(key_exec) || KEYPULSE(key_dep) || KEYPULSE(key_dep_nxt) || KEYPULSE(key_ex) || KEYPULSE(key_ex_nxt)) apr->extpulse |= EXT_KEY_MANUAL; if(KEYPULSE(key_inst_stop)) apr->extpulse |= EXT_KEY_INST_STOP; if(ptr){ if(KEYPULSE(key_rd_on)) ptr_setmotor(ptr, 1); if(KEYPULSE(key_rd_off)) ptr_setmotor(ptr, 0); } } setelements(apr->c.mb, mb_l, 36); setelements(apr->c.ar, ar_l, 36); setelements(apr->c.mq, mq_l, 36); ff_l[0].state = apr->key_ex_st; ff_l[1].state = apr->key_ex_sync; ff_l[2].state = apr->key_dep_st; ff_l[3].state = apr->key_dep_sync; ff_l[4].state = apr->key_rd_wr; ff_l[5].state = apr->mc_rd; ff_l[6].state = apr->mc_wr; ff_l[7].state = apr->mc_rq; ff_l[8].state = apr->if1a; ff_l[9].state = apr->af0; ff_l[10].state = apr->af3; ff_l[11].state = apr->af3a; ff_l[12].state = apr->et4_ar_pse; ff_l[13].state = apr->f1a; ff_l[14].state = apr->f4a; ff_l[15].state = apr->f6a; ff_l[16].state = apr->sf3; ff_l[17].state = apr->sf5a; ff_l[18].state = apr->sf7; ff_l[19].state = apr->ar_com_cont; ff_l[20].state = apr->blt_f0a; ff_l[21].state = apr->blt_f3a; ff_l[22].state = apr->blt_f5a; ff_l[23].state = apr->iot_f0a; ff_l[24].state = apr->fpf1; ff_l[25].state = apr->fpf2; ff_l[26].state = apr->faf1; ff_l[27].state = apr->faf2; ff_l[28].state = apr->faf3; ff_l[29].state = apr->faf4; ff_l[30].state = apr->fmf1; ff_l[31].state = apr->fmf2; ff_l[32].state = apr->fdf1; ff_l[33].state = apr->fdf2; ff_l[34].state = apr->ir & H6 && apr->c.mq & F1 && !apr->nrf3; ff_l[35].state = apr->nrf1; ff_l[36].state = apr->nrf2; ff_l[37].state = apr->nrf3; ff_l[38].state = apr->fsf1; ff_l[39].state = apr->chf7; ff_l[40].state = apr->dsf1; ff_l[41].state = apr->dsf2; ff_l[42].state = apr->dsf3; ff_l[43].state = apr->dsf4; ff_l[44].state = apr->dsf5; ff_l[45].state = apr->dsf6; ff_l[46].state = apr->dsf7; ff_l[47].state = apr->dsf8; ff_l[48].state = apr->dsf9; ff_l[49].state = apr->msf1; ff_l[50].state = apr->mpf1; ff_l[51].state = apr->mpf2; ff_l[52].state = apr->mc_split_cyc_sync; ff_l[53].state = apr->mc_stop_sync; ff_l[54].state = apr->shf1; ff_l[55].state = apr->sc == 0777; ff_l[56].state = apr->chf1; ff_l[57].state = apr->chf2; ff_l[58].state = apr->chf3; ff_l[59].state = apr->chf4; ff_l[60].state = apr->chf5; ff_l[61].state = apr->chf6; ff_l[62].state = apr->lcf1; ff_l[63].state = apr->dcf1; ff_l[64].state = apr->pi_ov; ff_l[65].state = apr->pi_cyc; ff_l[66].state = !!apr->pi_req; ff_l[67].state = apr->iot_go; ff_l[68].state = apr->a_long; ff_l[69].state = apr->ma == apr->mas; ff_l[70].state = apr->uuo_f1; ff_l[71].state = apr->cpa_pdl_ov; setelements(apr->fe, &ff_l[72], 8); setelements(apr->sc, &ff_l[80], 8); ff_l[88].state = !apr->ex_user; ff_l[89].state = apr->cpa_illeg_op; ff_l[90].state = apr->ex_ill_op; ff_l[91].state = apr->ex_uuo_sync; ff_l[92].state = apr->ex_pi_sync; ff_l[93].state = apr->mq36; ff_l[94].state = !!(apr->sc & 0400); ff_l[95].state = !!(apr->fe & 0400); ff_l[96].state = apr->key_rim_sbr; ff_l[97].state = apr->ar_cry0_xor_cry1; ff_l[98].state = apr->ar_cry0; ff_l[99].state = apr->ar_cry1; ff_l[100].state = apr->ar_ov_flag; ff_l[101].state = apr->ar_cry0_flag; ff_l[102].state = apr->ar_cry1_flag; ff_l[103].state = apr->ar_pc_chg_flag; ff_l[104].state = apr->cpa_non_exist_mem; ff_l[105].state = apr->cpa_clock_enable; ff_l[106].state = apr->cpa_clock_flag; ff_l[107].state = apr->cpa_pc_chg_enable; ff_l[108].state = apr->cpa_arov_enable; ff_l[109].state = !!(apr->cpa_pia&4); ff_l[110].state = !!(apr->cpa_pia&2); ff_l[111].state = !!(apr->cpa_pia&1); setelements(apr->pr, pr_l, 8); setelements(apr->rlr, rlr_l, 8); setelements(apr->rla, rla_l, 8); setelements(apr->iobus.c12, iobus_l, 36); rwakeupall(&panelsynch); } #include "mmregs.h" void writeconsreg(Apr *apr, u32 addr, u32 data) { switch(addr){ case MM_APR_CTL1_UP: //printf("write CTL1 UP %o\n", data); if(data & 3){ keys[0].active = 0; keys[0].state = 0; } if(data & 014){ keys[1].active = 0; keys[1].state = 0; } if(data & 060){ keys[2].active = 0; keys[2].state = 0; } if(data & 0300){ keys[3].active = 0; keys[3].state = 0; } if(data & 0400) misc_sw[1].state = 0; break; case MM_APR_CTL1_DN: //printf("write CTL1 DN %o\n", data); if(data & 1){ keys[0].active = 1; keys[0].state = 1; } if(data & 2){ keys[0].active = 1; keys[0].state = 2; } if(data & 4){ keys[1].active = 1; keys[1].state = 1; } if(data & 010){ keys[1].active = 1; keys[1].state = 2; } if(data & 020){ keys[2].active = 1; keys[2].state = 1; } if(data & 040){ keys[2].active = 1; keys[2].state = 2; } if(data & 0100){ keys[3].active = 1; keys[3].state = 1; } if(data & 0200){ keys[3].active = 1; keys[3].state = 2; } if(data & 0400) misc_sw[1].state = 1; break; case MM_APR_CTL2_UP: //printf("write CTL2 UP %o\n", data); if(data & 3){ keys[4].active = 0; keys[4].state = 0; } if(data & 014){ keys[5].active = 0; keys[5].state = 0; } if(data & 060){ keys[6].active = 0; keys[6].state = 0; } if(data & 0300){ keys[7].active = 0; keys[7].state = 0; } if(data & 0400) misc_sw[0].state = 0; if(data & 01000) misc_sw[3].state = 0; break; case MM_APR_CTL2_DN: //printf("write CTL2 DN %o\n", data); if(data & 1){ keys[4].active = 1; keys[4].state = 1; } if(data & 2){ keys[4].active = 1; keys[4].state = 2; } if(data & 4){ keys[5].active = 1; keys[5].state = 1; } if(data & 010){ keys[5].active = 1; keys[5].state = 2; } if(data & 020){ keys[6].active = 1; keys[6].state = 1; } if(data & 040){ keys[6].active = 1; keys[6].state = 2; } if(data & 0100){ keys[7].active = 1; keys[7].state = 1; } if(data & 0200){ keys[7].active = 1; keys[7].state = 2; } if(data & 0400) misc_sw[0].state = 1; if(data & 01000) misc_sw[3].state = 1; break; case MM_APR_MAINT_DN: // TODO: break; case MM_APR_DSLT: setelements(data, data_sw, 18); break; case MM_APR_DSRT: setelements(data, data_sw+18, 18); break; case MM_APR_MAS: setelements(data, ma_sw, 18); break; case MM_APR_REPEAT: break; // TODO } // wait for panel to pick up values rsleep(&panelsynch); } u32 readconsreg(Apr *apr, u32 addr) { u32 d; switch(addr){ case MM_APR_CTL1_DN: d = apr->key_start; d |= apr->key_readin<<1; d |= apr->key_inst_cont<<2; d |= apr->key_mem_cont<<3; d |= apr->key_inst_stop<<4; d |= apr->key_mem_stop<<5; d |= apr->key_io_reset<<6; d |= apr->key_exec<<7; d |= apr->sw_addr_stop<<8; d |= apr->run<<9; d |= apr->mc_stop<<10; d |= apr->sw_power<<11; return d; case MM_APR_CTL2_DN: d = apr->key_dep; d |= apr->key_dep_nxt<<1; d |= apr->key_ex<<2; d |= apr->key_ex_nxt<<3; d |= apr->key_rd_off<<4; d |= apr->key_rd_on<<5; d |= apr->key_pt_rd<<6; d |= apr->key_pt_wr<<7; d |= apr->sw_repeat<<8; d |= apr->sw_mem_disable<<9; return d; case MM_APR_MAINT_DN: // TODO: break; case MM_APR_DSLT: return getelements(data_sw, 36)>>18; case MM_APR_DSRT: return getelements(data_sw, 36)&RT; case MM_APR_MAS: return getelements(ma_sw, 18); case MM_APR_REPEAT: return 0; // TODO case MM_APR_IR: return apr->ir; case MM_APR_MILT: return apr->mi>>18; case MM_APR_MIRT: return apr->mi&RT; case MM_APR_PC: return apr->pc; case MM_APR_MA: return apr->ma; case MM_APR_PI: return apr->pi_active | apr->pio<<1 | apr->pir<<8 | apr->pih<<15; case MM_APR_MBLT: return apr->c.mb>>18; case MM_APR_MBRT: return apr->c.mb&RT; case MM_APR_ARLT: return apr->c.ar>>18; case MM_APR_ARRT: return apr->c.ar&RT; case MM_APR_MQLT: return apr->c.mq>>18; case MM_APR_MQRT: return apr->c.mq&RT; case MM_APR_FF1: d = 0; d |= (u32)apr->key_ex_st << 31; d |= (u32)apr->key_ex_sync << 30; d |= (u32)apr->key_dep_st << 29; d |= (u32)apr->key_dep_sync << 28; d |= (u32)apr->key_rd_wr << 27; d |= (u32)apr->mc_rd << 26; d |= (u32)apr->mc_wr << 25; d |= (u32)apr->mc_rq << 24; d |= (u32)apr->if1a << 23; d |= (u32)apr->af0 << 22; d |= (u32)apr->af3 << 21; d |= (u32)apr->af3a << 20; d |= (u32)apr->et4_ar_pse << 19; d |= (u32)apr->f1a << 18; d |= (u32)apr->f4a << 17; d |= (u32)apr->f6a << 16; d |= (u32)apr->sf3 << 15; d |= (u32)apr->sf5a << 14; d |= (u32)apr->sf7 << 13; d |= (u32)apr->ar_com_cont << 12; d |= (u32)apr->blt_f0a << 11; d |= (u32)apr->blt_f3a << 10; d |= (u32)apr->blt_f5a << 9; d |= (u32)apr->iot_f0a << 8; d |= (u32)apr->fpf1 << 7; d |= (u32)apr->fpf2 << 6; d |= (u32)apr->faf1 << 5; d |= (u32)apr->faf2 << 4; d |= (u32)apr->faf3 << 3; d |= (u32)apr->faf4 << 2; d |= (u32)apr->fmf1 << 1; d |= (u32)apr->fmf2 << 0; return d; case MM_APR_FF2: d = 0; d |= (u32)apr->fdf1 << 31; d |= (u32)apr->fdf2 << 30; d |= (u32)(apr->ir & H6 && apr->c.mq & F1 && !apr->nrf3) << 29; d |= (u32)apr->nrf1 << 28; d |= (u32)apr->nrf2 << 27; d |= (u32)apr->nrf3 << 26; d |= (u32)apr->fsf1 << 25; d |= (u32)apr->chf7 << 24; d |= (u32)apr->dsf1 << 23; d |= (u32)apr->dsf2 << 22; d |= (u32)apr->dsf3 << 21; d |= (u32)apr->dsf4 << 20; d |= (u32)apr->dsf5 << 19; d |= (u32)apr->dsf6 << 18; d |= (u32)apr->dsf7 << 17; d |= (u32)apr->dsf8 << 16; d |= (u32)apr->dsf9 << 15; d |= (u32)apr->msf1 << 14; d |= (u32)apr->mpf1 << 13; d |= (u32)apr->mpf2 << 12; d |= (u32)apr->mc_split_cyc_sync << 11; d |= (u32)apr->mc_stop_sync << 10; d |= (u32)apr->shf1 << 9; d |= (u32)(apr->sc == 0777) << 8; d |= (u32)apr->chf1 << 7; d |= (u32)apr->chf2 << 6; d |= (u32)apr->chf3 << 5; d |= (u32)apr->chf4 << 4; d |= (u32)apr->chf5 << 3; d |= (u32)apr->chf6 << 2; d |= (u32)apr->lcf1 << 1; d |= (u32)apr->dcf1 << 0; return d; case MM_APR_FF3: d = 0; d |= (u32)apr->pi_ov << 31; d |= (u32)apr->pi_cyc << 30; d |= (u32)(!!apr->pi_req) << 29; d |= (u32)apr->iot_go << 28; d |= (u32)apr->a_long << 27; d |= (u32)(apr->ma == apr->mas) << 26; d |= (u32)apr->uuo_f1 << 25; d |= (u32)apr->cpa_pdl_ov << 24; d |= (u32)(apr->fe&0377) << 16; d |= (u32)(apr->fe&0377) << 8; d |= (u32)(!apr->ex_user) << 7; d |= (u32)apr->cpa_illeg_op << 6; d |= (u32)apr->ex_ill_op << 5; d |= (u32)apr->ex_uuo_sync << 4; d |= (u32)apr->ex_pi_sync << 3; d |= (u32)apr->mq36 << 2; d |= (u32)(!!(apr->sc&0400)) << 1; d |= (u32)(!!(apr->fe&0400)) << 0; return d; case MM_APR_FF4: d = 0; d |= (u32)apr->key_rim_sbr << 31; d |= (u32)apr->ar_cry0_xor_cry1 << 30; d |= (u32)apr->ar_cry0 << 29; d |= (u32)apr->ar_cry1 << 28; d |= (u32)apr->ar_ov_flag << 27; d |= (u32)apr->ar_cry0_flag << 26; d |= (u32)apr->ar_cry1_flag << 25; d |= (u32)apr->ar_pc_chg_flag << 24; d |= (u32)apr->cpa_non_exist_mem << 23; d |= (u32)apr->cpa_clock_enable << 22; d |= (u32)apr->cpa_clock_flag << 21; d |= (u32)apr->cpa_pc_chg_enable << 20; d |= (u32)apr->cpa_arov_enable << 19; d |= (u32)(!!(apr->cpa_pia&4)) << 18; d |= (u32)(!!(apr->cpa_pia&2)) << 17; d |= (u32)(!!(apr->cpa_pia&1)) << 16; return d; case MM_APR_MMU: d = apr->pr; d = (u32)apr->rlr << 8; d = (u32)apr->rla << 16; return d; } return 0; } static void updatetty(Tty *tty) { if(tty){ tty_l[0].state = tty->tti_busy; tty_l[1].state = tty->tti_flag; tty_l[2].state = tty->tto_busy; tty_l[3].state = tty->tto_flag; setelements(tty->pia, &tty_l[4], 3); setelements(tty->tti, ttibuf_l, 8); } } static void updatept(Ptp *ptp, Ptr *ptr) { if(ptp){ ptp_l[0].state = ptp->b; ptp_l[1].state = ptp->busy; ptp_l[2].state = ptp->flag; setelements(ptp->pia, &ptp_l[3], 3); setelements(ptp->ptp, ptpbuf_l, 8); } if(ptr){ ptr_l[0].state = ptr->b; ptr_l[1].state = ptr->busy; ptr_l[2].state = ptr->flag; setelements(ptr->pia, &ptr_l[3], 3); setelements(ptr->ptr, ptrbuf_l, 36); extra_l[0].state = ptr->motor_on; } } static void putpixel(SDL_Texture *screen, int x, int y, Uint32 col) { // TODO: rewrite for SDL2 /* Uint32 *p = (Uint32*)screen->pixels; if(x < 0 || x >= screen->w || y < 0 || y >= screen->h) return; p += y*screen->w+x; *p = SDL_MapRGBA(screen->format, col&0xFF, (col>>8)&0xFF, (col>>16)&0xFF, (col>>24)&0xFF); */ } static void drawhline(SDL_Texture *screen, int y, int x1, int x2, Uint32 col) { for(; x1 < x2; x1++) putpixel(screen, x1, y, col); } static void drawvline(SDL_Texture *screen, int x, int y1, int y2, Uint32 col) { for(; y1 < y2; y1++) putpixel(screen, x, y1, col); } static Point xform(Grid *g, Point p) { p.x = g->panel->pos.x + g->xoff + p.x*g->xscl; p.y = g->panel->pos.y + (g->panel->surf->h - (g->yoff + p.y*g->yscl)); return p; } static int ismouseover(Element *e, int x, int y) { Point p; p = xform(e->grid, e->pos); return x >= p.x && x <= p.x + e->surf[e->state]->w && y >= p.y && y <= p.y + e->surf[e->state]->h; } static void drawgrid(Grid *g, SDL_Texture *s, Uint32 col) { Image *pi; int x, y; int xmax, ymax; Point p; pi = g->panel->surf; xmax = pi->w/g->xscl; ymax = pi->h/g->yscl; for(x = 0; x < xmax; x++){ p = xform(g, (Point){ x, 0 }); drawvline(s, p.x, p.y - pi->h, p.y, col); } for(y = 0; y < ymax; y++){ p = xform(g, (Point){ 0, y }); drawhline(s, p.y, p.x, p.x + pi->w, col); } } static void drawpanel(SDL_Renderer *renderer, Panel *p) { if(p->pos.x < 0) return; p->pos.w = p->surf->w; p->pos.h = p->surf->h; SDL_RenderCopy(renderer, p->surf->tex, nil, &p->pos); } static void drawelement(SDL_Renderer *renderer, Element *elt, int power) { Image *img; SDL_Rect r; Point p; int s; if(elt->grid->panel == nil) return; p = xform(elt->grid, elt->pos); r.x = p.x+0.5; r.y = p.y+0.5; if(elt->surf == lampsurf) s = elt->state && power; else s = elt->state; img = elt->surf[s]; r.w = img->w; r.h = img->h; SDL_RenderCopy(renderer, img->tex, nil, &r); } static void mouse(int button, int state, int x, int y) { static int buttonstate; Element *e; int i; if(button){ if(state == 1) buttonstate |= 1 << button-1; else buttonstate &= ~(1 << button-1); } /* keys */ for(i = 0; i < nelem(keys); i++){ e = &keys[i]; /* e->active means latched on/off for keys */ if(buttonstate == 0 || !ismouseover(e, x, y)){ if(!e->active) e->state = 0; continue; } if((buttonstate & 5) == 5) /* left and right -> latched on/off */ e->active = !e->active; else if(buttonstate & 1) /* left button -> down */ e->state = 1; else if(buttonstate & 4) /* right button -> up */ e->state = 2; } /* switches */ for(i = 0; i < nelem(switches); i++){ e = &switches[i]; if(buttonstate == 0 || !ismouseover(e, x, y)){ e->active = 0; continue; } if(!e->active){ e->active = 1; if(buttonstate & 1) /* left button, toggle */ e->state = !e->state; else if(buttonstate & 2) /* middle button, on */ e->state = 1; else if(buttonstate & 4) /* right button, off */ e->state = 0; } } } static void setcurdigit(SwDigit *d) { Point p1, p2; curdigit = d; p1 = xform(d->sw[0].grid, d->sw[0].pos); p2 = xform(d->sw[2].grid, d->sw[2].pos); p2.x += d->sw[2].surf[0]->w; p2.y += d->sw[2].surf[0]->h; digitindline.x = p1.x; digitindline.y = p1.y; digitindline.w = p2.x - p1.x; digitindline.h = p2.y - p1.y; } static void setdigit(int n) { curdigit->sw[0].state = !!(n & 4); curdigit->sw[1].state = !!(n & 2); curdigit->sw[2].state = !!(n & 1); setcurdigit(curdigit->next); } /* This is in some ways horrible, but oh well */ static void keydown(SDL_Keysym keysym) { int i; static Element *dsrc, *asrc, **srcp; static int dlen, alen, *lenp; word mask, s, d; int ctrl, len; const u8 *keystate; if(dsrc == nil){ dsrc = mi_l; dlen = 36; } if(asrc == nil){ asrc = ma_l; alen = 18; } if(srcp == nil){ srcp = &dsrc; lenp = &dlen; } keystate = SDL_GetKeyboardState(nil); ctrl = keystate[SDL_SCANCODE_CAPSLOCK] || keystate[SDL_SCANCODE_LCTRL] || keystate[SDL_SCANCODE_RCTRL]; switch(keysym.scancode){ case SDL_SCANCODE_0: setdigit(0); break; case SDL_SCANCODE_1: setdigit(1); break; case SDL_SCANCODE_2: setdigit(2); break; case SDL_SCANCODE_3: setdigit(3); break; case SDL_SCANCODE_4: setdigit(4); break; case SDL_SCANCODE_5: setdigit(5); break; case SDL_SCANCODE_6: setdigit(6); break; case SDL_SCANCODE_7: setdigit(7); break; case SDL_SCANCODE_LEFT: setcurdigit(curdigit->prev); break; case SDL_SCANCODE_RIGHT: setcurdigit(curdigit->next); break; /* Set destination switches */ case SDL_SCANCODE_A: setcurdigit(addr_digits); srcp = &asrc; lenp = &alen; break; case SDL_SCANCODE_S: setcurdigit(data_digits); srcp = &dsrc; lenp = &dlen; break; /* Set source lights */ case SDL_SCANCODE_M: *srcp = ma_l; *lenp = 18; break; case SDL_SCANCODE_P: *srcp = pc_l; *lenp = 18; break; case SDL_SCANCODE_I: *srcp = ir_l; *lenp = 18; break; case SDL_SCANCODE_D: *srcp = mi_l; *lenp = 36; break; /* Set MA from IR AC */ case SDL_SCANCODE_R: d = getelements(ir_l, 18); d = d>>5 & 017; setelements(d, ma_sw, 18); break; /* Set MA from IR index */ case SDL_SCANCODE_X: d = getelements(ir_l, 18); d &= 017; setelements(d, ma_sw, 18); break; /* Clear */ case SDL_SCANCODE_C: for(i = 0; i < 12; i++) setdigit(0); break; case SDL_SCANCODE_J: mask = LT; goto load; case SDL_SCANCODE_K: mask = FW; goto load; case SDL_SCANCODE_L: mask = RT; goto load; load: if(curdigit->first == data_sw) len = 36; else len = 18; d = getelements(curdigit->first, len); s = getelements(*srcp, *lenp); if(ctrl) s = (s&RT)<<18 | (s<)>>18; d = s&mask | d&~mask; setelements(d, curdigit->first, len); break; default: break; } } static void findlayout(int *w, int *h) { float gap; gap = (oppanel.surf->w - indpanel1.surf->w - indpanel2.surf->w)/4.0f; indpanel1.pos = (SDL_Rect){ 0, 0, 0, 0 }; indpanel1.pos.x += gap; indpanel2.pos = indpanel1.pos; indpanel2.pos.x += indpanel1.surf->w + 2*gap; iopanel.pos = indpanel2.pos; iopanel.pos.y += indpanel2.surf->h; oppanel.pos = (SDL_Rect){ 0, 0, 0, 0 }; oppanel.pos.y += indpanel1.surf->h*2.7; extrapanel.pos = indpanel1.pos; extrapanel.pos.y = oppanel.pos.y - extrapanel.surf->h; *w = oppanel.surf->w; *h = oppanel.pos.y + oppanel.surf->h; } static void initpanel(void) { Element *e; #ifdef LOADFILES oppanel.surf = mustloadimg("../art/op_panel.png"); iopanel.surf = mustloadimg("../art/io_panel.png"); indpanel1.surf = mustloadimg("../art/ind_panel1.png"); indpanel2.surf = mustloadimg("../art/ind_panel2.png"); extrapanel.surf = mustloadimg("../art/extra_panel.png"); lampsurf[0] = mustloadimg("../art/lamp_off.png"); lampsurf[1] = mustloadimg("../art/lamp_on.png"); switchsurf[0] = mustloadimg("../art/switch_d.png"); switchsurf[1] = mustloadimg("../art/switch_u.png"); keysurf[0] = mustloadimg("../art/key_n.png"); keysurf[1] = mustloadimg("../art/key_d.png"); keysurf[2] = mustloadimg("../art/key_u.png"); #else oppanel.surf = loadresimg(op_panel_png, op_panel_png_len); iopanel.surf = loadresimg(io_panel_png, io_panel_png_len); indpanel1.surf = loadresimg(ind_panel1_png, ind_panel1_png_len); indpanel2.surf = loadresimg(ind_panel2_png, ind_panel2_png_len); extrapanel.surf = loadresimg(extra_panel_png, extra_panel_png_len); lampsurf[0] = loadresimg(lamp_off_png, lamp_off_png_len); lampsurf[1] = loadresimg(lamp_on_png, lamp_on_png_len); switchsurf[0] = loadresimg(switch_d_png, switch_d_png_len); switchsurf[1] = loadresimg(switch_u_png, switch_u_png_len); keysurf[0] = loadresimg(key_n_png, key_n_png_len); keysurf[1] = loadresimg(key_d_png, key_d_png_len); keysurf[2] = loadresimg(key_u_png, key_u_png_len); #endif opgrid1.panel = &oppanel; opgrid1.xscl = opgrid1.panel->surf->w/90.0f; opgrid1.yscl = opgrid1.panel->surf->h/11.0f; opgrid1.yoff = opgrid1.yscl/2.0f; opgrid2.panel = &oppanel; opgrid2.xscl = opgrid1.xscl*1.76f; opgrid2.yscl = opgrid2.xscl; opgrid2.xoff = opgrid1.xscl*44.5f; opgrid2.yoff = opgrid1.panel->surf->h*2.4f/143.0f; iogrid.panel = &iopanel; iogrid.xscl = iogrid.panel->surf->w/44.0f; iogrid.yscl = iogrid.panel->surf->h/28.0f; indgrid1.panel = &indpanel1; indgrid1.xscl = indgrid1.panel->surf->w*5.0f/77.0f; indgrid1.yscl = indgrid1.panel->surf->h/12.0f; indgrid2.panel = &indpanel2; indgrid2.xscl = indgrid2.panel->surf->w/44.0f; indgrid2.yscl = indgrid2.panel->surf->h/11.0f; extragrid = indgrid1; extragrid.panel = &extrapanel; e = switches; data_sw = e; e += 36; ma_sw = e; e += 18; misc_sw = e; e += 4; extra_sw = e; e += 5; e = lamps; mi_l = e; e += 36; ir_l = e; e += 18; ma_l = e; e += 18; pc_l = e; e += 18; pio_l = e; e += 7; pir_l = e; e += 7; pih_l = e; e += 7; misc_l = e; e += 7; mb_l = e; e += 36; ar_l = e; e += 36; mq_l = e; e += 36; ff_l = e; e += 14*8; iobus_l = e; e += 36; cr_l = e; e += 9; crbuf_l = e; e += 36; ptr_l = e; e += 6; ptrbuf_l = e; e += 36; ptp_l = e; e += 6; ptpbuf_l = e; e += 8; tty_l = e; e += 7; ttibuf_l = e; e += 8; pr_l = e; e += 8; rlr_l = e; e += 8; rla_l = e; e += 8; extra_l = e; e += 1; } void usage(void) { fprintf(stderr, "usage: %s [-t] [-d debugfile]\n", argv0); exit(1); } extern void joy_motion (SDL_JoyAxisEvent *event); extern void joy_button (SDL_JoyButtonEvent *event); extern void controller_motion (SDL_ControllerAxisEvent *event); extern void controller_button (SDL_ControllerButtonEvent *event); int threadmain(int argc, char *argv[]) { SDL_Event ev; SDL_MouseButtonEvent *mbev; SDL_MouseMotionEvent *mmev; Element *e; int i; int w, h; const char *outfile; Channel *cmdchans[2]; Task t; Apr *apr; Ptr *ptr; Ptp *ptp; Tty *tty; outfile = "/dev/null"; ARGBEGIN{ case 't': dotrace = 1; break; case 'd': outfile = EARGF(usage()); break; default: usage(); }ARGEND; if(debugfp = fopen(outfile, "w"), debugfp == nil){ fprintf(stderr, "Can't open %s\n", outfile); exit(1); } void test_apr(void); //test_apr(); SDL_Init(SDL_INIT_EVERYTHING); IMG_Init(IMG_INIT_PNG); void main340(void); // main340(); // return 0; if(SDL_CreateWindowAndRenderer(1399, 740, 0, &window, &renderer) < 0) err("SDL_CreateWindowAndRenderer() failed: %s\n", SDL_GetError()); SDL_SetWindowTitle(window, "PDP-6 console"); initpanel(); panelsynch.l = &panellock; findlayout(&w, &h); SDL_SetWindowSize(window, w, h); for(i = 0; i < 12; i++){ data_digits[i].first = data_sw; data_digits[i].sw = &data_sw[i*3]; data_digits[i].prev = &data_digits[(i+11) % 12]; data_digits[i].next = &data_digits[(i+1) % 12]; } for(i = 0; i < 6; i++){ addr_digits[i].first = ma_sw; addr_digits[i].sw = &ma_sw[i*3]; addr_digits[i].prev = &addr_digits[(i+5) % 6]; addr_digits[i].next = &addr_digits[(i+1) % 6]; } setcurdigit(data_digits); rtcchan = chancreate(sizeof(RtcMsg), 20); if(dofile("init.ini")) defaultconfig(); apr = (Apr*)getdevice("apr"); tty = (Tty*)getdevice("tty"); ptr = (Ptr*)getdevice("ptr"); ptp = (Ptp*)getdevice("ptp"); if(apr == nil || tty == nil || ptr == nil || ptp == nil) err("need APR, TTY, PTR and PTP"); while(awaitinit); cmdchans[0] = chancreate(sizeof(char*), 1); cmdchans[1] = chancreate(sizeof(void*), 1); t = (Task){ nil, readcmdchan, cmdchans, 10, 0 }; addtask(t); threadcreate(simthread, nil); threadcreate(cmdthread, cmdchans); threadcreate(rtcthread, nil); for(;;){ while(SDL_PollEvent(&ev)) switch(ev.type){ case SDL_MOUSEMOTION: mmev = (SDL_MouseMotionEvent*)&ev; mouse(0, mmev->state, mmev->x, mmev->y); break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: mbev = (SDL_MouseButtonEvent*)&ev; mouse(mbev->button, mbev->state, mbev->x, mbev->y); break; case SDL_CONTROLLERAXISMOTION: controller_motion (&ev.caxis); break; case SDL_JOYAXISMOTION: joy_motion (&ev.jaxis); break; case SDL_JOYBUTTONUP: case SDL_JOYBUTTONDOWN: joy_button (&ev.jbutton); break; case SDL_CONTROLLERBUTTONUP: case SDL_CONTROLLERBUTTONDOWN: controller_button (&ev.cbutton); break; case SDL_KEYDOWN: keydown(ev.key.keysym); break; case SDL_QUIT: quit(0); } updateapr(apr, ptr); updatetty(tty); updatept(ptp, ptr); SDL_SetRenderDrawColor(renderer, 0xe6, 0xe6, 0xe6, 0xff); SDL_RenderClear(renderer); drawpanel(renderer, &indpanel1); drawpanel(renderer, &indpanel2); drawpanel(renderer, &extrapanel); drawpanel(renderer, &iopanel); drawpanel(renderer, &oppanel); for(i = 0, e = lamps; i < nelem(lamps); i++, e++) drawelement(renderer, e, apr->sw_power); for(i = 0, e = keys; i < nelem(keys); i++, e++) drawelement(renderer, e, apr->sw_power); for(i = 0, e = switches; i < nelem(switches); i++, e++) drawelement(renderer, e, apr->sw_power); SDL_SetRenderDrawColor(renderer, 0xFF, 0, 0, 0xff); SDL_RenderDrawRect(renderer, &digitindline); // SDL_LockSurface(screen); // drawgrid(&opgrid1, screen, 0xFFFFFF00); // drawgrid(&opgrid2, screen, 0xFF0000FF); // drawgrid(&iogrid, screen, 0xFFFFFF00); // drawgrid(&indgrid1, screen, 0xFFFFFF00); // drawgrid(&indgrid2, screen, 0xFFFFFF00); // drawgrid(&extragrid, screen, 0xFFFFFF00); // SDL_UnlockSurface(screen); SDL_RenderPresent(renderer); SDL_Delay(30); } return 0; }