--- /dev/null
+/*
+ EPS TRN Junior Emulator 'eTRNJunior'
+
+ Author : Takeda.Toshiya
+ Date : 2022.07.02-
+
+ [ display / keyboard ]
+*/
+
+#include "display.h"
+#include "../i8255.h"
+
+static const int led_pattern[LED_SIZE_Y][LED_SIZE_X] = {
+ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ {0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0},
+ {0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,2,2,2,0,0,0,0},
+ {0,0,0,0,0,0,6,6,6,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,2,2,2,2,0,0,0,0},
+ {0,0,0,0,0,0,6,6,6,6,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,2,2,2,2,2,0,0,0,0},
+ {0,0,0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0},
+ {0,0,0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0},
+ {0,0,0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0},
+ {0,0,0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0},
+ {0,0,0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0},
+ {0,0,0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0},
+ {0,0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0},
+ {0,0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0},
+ {0,0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0},
+ {0,0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0},
+ {0,0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0},
+ {0,0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0},
+ {0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0,0},
+ {0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0,0},
+ {0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0,0},
+ {0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0,0},
+ {0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0,0},
+ {0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0,0},
+ {0,0,0,0,0,6,6,6,0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,0,2,2,2,0,0,0,0,0,0,0},
+ {0,0,0,0,0,0,0,0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0,0,0,0,0},
+ {0,0,0,0,0,0,0,0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0,0,0,0,0},
+ {0,0,0,0,0,5,5,5,0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,0,3,3,3,0,0,0,0,0,0,0},
+ {0,0,0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,0,0,0,0,0,0},
+ {0,0,0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,0,0,0,0,0,0},
+ {0,0,0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,0,0,0,0,0,0},
+ {0,0,0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,0,0,0,0,0,0},
+ {0,0,0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,0,0,0,0,0,0},
+ {0,0,0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,0,0,0,0,0,0},
+ {0,0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,0,0,0,0,0,0,0},
+ {0,0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,0,0,0,0,0,0,0},
+ {0,0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,0,0,0,0,0,0,0},
+ {0,0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,0,0,0,0,0,0,0},
+ {0,0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,0,0,0,0,0,0,0},
+ {0,0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,0,0,0,0,0,0,0},
+ {0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,0,0,0,0,0,0,0,0},
+ {0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,0,0,0,0,0,0,0,0},
+ {0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,0,0,0,0,0,0,0,0},
+ {0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,0,0,0,0,0,0,0,0},
+ {0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,0,0,0,0,0,0,0,0},
+ {0,0,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,0,0,0,0,0,0,0,0},
+ {0,0,5,5,5,5,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,3,3,3,3,3,0,0,8,8,8,8,0,0},
+ {0,0,5,5,5,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,3,3,3,3,0,0,8,8,8,8,0,0},
+ {0,0,0,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,3,3,3,0,0,8,8,8,8,0,0},
+ {0,0,0,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,8,8,8,8,0,0},
+ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+};
+
+void DISPLAY::initialize()
+{
+ memset(seg, 0, sizeof(seg));
+ pa = pc = 0;
+
+ // register event
+ register_vline_event(this);
+}
+
+void DISPLAY::event_vline(int v, int clock)
+{
+ if(!v) {
+ memset(seg, 0, sizeof(seg));
+ update_keyboard();
+ }
+ if(!(pc & 0x80)) {
+ for(int i = 0; i < 8; i++) {
+ if(pa & (1 << i)) {
+ seg[(pc >> 4) & 7][i]++;
+ }
+ }
+ }
+}
+
+void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
+{
+ switch(id) {
+ case SIG_DISPLAY_PORT_A:
+ pa = (pa & ~mask) | (data & mask);
+ break;
+ case SIG_DISPLAY_PORT_C:
+ pc = (pc & ~mask) | (data & mask);
+ update_keyboard();
+ break;
+ }
+}
+
+void DISPLAY::draw_screen()
+{
+ // draw 7-seg LEDs
+ scrntype_t col_h, col_l;
+ scrntype_t col[9];
+
+ col_h = RGB_COLOR(0, 255, 0);
+ col_l = RGB_COLOR(100, 100, 80);
+ col[0] = RGB_COLOR(57, 45, 37);
+
+ for(int i = 0; i < 8; i++) {
+ for(int j = 0; j < 8; j++) {
+ col[j + 1] = (seg[7 - i][j] > 8) ? col_h : col_l;
+ }
+ for(int y = 0; y < LED_SIZE_Y; y++) {
+ scrntype_t* dest = emu->get_screen_buffer(vm_ranges[i].y + y) + vm_ranges[i].x;
+ for(int x = 0; x < LED_SIZE_X; x++) {
+ dest[x] = col[led_pattern[y][x]];
+ }
+ }
+ }
+}
+
+void DISPLAY::update_keyboard()
+{
+ const uint8_t *key = emu->get_key_buffer();
+ uint8_t val = 0xff;
+
+ switch(pc & 0xf0) {
+ case 0x00:
+ if(key[0x30]) val &= ~0x01; // 0
+ if(key[0x31]) val &= ~0x02; // 1
+ if(key[0x32]) val &= ~0x04; // 2
+ if(key[0x33]) val &= ~0x08; // 3
+ break;
+ case 0x10:
+ if(key[0x34]) val &= ~0x01; // 4
+ if(key[0x35]) val &= ~0x02; // 5
+ if(key[0x36]) val &= ~0x04; // 6
+ if(key[0x37]) val &= ~0x08; // 7
+ break;
+ case 0x20:
+ if(key[0x38]) val &= ~0x01; // 8
+ if(key[0x39]) val &= ~0x02; // 9
+ if(key[0x41]) val &= ~0x04; // A
+ if(key[0x42]) val &= ~0x08; // B
+ break;
+ case 0x30:
+ if(key[0x43]) val &= ~0x01; // C
+ if(key[0x44]) val &= ~0x02; // D
+ if(key[0x45]) val &= ~0x04; // E
+ if(key[0x46]) val &= ~0x08; // F
+ break;
+ case 0x40:
+ if(key[0x70]) val &= ~0x01; // REG
+ if(key[0x71]) val &= ~0x02; // INC
+ if(key[0x72]) val &= ~0x04; // DEC
+ if(key[0x73]) val &= ~0x08; // RUN
+ break;
+ case 0x50:
+ if(key[0x74]) val &= ~0x01; // STEP
+ if(key[0x75]) val &= ~0x02; // WRT
+ if(key[0x76]) val &= ~0x04; // ADRS
+ if(key[0x77]) val &= ~0x08; // SHFT
+ break;
+ }
+ d_pio->write_signal(SIG_I8255_PORT_C, val, 0x0f);
+}
+
+#define STATE_VERSION 1
+
+bool DISPLAY::process_state(FILEIO* state_fio, bool loading)
+{
+ if(!state_fio->StateCheckUint32(STATE_VERSION)) {
+ return false;
+ }
+ if(!state_fio->StateCheckInt32(this_device_id)) {
+ return false;
+ }
+ state_fio->StateArray(&seg[0][0], sizeof(seg), 1);
+ state_fio->StateValue(pa);
+ state_fio->StateValue(pc);
+ return true;
+}
+