Subversion Repositories pentevo

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

  1. #include "std.h"
  2.  
  3. #include "emul.h"
  4. #include "vars.h"
  5. #include "font.h"
  6. #include "font16.h"
  7. #include "gs.h"
  8. #include "tape.h"
  9. #include "draw.h"
  10. #include "debug.h"
  11. #include "dbgbpx.h"
  12. #include "memory.h"
  13. #include "leds.h"
  14.  
  15. #include "util.h"
  16.  
  17. static unsigned pitch;
  18.  
  19. //=============================================================================
  20. void text_i(unsigned char *dst, const char *text, unsigned char ink, unsigned off)
  21. {
  22.    ink &= 0x0F;
  23.    for (const u8 *x = (const u8*)text; *x; x++) {
  24.       unsigned char *d0 = dst;
  25.       for (unsigned y = 0; y < 8; y++) {
  26.          unsigned char byte = font[(*x)*8+y];
  27.          d0[0] = (byte >> off) + (d0[0] & ~(0xFC >> off));
  28.          d0[1] = (d0[1] & 0xF0) + ink;
  29.          if (off > 2) {
  30.             d0[2] = u8((byte << (8-off)) + (d0[2] & ~(0xFC << (8-off))));
  31.             d0[3] = (d0[3] & 0xF0) + ink;
  32.          }
  33.          d0 += pitch;
  34.       }
  35.       off += 6;
  36.       if(off & 8)
  37.       {
  38.           off -= 8;
  39.           dst += 2;
  40.       }
  41.    }
  42. }
  43. //=============================================================================
  44.  
  45.  
  46. //=============================================================================
  47. static void text_16(unsigned char *dst, const char *text, unsigned char attr)
  48. {
  49.     for(; *text; text++, dst += 2)
  50.     {
  51.         for(unsigned y = 0; y < 16; y++)
  52.         {
  53.             dst[y*pitch] = font16[16 * *(const u8*)text + y];
  54.             dst[y*pitch + 1] = attr;
  55.         }
  56.     }
  57. }
  58. //=============================================================================
  59.  
  60.  
  61. //=============================================================================
  62. static unsigned char *aypos;
  63. static void paint_led(unsigned level, unsigned char at)
  64. {
  65.    if (level) {
  66.        if(level > 15)
  67.        {
  68.            level = 15; at = 0x0E;
  69.        }
  70.       unsigned mask = (0xFFFF0000 >> level) & 0xFFFF;
  71.       aypos[0] = u8(mask >> 8);
  72.       aypos[2] = (unsigned char)mask;
  73.       aypos[1] = (aypos[1] & 0xF0) + at;
  74.       aypos[3] = (aypos[3] & 0xF0) + at;
  75.    }
  76.    aypos += pitch;
  77. }
  78. //=============================================================================
  79.  
  80.  
  81. //=============================================================================
  82. static void ay_led()
  83. {
  84.    aypos = temp.led.ay;
  85.    unsigned char sum=0;
  86.                                 //яюьхэ Є№ ЎтхЄр ўЄюс эх ъюэЇышъЄютрыш ё ярышЄЁющ!
  87. //tone          схы√щ
  88. //°єь           цхыЄ√щ
  89. //юушср■∙р      чхыхэ√щ
  90.    int max_ay = (conf.sound.ay_scheme > AY_SCHEME_PSEUDO)? 2 : 1;
  91.    for (int n_ay = 0; n_ay < max_ay; n_ay++)    //AY-ъш
  92.    {
  93.       for (unsigned i = 0; i < 3; i++)  //3 channels
  94.       {
  95.          unsigned char r_mix = ay[n_ay].get_reg(7);
  96.          unsigned char tone = (r_mix >> i) & 1,
  97.                        noise = (r_mix >> (i+3)) & 1;
  98.          unsigned char c1 = 0, c2 = 0;
  99.          unsigned char v = ay[n_ay].get_reg(i+8);
  100.          
  101.          
  102.          c1 = 0x01;//blue       //07;           //DAC MODE      //NS
  103.          c2 = 0x0D;//cyan        //0B; //09;   
  104.          
  105.          //tone
  106.          if (!tone) c1 = c2 = 0x0F;     //схы√щ
  107.          
  108.          //noise
  109.          if (!noise) c2 = 0x0E;         //цхыЄ√щ
  110.          
  111.  
  112.         if (v & 0x10)
  113.         {
  114.             //envelope
  115.             //тшфшью ЄєЄ яЁ ьюх ўЄхэшх юушср■∙х
  116.             unsigned r_envT = ay[n_ay].get_reg(11) + 0x100*ay[n_ay].get_reg(12);
  117.             if (r_envT < 0x400)
  118.             {
  119.                v = (3-(r_envT>>3)) & 0x0F;
  120.                if (!v) v = 6;
  121.             }
  122.             else
  123.             {
  124.                 v = u8(ay[n_ay].get_env()/2);
  125.             }
  126.             c1 = 0x0C;
  127.         }
  128.         else
  129.         {
  130.                 //tone
  131.                 v &= 0x0F;      //схы√щ
  132.                 //c1 = 0x03;    //ЄхёЄ
  133.                                 //эртхЁэюх юЄ ё■фр ьюцэю яюЇшъёшЄ№
  134.                                 //ёЄрЁ√щ трЁшрэЄ ЎтхЄр °єьр
  135.         }
  136.          
  137.          if (!c1) c1 = c2;
  138.          if (!c2) c2 = c1;
  139.          if (!c1) v = 0;
  140.          
  141.          sum |= v;
  142.          paint_led(v, c1);
  143.          paint_led(v, c2);
  144.          paint_led(0, 0);
  145.       }
  146.    }
  147. //-----------------------------------------------------------------------------
  148.    const unsigned FMvols[]={4,9,15,23,35,48,70,105,140,195,243,335,452,608,761,1023};
  149.    #define _cBlue 0x09
  150.    #define _cRed 0x0a
  151.    #define _cPurp 0x0b
  152.    #define _cGreen 0x0c
  153.    #define _cCyan 0x0d
  154.    #define _cYell 0x0e
  155.    #define _cWhite 0x0f
  156.  
  157.    const u8 FMalg1[]={
  158.    _cBlue , _cPurp , _cGreen, _cWhite,
  159.    _cPurp , _cPurp , _cGreen, _cWhite,
  160.    _cGreen, _cPurp , _cGreen, _cWhite,
  161.    _cPurp , _cGreen, _cGreen, _cWhite,
  162.  
  163.    _cGreen, _cWhite, _cGreen, _cWhite,
  164.    _cPurp , _cWhite, _cWhite, _cWhite,
  165.    _cGreen, _cWhite, _cWhite, _cWhite,
  166.    _cWhite, _cWhite, _cWhite, _cWhite
  167.    };
  168.  
  169.    const u8 FMalg2[]={
  170.    _cBlue , _cPurp , _cGreen, _cYell ,
  171.    _cPurp , _cPurp , _cGreen, _cYell ,
  172.    _cGreen, _cPurp , _cGreen, _cYell ,
  173.    _cPurp , _cGreen, _cGreen, _cYell ,
  174.  
  175.    _cGreen, _cYell , _cGreen, _cYell ,
  176.    _cPurp , _cYell , _cYell , _cYell ,
  177.    _cGreen, _cYell , _cYell , _cYell ,
  178.    _cYell , _cYell , _cYell , _cYell
  179.    };
  180.  
  181.    const int FMslots[]={0,2,1,3};
  182. /*
  183.    const int FMalg1[]={
  184.    _cPurp , _cGreen, _cCyan , _cWhite,
  185.    _cPurp , _cPurp , _cGreen, _cWhite,
  186.    _cGreen, _cPurp , _cCyan , _cWhite,
  187.    _cPurp , _cCyan , _cGreen, _cWhite,
  188.  
  189.    _cPurp , _cWhite, _cGreen, _cWhite,
  190.    _cPurp , _cWhite, _cWhite, _cWhite,
  191.    _cGreen, _cWhite, _cWhite, _cWhite,
  192.    _cWhite, _cWhite, _cWhite, _cWhite
  193.    };
  194.  
  195.    const int FMalg2[]={
  196.    _cPurp , _cGreen, _cCyan , _cYell ,
  197.    _cPurp , _cPurp , _cGreen, _cYell ,
  198.    _cGreen, _cPurp , _cCyan , _cYell ,
  199.    _cPurp , _cCyan , _cGreen, _cYell ,
  200.  
  201.    _cPurp , _cYell , _cGreen, _cYell ,
  202.    _cPurp , _cYell , _cYell , _cYell ,
  203.    _cGreen, _cYell , _cYell , _cYell ,
  204.    _cYell , _cYell , _cYell , _cYell
  205.    };
  206. */
  207.    if ( conf.sound.ay_chip == SNDCHIP::CHIP_YM2203 ) {
  208.       for (int ayN = 0; ayN < max_ay; ayN++) {
  209.          for (int i = 0; i < 3; i++) {
  210.             for (int j = 0; j < 4; j++) {
  211.                unsigned v=ay[ayN].Chip2203->CH[i].SLOT[j].vol_out;
  212.                if (v>1023) v=1023;
  213.                unsigned c; //Alone Coder 0.36.7
  214.                for (/*int*/ c=0;c<16;c++)
  215.                   if (FMvols[c]>=v) break;
  216.                if ( (i == 2) && (((ay[ayN].Chip2203->OPN.ST.mode) & 0xc0) == 0x40) )
  217.                   paint_led(15-c, FMalg2[ay[ayN].Chip2203->CH[i].ALGO * 4 + FMslots[j]]);
  218.                else
  219.                   paint_led(15-c, FMalg1[ay[ayN].Chip2203->CH[i].ALGO * 4 + FMslots[j]]);
  220.             }
  221.          paint_led(0, 0);
  222.          }
  223.       }
  224.    } //Dexus
  225.  
  226.    #ifdef MOD_GS
  227.    if (sum || !conf.gs_type) return; // else show GS indicators
  228.    aypos = temp.led.ay; // reset y-pos, if nothing above
  229.    for (unsigned ch = 0; ch < 8; ch++)
  230.    {
  231.       unsigned v = gsleds[ch].level, a = gsleds[ch].attrib;
  232.       paint_led(v, u8(a));
  233.       paint_led(v, u8(a));
  234.       paint_led(0, 0);
  235.  
  236. #if 0
  237.       printf("{%2u}", v);
  238.       for(unsigned i = 0; i < v; i++)
  239.       {
  240.           printf("#");
  241.       }
  242.       printf("\n");
  243.    }
  244.    printf("-------------------------\n");
  245. #else
  246.    }
  247. #endif
  248.  
  249.    #endif
  250. }
  251. //=============================================================================
  252.  
  253.  
  254. //=============================================================================
  255. static void load_led()
  256. {
  257.     char ln[20]; unsigned char diskcolor = 0;
  258.  
  259. #ifdef GS_BASS
  260.     if(gs.loadmod)
  261.     {
  262.         text_i(temp.led.load, "", 0x0D);
  263.         gs.loadmod = 0;
  264.     }
  265.     else if(gs.loadfx)
  266.     {
  267.         sprintf(ln, "\x0D%d", gs.loadfx);
  268.         text_i(temp.led.load, ln, 0x0D);
  269.         gs.loadfx = 0;
  270.     }
  271.     else
  272. #endif
  273.         if(trdos_format)
  274.         {
  275.             diskcolor = (trdos_format < ROMLED_TIME * 3 / 4) ? 0x06 : 0x0E;
  276.             trdos_format--;
  277.         }
  278.         else if(trdos_save)
  279.         {
  280.             diskcolor = (trdos_save < ROMLED_TIME * 3 / 4) ? 0x02 : 0x0A;
  281.             trdos_save--;
  282.         }
  283.         else if(trdos_load)
  284.         {
  285.             diskcolor = (trdos_load < ROMLED_TIME * 3 / 4) ? 0x01 : 0x09;
  286.             trdos_load--;
  287.         }
  288.         else if(trdos_seek)
  289.         {
  290.             trdos_seek--;
  291.         }
  292.         else if(!comp.tape.stopped)
  293.         {
  294.             static unsigned char tapeled[11 * 2] =
  295.             {
  296.                 0x7F, 0xFE, 0x80, 0x01, 0x80, 0x01, 0x93, 0xC9, 0xAA, 0x55, 0x93, 0xC9,
  297.                 0x80, 0x01, 0x8F, 0xF1, 0x80, 0x01, 0xB5, 0xA9, 0xFF, 0xFF
  298.             };
  299.             const int tapecolor = 0x51;
  300.             for(unsigned i = 0; i < 11; i++)
  301.             {
  302.                 temp.led.load[pitch*i + 0] = tapeled[2 * i];
  303.                 temp.led.load[pitch*i + 1] = tapecolor;
  304.                 temp.led.load[pitch*i + 2] = tapeled[2 * i + 1];
  305.                 temp.led.load[pitch*i + 3] = tapecolor;
  306.             }
  307.             int time = (int)(temp.led.tape_started + tapeinfo[comp.tape.index].t_size - comp.t_states);
  308.             if(time < 0)
  309.             {
  310.                 find_tape_index(); time = 0;
  311.                 temp.led.tape_started = comp.t_states;
  312.                 unsigned char *ptr = tape_image + tapeinfo[comp.tape.index].pos;
  313.                 if(ptr == comp.tape.play_pointer && comp.tape.index)
  314.                 {
  315.                     comp.tape.index--;
  316.                     ptr = tape_image + tapeinfo[comp.tape.index].pos;
  317.                 }
  318.                 for(; ptr < comp.tape.play_pointer; ptr++)
  319.                 {
  320.                     temp.led.tape_started -= (tape_pulse[*ptr] & tape_pulse_mask);
  321.                 }
  322.             }
  323.             time /= (conf.frame * conf.intfq);
  324.             sprintf(ln, "%X:%02d", time / 60, time % 60);
  325.             text_i(temp.led.load + pitch * 12 - 2, ln, 0x0D);
  326.         }
  327.     if(diskcolor | trdos_seek)
  328.     {
  329.         if(diskcolor)
  330.         {
  331.             unsigned *ptr = (unsigned*)temp.led.load;
  332.             int i; //Alone Coder 0.36.7
  333.             for(/*int*/ i = 0; i < 7; i++, ptr = (unsigned*)((char*)ptr + pitch))
  334.             {
  335.                 *ptr = (*ptr & WORD4(0, 0xF0, 0, 0xF0)) | WORD4(0x3F, diskcolor, 0xFC, diskcolor);
  336.             }
  337.  
  338.             static unsigned char disk[] = { 0x38, 0x1C, 0x3B, 0x9C, 0x3B, 0x9C, 0x3B, 0x9C, 0x38, 0x1C };
  339.             for(i = 0; i < 5; i++, ptr = (unsigned*)((char*)ptr + pitch))
  340.             {
  341.                 *ptr = (*ptr & WORD4(0, 0xF0, 0, 0xF0)) | WORD4(disk[2 * i], diskcolor, disk[2 * i + 1], diskcolor);
  342.             }
  343.         }
  344.         if(comp.wd.seldrive->track != 0xFF)
  345.         {
  346.             sprintf(ln, "%02X", comp.wd.seldrive->track * 2 + comp.wd.side);
  347.             text_i(temp.led.load + pitch - 4, ln, 0x05 + (diskcolor & 8));
  348.         }
  349.     }
  350. }
  351. //=============================================================================
  352.  
  353.  
  354. //=============================================================================
  355. static unsigned p_frames = 1;
  356. static u64 led_updtime, p_time;
  357. static double p_fps;
  358. __inline void update_perf_led()
  359. {
  360.    u64 now = led_updtime - p_time;
  361.    if (now >= temp.cpufq) // єёЁхфэхэшх чр ёхъєэфє
  362.    {
  363.       p_fps = (p_frames * temp.cpufq) / double(now) + 0.005;
  364.       p_frames = 0;
  365.       p_time = led_updtime;
  366.    }
  367.    p_frames++;
  368. }
  369. //=============================================================================
  370.  
  371.  
  372. //=============================================================================
  373. static void perf_led()
  374. {
  375.    char bf[0x20]; unsigned PSZ;
  376.    if(conf.led.perf_t)
  377.    {
  378.        sprintf(bf, "%6u*%2.2f", cpu.haltpos ? cpu.haltpos : cpu.t, p_fps);
  379.        PSZ = 7;
  380.    }
  381.    else
  382.    {
  383.        sprintf(bf, "%2.2f fps", p_fps);
  384.        PSZ = 5;
  385.    }
  386.    text_i(temp.led.perf, bf, 0x0E);
  387.    if (cpu.haltpos) {
  388.       unsigned char *ptr = temp.led.perf + pitch*8;
  389.       unsigned xx; //Alone Coder 0.36.7
  390.       for (/*unsigned*/ xx = 0; xx < PSZ; xx++) *(unsigned short*)(ptr+xx*2) = 0x9A00;
  391.       unsigned mx = cpu.haltpos*PSZ*8/conf.frame;
  392.       for (xx = 1; xx < mx; xx++) ptr[(xx>>2)&0xFE] |= (0x80 >> (xx & 7));
  393.    }
  394. }
  395. //=============================================================================
  396.  
  397.  
  398. //=============================================================================
  399. static void input_led()
  400. {
  401.    if (input.kbdled != 0xFF) {
  402.       unsigned char k0 = 0x99, k1 = 0x9F, k2 = 0x90;
  403.       if(input.keymode == K_INPUT::KM_PASTE_HOLD)
  404.       {
  405.           k0 = 0xAA; k1 = 0xAF; k2 = 0xA0;
  406.       }
  407.       if(input.keymode == K_INPUT::KM_PASTE_RELEASE)
  408.       {
  409.           k0 = 0x22; k1 = 0x2F; k2 = 0x20;
  410.       }
  411.  
  412.       unsigned i; //Alone Coder 0.36.7
  413.       for (/*int*/ i = 0; i < 5; i++)
  414.          temp.led.input[1+i*2*pitch] = temp.led.input[3+i*2*pitch] = k0;
  415.       for(i = 0; i < 4; i++)
  416.       {
  417.           temp.led.input[pitch*(2 * i + 1)] = 0x7F;
  418.           temp.led.input[pitch*(2 * i + 1) + 2] = 0xFE;
  419.       }
  420.       temp.led.input[pitch*1+1] = (input.kbdled & 0x08)? k2 : k1;
  421.       temp.led.input[pitch*3+1] = (input.kbdled & 0x04)? k2 : k1;
  422.       temp.led.input[pitch*5+1] = (input.kbdled & 0x02)? k2 : k1;
  423.       temp.led.input[pitch*7+1] = (input.kbdled & 0x01)? k2 : k1;
  424.       temp.led.input[pitch*1+3] = (input.kbdled & 0x10)? k2 : k1;
  425.       temp.led.input[pitch*3+3] = (input.kbdled & 0x20)? k2 : k1;
  426.       temp.led.input[pitch*5+3] = (input.kbdled & 0x40)? k2 : k1;
  427.       temp.led.input[pitch*7+3] = (input.kbdled & 0x80)? k2 : k1;
  428.    }
  429.    static unsigned char joy[] =   { 0x10, 0x38, 0x1C, 0x1C, 0x1C, 0x1C, 0x08, 0x00, 0x7E, 0xFF, 0x00, 0xE7 };
  430.    static unsigned char mouse[] = { 0x0C, 0x12, 0x01, 0x79, 0xB5, 0xB5, 0xB5, 0xFC, 0xFC, 0xFC, 0xFC, 0x78 };
  431.    if(input.mouse_joy_led & 2)
  432.    {
  433.        for(size_t i = 0; i < sizeof joy; i++)
  434.        {
  435.            temp.led.input[4 + pitch * i] = joy[i];
  436.            temp.led.input[4 + pitch * i + 1] = (temp.led.input[4 + pitch * i + 1] & 0xF0) + 0x0F;
  437.        }
  438.    }
  439.    if(input.mouse_joy_led & 1)
  440.    {
  441.        for(size_t i = 0; i < sizeof mouse; i++)
  442.        {
  443.            temp.led.input[6 + pitch * i] = mouse[i];
  444.            temp.led.input[6 + pitch * i + 1] = (temp.led.input[6 + pitch * i + 1] & 0xF0) + 0x0F;
  445.        }
  446.    }
  447.    input.mouse_joy_led = 0; input.kbdled = 0xFF;
  448. }
  449. //=============================================================================
  450.  
  451.  
  452. //=============================================================================
  453. #ifdef MOD_MONITOR
  454. static void debug_led()
  455. {
  456.    unsigned char *ptr = temp.led.osw;
  457.    if (trace_rom | trace_ram) {
  458.       set_banks();
  459.       if (trace_rom) {
  460.          const unsigned char off = 0x01, on = 0x0C;
  461.          text_i(ptr + 2,           "B48", used_banks[(base_sos_rom - memory) / PAGE] ? on : off);
  462.          text_i(ptr + 8,           "DOS", used_banks[(base_dos_rom - memory) / PAGE] ? on : off);
  463.          text_i(ptr + pitch*8 + 2, "128", used_banks[(base_128_rom - memory) / PAGE] ? on : off);
  464.          text_i(ptr + pitch*8 + 8, "SYS", used_banks[(base_sys_rom - memory) / PAGE] ? on : off);
  465.          ptr += pitch*16;
  466.       }
  467.       if (trace_ram) {
  468.          unsigned num_rows = conf.ramsize/128;
  469.          unsigned j; //Alone Coder 0.36.7
  470.          for (unsigned  i = 0; i < num_rows; i++) {
  471.             char ln[9];
  472.             for (/*unsigned*/ j = 0; j < 8; j++)
  473.                ln[j] = used_banks[i*8+j]? '*' : '-';
  474.             ln[j] = 0;
  475.             text_i(ptr, ln, 0x0D);
  476.             ptr += pitch*8;
  477.          }
  478.       }
  479.       for (unsigned j = 0; j < MAX_PAGES; j++) used_banks[j] = 0;
  480.    }
  481.    for (unsigned w = 0; w < 4; w++) if (watch_enabled[w])
  482.    {
  483.       char bf[12]; sprintf(bf, "%8X", calc(&cpu, watch_script[w]));
  484.       text_i(ptr,bf,0x0F); ptr += pitch*8;
  485.    }
  486. }
  487. #endif
  488. //=============================================================================
  489.  
  490.  
  491.  
  492.  
  493.  
  494. #ifdef MOD_MEMBAND_LED
  495. //=============================================================================
  496.  
  497. static void show_highres_256_mband( unsigned char *dst)
  498. {
  499.     Z80 &cpu = CpuMgr.Cpu();
  500.     unsigned char band[ 256];
  501.     unsigned i;
  502.     unsigned char out_attr;
  503.  
  504.     unsigned start = 0x0000;
  505.     unsigned char *dst_at_start;
  506.     int line_cnt = 256;
  507.     unsigned char r;
  508.     unsigned char w;
  509.     unsigned char x;
  510.        
  511.     //-------------------------------------------------------------------------
  512.     while (line_cnt > 0)
  513.     {
  514.         dst_at_start = dst;
  515.  
  516.         //---------------------------------------------------------------------
  517.         //яюыюёюўъш юЄфхы ■∙шх 16╩ яю сюърь
  518.         if (    ((start & 0x3FFF) == 0x0000)    ||
  519.                 ((start & 0x3FFF) == 0x3F00)   
  520.          )
  521.         {
  522.             dst[ 0] |= 0b00011110;
  523.             dst[ 1] = (dst[1] & 0xF0) | 0x0B;  
  524.         }
  525.         //---------------------------------------------------------------------
  526.         dst += 2;
  527.         //---------------------------------------------------------------------
  528.         for (i = 0;    i < 256;    i++)
  529.         {
  530.             band[i] = cpu.membits[ start++];
  531.         }
  532.         //---------------------------------------------------------------------
  533.         for (unsigned p = 0;    p < 32;    p++, dst += 2)
  534.         {
  535.             r = 0;
  536.             w = 0;
  537.             x = 0;
  538.             //-----------------------------------------------------------------
  539.             // ёсюЁър 8 Єюўхъ т срщЄ
  540.             for (unsigned b = 0;    b < 8;    b++)
  541.             {
  542.                 r <<= 1;        // r *= 2;
  543.                 w <<= 1;        // w *= 2;
  544.                 x <<= 1;        // x *= 2;
  545.                 //-------------------------------------------------------------
  546.                 if (band[ p * 8 + b] & MEMBITS_R)       r |= 1;
  547.                 if (band[ p * 8 + b] & MEMBITS_W)       w |= 1;
  548.                 if (band[ p * 8 + b] & MEMBITS_X)       x |= 1;
  549.                 //-------------------------------------------------------------
  550.             }
  551.             //-----------------------------------------------------------------
  552.                
  553.             // чряшё№ срщЄ + ЎтхЄ (4.4 paper ink)
  554.             // dst[0] = r; dst[1] = 0x0C;       //100 green read      
  555.             // dst[0] = w; dst[1] = 0x0A;       //010 red write
  556.             // dst[0] = x; dst[1] = 0x0F;       //001 execute
  557.            
  558.             out_attr = 0x00;    //dst[1] = 0x00;
  559.             dst[ 0] = r | w | x;
  560.             //-----------------------------------------------------------------
  561.             if (r != 0)         out_attr |= 0x0C;       //100 green read      
  562.             if (w != 0)         out_attr |= 0x0A;       //010 red write
  563.             if (x != 0)         out_attr |= 0x09;       //001 blue execute
  564.             //-----------------------------------------------------------------
  565.             dst[1] = out_attr;
  566.         }
  567.         //---------------------------------------------------------------------
  568.         //яюыюёюўъш юЄфхы ■∙шх 16╩ яю сюърь
  569.         if (    ((start & 0x3FFF) == 0x0100) ||
  570.                 ((start & 0x3FFF) == 0x0000)   
  571.          )
  572.         {
  573.             dst[ 0] |= 0b01111000;
  574.             dst[ 1] = (dst[1] & 0xF0) | 0x0B;          
  575.         }
  576.         //---------------------------------------------------------------------
  577.         dst = dst_at_start + pitch;
  578.         line_cnt--;
  579.     }
  580.     //-------------------------------------------------------------------------
  581. }
  582. //=============================================================================
  583.  
  584.  
  585.  
  586. //=============================================================================
  587. static void show_mband(unsigned char *dst, unsigned start)
  588. {
  589.    
  590.     char xx[8];
  591.     sprintf( xx, "%02X", start >> 8);
  592.     text_i( dst, xx, 0x0B);
  593.     dst += 4;   //ЎшЇЁ√ ёыхтр
  594.  
  595.     Z80 &cpu = CpuMgr.Cpu();
  596.     unsigned char band[128];
  597.     unsigned i; //Alone Coder 0.36.7
  598.    
  599.     //printf("memband---------------------\n");
  600.     //ЄєЄ ЁрсюЄрхЄ ёЁрчє ш ърцф√щ ЇЁхщь
  601.    
  602.     if ((start & 0b0011'1111'1111'1111) == 0)
  603.    {
  604.         char ln[ 64];
  605.         cpu.BankNames( (start >> 14), ln);
  606.         text_i( dst + 36, ln, 0x0B, 2);         //ram rom
  607.    }
  608.    //-------------------------------------------------------------------------
  609.    for (/*unsigned*/ i = 0;    i < 128;    i++)
  610.    {
  611.         unsigned char res = 0;
  612.         //---------------------------------------------------------------------
  613.         for (unsigned q = 0;    q < conf.led.bandBpp;    q++)
  614.             res |= cpu.membits[ start++];
  615.         //---------------------------------------------------------------------
  616.         band[ i] = res; //ёсюЁър "єёЁхфэхээ√ї" 128 чэрўхэшщ
  617.    }
  618.    //-------------------------------------------------------------------------
  619.    for (unsigned p = 0;    p < 16;    p++, dst += 2)
  620.    {
  621.         unsigned char r = 0;
  622.         unsigned char w = 0;
  623.         unsigned char x = 0;
  624.         //---------------------------------------------------------------------
  625.         for (unsigned b = 0;    b < 8;    b++)
  626.         {
  627.             r <<= 1;    //r *= 2;
  628.             w <<= 1;    //w *= 2;
  629.             x <<= 1;    //x *= 2;
  630.             //-----------------------------------------------------------------
  631.             if (band[ p * 8 + b] & MEMBITS_R) r |= 1;
  632.             if (band[ p * 8 + b] & MEMBITS_W) w |= 1;
  633.             if (band[ p * 8 + b] & MEMBITS_X) x |= 1;
  634.             //-----------------------------------------------------------------
  635.         }
  636.         //-------------------------------------------------------------------------
  637.  
  638.         unsigned char t = (p && !(p & 3))  ?  0x7F :
  639.                                               0xFF;
  640.  
  641.         dst[ 0 * pitch] = t;    dst[ 0 * pitch + 1] = 0x9B;     //Ёрьър ?
  642.                                                
  643.         dst[ 1 * pitch] = r;    dst[ 1 * pitch + 1] = 0x1C;     //100 green read
  644.         dst[ 2 * pitch] = r;    dst[ 2 * pitch + 1] = 0x1C;
  645.                                                
  646.         dst[ 3 * pitch] = w;    dst[ 3 * pitch + 1] = 0x1A;     //010 red write
  647.         dst[ 4 * pitch] = w;    dst[ 4 * pitch + 1] = 0x1A;
  648.                                                
  649.         dst[ 5 * pitch] = x;    dst[ 5 * pitch + 1] = 0x1F;     //white execute
  650.         dst[ 6 * pitch] = x;    dst[ 6 * pitch + 1] = 0x1F;
  651.                                                
  652.         dst[ 7 * pitch] = t;    dst[ 7 * pitch + 1] = 0x9B;     //Ёрьър ?
  653.    }
  654.    //-------------------------------------------------------------------------
  655.    sprintf( xx, "%02X", (start - 1) >> 8);
  656.     text_i( dst, xx, 0x0B, 2);                  //ЎшЇЁ√ ёяЁртр    
  657.    //-------------------------------------------------------------------------
  658.    for (i = 0;    i < 8;    i++)
  659.    {
  660.         dst[ i * pitch] |= 0x80;
  661.         dst[ i * pitch - 17 * 2] |= 0x01;
  662.    }
  663.    //-------------------------------------------------------------------------
  664. }
  665. //=============================================================================
  666. static void memband_led()
  667. {
  668.    unsigned char *dst = temp.led.memband;  
  669.    //-------------------------------------------------------------------------
  670.    for (unsigned start = 0x0000;    start < 0x10000;    )
  671.    {
  672.         show_mband( dst, start);
  673.         start += conf.led.bandBpp * 128;
  674.         dst += 7 * pitch;                       // +10*pitch; т юЁшушэрых
  675.    }
  676.    //-------------------------------------------------------------------------
  677.    Z80 &cpu = CpuMgr.Cpu();
  678.    //-------------------------------------------------------------------------
  679.    for (unsigned i = 0;    i < 0x10000;    i++)
  680.         cpu.membits[ i] &= ripper | unsigned( ~(MEMBITS_R | MEMBITS_W | MEMBITS_X));
  681.    //-------------------------------------------------------------------------
  682. }
  683. //=============================================================================
  684.  
  685.  
  686. //=============================================================================
  687. static void memband_256_led()
  688. {
  689.    unsigned char *dst = temp.led.memband_256;
  690.    
  691.    show_highres_256_mband( dst);
  692.         //яхЁхьхёЄшЄ№ ё■фр!!!
  693.  
  694.    Z80 &cpu = CpuMgr.Cpu();
  695.    //-------------------------------------------------------------------------
  696.    for (unsigned i = 0;    i < 0x10000;    i++)
  697.         cpu.membits[ i] &= ripper | unsigned( ~(MEMBITS_R | MEMBITS_W | MEMBITS_X));
  698.    //-------------------------------------------------------------------------
  699. }
  700.  
  701. //=============================================================================
  702. #endif  // MOD_MEMBAND_LED
  703.  
  704. //=============================================================================
  705.  
  706. HANDLE hndKbdDev;
  707.  
  708. //=============================================================================
  709. void init_leds()
  710. {
  711.    DefineDosDevice( DDD_RAW_TARGET_PATH, "Kbd_unreal_spec", "\\Device\\KeyboardClass0");
  712.    hndKbdDev = CreateFile( "\\\\.\\Kbd_unreal_spec", GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
  713.    //-------------------------------------------------------------------------
  714.    if (hndKbdDev == INVALID_HANDLE_VALUE)
  715.    {
  716.       hndKbdDev = nullptr;
  717.       conf.led.flash_ay_kbd = 0;
  718.    }
  719.    //-------------------------------------------------------------------------
  720. }
  721. //=============================================================================
  722.  
  723.  
  724. //=============================================================================
  725. void done_leds()
  726. {
  727.    if (hndKbdDev)
  728.    {
  729.         DefineDosDevice( DDD_REMOVE_DEFINITION, "Kbd_unreal_spec", nullptr);
  730.         CloseHandle( hndKbdDev);
  731.         hndKbdDev = nullptr;
  732.    }
  733. }
  734. //=============================================================================
  735.  
  736.  
  737. //=============================================================================
  738. static void ay_kbd()
  739. {
  740.    static unsigned char pA, pB, pC;
  741.    static unsigned prev_keyled = -1U;
  742.  
  743.    KEYBOARD_INDICATOR_PARAMETERS InputBuffer;
  744.    InputBuffer.LedFlags = InputBuffer.UnitId = 0;
  745.    //-------------------------------------------------------------------------
  746.    if (ay[ 0].get_reg(  8) > pA) InputBuffer.LedFlags |= KEYBOARD_NUM_LOCK_ON;
  747.    if (ay[ 0].get_reg(  9) > pB) InputBuffer.LedFlags |= KEYBOARD_CAPS_LOCK_ON;
  748.    if (ay[ 0].get_reg( 10) > pC) InputBuffer.LedFlags |= KEYBOARD_SCROLL_LOCK_ON;
  749.    //-------------------------------------------------------------------------
  750.    pA = ay[ 0].get_reg(  8);
  751.    pB = ay[ 0].get_reg(  9);
  752.    pC = ay[ 0].get_reg( 10);
  753.  
  754.    DWORD xx;
  755.    //-------------------------------------------------------------------------
  756.    if (prev_keyled != InputBuffer.LedFlags)
  757.    {
  758.         prev_keyled = InputBuffer.LedFlags;
  759.         DeviceIoControl(  hndKbdDev,
  760.                           IOCTL_KEYBOARD_SET_INDICATORS,
  761.                           &InputBuffer,
  762.                           sizeof( KEYBOARD_INDICATOR_PARAMETERS),
  763.                           nullptr,
  764.                           0,
  765.                           &xx,
  766.                           nullptr
  767.                 );
  768.    }
  769.    //-------------------------------------------------------------------------
  770. }
  771. //=============================================================================
  772.  
  773.  
  774. //=============================================================================
  775. static void key_led()
  776. {
  777.    #define key_x 1U
  778.    #define key_y 1U
  779.    unsigned i; //Alone Coder 0.36.7
  780.    //-------------------------------------------------------------------------
  781.    for (/*int*/ i = 0;    i < 9;    i++)
  782.    {
  783.         text_16(  rbuf + (key_y + i) * pitch * 16 + key_x * 2,
  784.                   "                                 ",
  785.                   0x40
  786.              );
  787.    }
  788.    //-------------------------------------------------------------------------
  789.    static char ks[] = "cZXCVASDFGQWERT1234509876POIUYeLKJHssMNB";
  790.    //-------------------------------------------------------------------------
  791.    for (i = 0;    i < 8;    i++)
  792.    {
  793.         //---------------------------------------------------------------------
  794.         for (unsigned j = 0;    j < 5;    j++)
  795.         {
  796.             unsigned x;
  797.             unsigned y;
  798.             unsigned at;
  799.             //-----------------------------------------------------------------
  800.             if (i < 4)
  801.             {
  802.                 y = 7 - 2 * i + key_y;
  803.                 x = 3 * j + 2 + key_x;
  804.             }
  805.             //-----------------------------------------------------------------
  806.             else
  807.             {
  808.                 y = 2 * (i - 4) + 1 + key_y;
  809.                 x = 29 - 3 * j + key_x;
  810.             }
  811.             //-----------------------------------------------------------------
  812.             unsigned a = u8( ks[ i * 5 + j]) * 0x100U + u8(' ');
  813.             at = (input.kbd[ i] & (1 << j))  ?  0x07 :
  814.                                                 ( (input.rkbd[ i] & (1 << j))  ?  0xA0:
  815.                                                                                   0xD0
  816.                                                         );
  817.             text_16( rbuf + 2 * x + y * pitch * 16, (char*) &a, u8( at));
  818.      }
  819.   }
  820. }
  821. //=============================================================================
  822.  
  823.  
  824. //=============================================================================
  825. static void time_led()
  826. {
  827.    static u64 prev_time;
  828.    static char bf[ 8];
  829.    //-------------------------------------------------------------------------
  830.    if (led_updtime - prev_time > 5000)
  831.    {
  832.         prev_time = led_updtime;
  833.         SYSTEMTIME st;
  834.         GetLocalTime( &st);
  835.         sprintf( bf, "%2d:%02d", st.wHour, st.wMinute);
  836.    }
  837.    //-------------------------------------------------------------------------
  838.    text_i( temp.led.time, bf, 0x0D);
  839. }
  840. //=============================================================================
  841.  
  842.  
  843. //=============================================================================
  844. // ┬√ч√трхЄё  Ёрч т ърфЁ
  845. void showleds()
  846. {
  847.    led_updtime = rdtsc();
  848.    update_perf_led();
  849.    //-------------------------------------------------------------------------
  850.    if (temp.vidblock)
  851.         return;
  852.    //-------------------------------------------------------------------------
  853.    pitch = temp.scx/4;
  854.    //-------------------------------------------------------------------------
  855.    if (statcnt)
  856.    {
  857.         statcnt--;
  858.         text_i( rbuf + (((pitch / 2) - strlen( statusline) * 6 / 8) & 0xFE) + (temp.scy - 10) * pitch,
  859.                 statusline,
  860.                 0x09
  861.             );
  862.    }
  863.    //-------------------------------------------------------------------------
  864.    if (!conf.led.enabled)
  865.         return;
  866.    //-------------------------------------------------------------------------
  867.     if (temp.led.ay)    ay_led();
  868.     if (temp.led.perf)  perf_led();
  869.     if (temp.led.load)  load_led();
  870.     if (temp.led.input) input_led();
  871.     if (temp.led.time)  time_led();
  872.    //-------------------------------------------------------------------------
  873.    #ifdef MOD_MONITOR
  874.         if (temp.led.osw) debug_led();
  875.    #endif
  876.    //-------------------------------------------------------------------------
  877.  
  878.  
  879.    // dbgchk - ╧Ёшчэръ эрышўш  ръЄштэ√ї сЁхъяюшэЄют
  880.    // isbrk(cpu) - is there breakpoints active or any other reason to use debug z80 loop?
  881.    
  882.    
  883.    #ifdef MOD_MEMBAND_LED
  884.    //-------------------------------------------------------------------------
  885.         if (temp.led.memband)
  886.         {      
  887.             memband_led();
  888.             cpu.dbgchk |= 1;    // фы  force memory band [NS]
  889.         }
  890.         //---------------------------------------------------------------------
  891.         else if (temp.led.memband_256) // [NS]
  892.         {
  893.             memband_256_led(); 
  894.             cpu.dbgchk |= 1;    // фы  force memory band [NS]
  895.         }
  896.    //-------------------------------------------------------------------------
  897.    #endif
  898.    //-------------------------------------------------------------------------
  899.     if (conf.led.flash_ay_kbd && hndKbdDev)     ay_kbd();
  900.     if (input.keymode == K_INPUT::KM_KEYSTICK)  key_led();
  901.    //-------------------------------------------------------------------------
  902. }
  903. //=============================================================================
  904.