Top secrets sources NedoPC pentevo

Rev

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

#include "std.h"

#include "emul.h"
#include "vars.h"
#include "font.h"
#include "font16.h"
#include "gs.h"
#include "tape.h"
#include "draw.h"
#include "debug.h"
#include "dbgbpx.h"
#include "memory.h"
#include "leds.h"

#include "util.h"

static unsigned pitch;

//=============================================================================
void text_i(unsigned char *dst, const char *text, unsigned char ink, unsigned off)
{
   ink &= 0x0F;
   for (const u8 *x = (const u8*)text; *x; x++) {
      unsigned char *d0 = dst;
      for (unsigned y = 0; y < 8; y++) {
         unsigned char byte = font[(*x)*8+y];
         d0[0] = (byte >> off) + (d0[0] & ~(0xFC >> off));
         d0[1] = (d0[1] & 0xF0) + ink;
         if (off > 2) {
            d0[2] = u8((byte << (8-off)) + (d0[2] & ~(0xFC << (8-off))));
            d0[3] = (d0[3] & 0xF0) + ink;
         }
         d0 += pitch;
      }
      off += 6;
      if(off & 8)
      {
          off -= 8;
          dst += 2;
      }
   }
}
//=============================================================================


//=============================================================================
static void text_16(unsigned char *dst, const char *text, unsigned char attr)
{
    for(; *text; text++, dst += 2)
    {
        for(unsigned y = 0; y < 16; y++)
        {
            dst[y*pitch] = font16[16 * *(const u8*)text + y];
            dst[y*pitch + 1] = attr;
        }
    }
}
//=============================================================================


//=============================================================================
static unsigned char *aypos;
static void paint_led(unsigned level, unsigned char at)
{
   if (level) {
       if(level > 15)
       {
           level = 15; at = 0x0E;
       }
      unsigned mask = (0xFFFF0000 >> level) & 0xFFFF;
      aypos[0] = u8(mask >> 8);
      aypos[2] = (unsigned char)mask;
      aypos[1] = (aypos[1] & 0xF0) + at;
      aypos[3] = (aypos[3] & 0xF0) + at;
   }
   aypos += pitch;
}
//=============================================================================


//=============================================================================
static void ay_led()
{
   aypos = temp.led.ay;
   unsigned char sum=0;
                                //ïîìåíÿòü öâåòà ÷òîá íå êîíôëèêòîâàëè ñ ïàëèòðîé!
//tone          áåëûé
//øóì           æåëòûé
//îãèáàþùàÿ     çåëåíûé
   int max_ay = (conf.sound.ay_scheme > AY_SCHEME_PSEUDO)? 2 : 1;
   for (int n_ay = 0; n_ay < max_ay; n_ay++)    //AY-êè
   {
      for (unsigned i = 0; i < 3; i++)  //3 channels
      {
         unsigned char r_mix = ay[n_ay].get_reg(7);
         unsigned char tone = (r_mix >> i) & 1,
                       noise = (r_mix >> (i+3)) & 1;
         unsigned char c1 = 0, c2 = 0;
         unsigned char v = ay[n_ay].get_reg(i+8);
         
         
         c1 = 0x01;//blue       //07;           //DAC MODE      //NS
         c2 = 0x0D;//cyan        //0B; //09;   
         
         //tone
         if (!tone) c1 = c2 = 0x0F;     //áåëûé
         
         //noise
         if (!noise) c2 = 0x0E;         //æåëòûé
         

        if (v & 0x10)
        {
            //envelope
            //âèäèìî òóò ïðÿìîå ÷òåíèå îãèáàþùå
            unsigned r_envT = ay[n_ay].get_reg(11) + 0x100*ay[n_ay].get_reg(12);
            if (r_envT < 0x400)
            {
               v = (3-(r_envT>>3)) & 0x0F;
               if (!v) v = 6;
            }
            else
            {
                v = u8(ay[n_ay].get_env()/2);
            }
            c1 = 0x0C;
        }
        else
        {
                //tone
                v &= 0x0F;      //áåëûé
                //c1 = 0x03;    //òåñò
                                //íàâåðíîå îò ñþäà ìîæíî ïîôèêñèòü
                                //ñòàðûé âàðèàíò öâåòà øóìà
        }
         
         if (!c1) c1 = c2;
         if (!c2) c2 = c1;
         if (!c1) v = 0;
         
         sum |= v;
         paint_led(v, c1);
         paint_led(v, c2);
         paint_led(0, 0);
      }
   }
//-----------------------------------------------------------------------------
   const unsigned FMvols[]={4,9,15,23,35,48,70,105,140,195,243,335,452,608,761,1023};
   #define _cBlue 0x09
   #define _cRed 0x0a
   #define _cPurp 0x0b
   #define _cGreen 0x0c
   #define _cCyan 0x0d
   #define _cYell 0x0e
   #define _cWhite 0x0f

   const u8 FMalg1[]={
   _cBlue , _cPurp , _cGreen, _cWhite,
   _cPurp , _cPurp , _cGreen, _cWhite,
   _cGreen, _cPurp , _cGreen, _cWhite,
   _cPurp , _cGreen, _cGreen, _cWhite,

   _cGreen, _cWhite, _cGreen, _cWhite,
   _cPurp , _cWhite, _cWhite, _cWhite,
   _cGreen, _cWhite, _cWhite, _cWhite,
   _cWhite, _cWhite, _cWhite, _cWhite
   };

   const u8 FMalg2[]={
   _cBlue , _cPurp , _cGreen, _cYell ,
   _cPurp , _cPurp , _cGreen, _cYell ,
   _cGreen, _cPurp , _cGreen, _cYell ,
   _cPurp , _cGreen, _cGreen, _cYell ,

   _cGreen, _cYell , _cGreen, _cYell ,
   _cPurp , _cYell , _cYell , _cYell ,
   _cGreen, _cYell , _cYell , _cYell ,
   _cYell , _cYell , _cYell , _cYell
   };

   const int FMslots[]={0,2,1,3};
/*
   const int FMalg1[]={
   _cPurp , _cGreen, _cCyan , _cWhite,
   _cPurp , _cPurp , _cGreen, _cWhite,
   _cGreen, _cPurp , _cCyan , _cWhite,
   _cPurp , _cCyan , _cGreen, _cWhite,

   _cPurp , _cWhite, _cGreen, _cWhite,
   _cPurp , _cWhite, _cWhite, _cWhite,
   _cGreen, _cWhite, _cWhite, _cWhite,
   _cWhite, _cWhite, _cWhite, _cWhite
   };

   const int FMalg2[]={
   _cPurp , _cGreen, _cCyan , _cYell ,
   _cPurp , _cPurp , _cGreen, _cYell ,
   _cGreen, _cPurp , _cCyan , _cYell ,
   _cPurp , _cCyan , _cGreen, _cYell ,

   _cPurp , _cYell , _cGreen, _cYell ,
   _cPurp , _cYell , _cYell , _cYell ,
   _cGreen, _cYell , _cYell , _cYell ,
   _cYell , _cYell , _cYell , _cYell
   };
*/

   if ( conf.sound.ay_chip == SNDCHIP::CHIP_YM2203 ) {
      for (int ayN = 0; ayN < max_ay; ayN++) {
         for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 4; j++) {
               unsigned v=ay[ayN].Chip2203->CH[i].SLOT[j].vol_out;
               if (v>1023) v=1023;
               unsigned c; //Alone Coder 0.36.7
               for (/*int*/ c=0;c<16;c++)
                  if (FMvols[c]>=v) break;
               if ( (i == 2) && (((ay[ayN].Chip2203->OPN.ST.mode) & 0xc0) == 0x40) )
                  paint_led(15-c, FMalg2[ay[ayN].Chip2203->CH[i].ALGO * 4 + FMslots[j]]);
               else
                  paint_led(15-c, FMalg1[ay[ayN].Chip2203->CH[i].ALGO * 4 + FMslots[j]]);
            }
         paint_led(0, 0);
         }
      }
   } //Dexus

   #ifdef MOD_GS
   if (sum || !conf.gs_type) return; // else show GS indicators
   aypos = temp.led.ay; // reset y-pos, if nothing above
   for (unsigned ch = 0; ch < 8; ch++)
   {
      unsigned v = gsleds[ch].level, a = gsleds[ch].attrib;
      paint_led(v, u8(a));
      paint_led(v, u8(a));
      paint_led(0, 0);

#if 0
      printf("{%2u}", v);
      for(unsigned i = 0; i < v; i++)
      {
          printf("#");
      }
      printf("\n");
   }
   printf("-------------------------\n");
#else
   }
#endif

   #endif
}
//=============================================================================


//=============================================================================
static void load_led()
{
    char ln[20]; unsigned char diskcolor = 0;

#ifdef GS_BASS
    if(gs.loadmod)
    {
        text_i(temp.led.load, "", 0x0D);
        gs.loadmod = 0;
    }
    else if(gs.loadfx)
    {
        sprintf(ln, "\x0D%d", gs.loadfx);
        text_i(temp.led.load, ln, 0x0D);
        gs.loadfx = 0;
    }
    else
#endif
        if(trdos_format)
        {
            diskcolor = (trdos_format < ROMLED_TIME * 3 / 4) ? 0x06 : 0x0E;
            trdos_format--;
        }
        else if(trdos_save)
        {
            diskcolor = (trdos_save < ROMLED_TIME * 3 / 4) ? 0x02 : 0x0A;
            trdos_save--;
        }
        else if(trdos_load)
        {
            diskcolor = (trdos_load < ROMLED_TIME * 3 / 4) ? 0x01 : 0x09;
            trdos_load--;
        }
        else if(trdos_seek)
        {
            trdos_seek--;
        }
        else if(!comp.tape.stopped)
        {
            static unsigned char tapeled[11 * 2] =
            {
                0x7F, 0xFE, 0x80, 0x01, 0x80, 0x01, 0x93, 0xC9, 0xAA, 0x55, 0x93, 0xC9,
                0x80, 0x01, 0x8F, 0xF1, 0x80, 0x01, 0xB5, 0xA9, 0xFF, 0xFF
            };
            const int tapecolor = 0x51;
            for(unsigned i = 0; i < 11; i++)
            {
                temp.led.load[pitch*i + 0] = tapeled[2 * i];
                temp.led.load[pitch*i + 1] = tapecolor;
                temp.led.load[pitch*i + 2] = tapeled[2 * i + 1];
                temp.led.load[pitch*i + 3] = tapecolor;
            }
            int time = (int)(temp.led.tape_started + tapeinfo[comp.tape.index].t_size - comp.t_states);
            if(time < 0)
            {
                find_tape_index(); time = 0;
                temp.led.tape_started = comp.t_states;
                unsigned char *ptr = tape_image + tapeinfo[comp.tape.index].pos;
                if(ptr == comp.tape.play_pointer && comp.tape.index)
                {
                    comp.tape.index--;
                    ptr = tape_image + tapeinfo[comp.tape.index].pos;
                }
                for(; ptr < comp.tape.play_pointer; ptr++)
                {
                    temp.led.tape_started -= (tape_pulse[*ptr] & tape_pulse_mask);
                }
            }
            time /= (conf.frame * conf.intfq);
            sprintf(ln, "%X:%02d", time / 60, time % 60);
            text_i(temp.led.load + pitch * 12 - 2, ln, 0x0D);
        }
    if(diskcolor | trdos_seek)
    {
        if(diskcolor)
        {
            unsigned *ptr = (unsigned*)temp.led.load;
            int i; //Alone Coder 0.36.7
            for(/*int*/ i = 0; i < 7; i++, ptr = (unsigned*)((char*)ptr + pitch))
            {
                *ptr = (*ptr & WORD4(0, 0xF0, 0, 0xF0)) | WORD4(0x3F, diskcolor, 0xFC, diskcolor);
            }

            static unsigned char disk[] = { 0x38, 0x1C, 0x3B, 0x9C, 0x3B, 0x9C, 0x3B, 0x9C, 0x38, 0x1C };
            for(i = 0; i < 5; i++, ptr = (unsigned*)((char*)ptr + pitch))
            {
                *ptr = (*ptr & WORD4(0, 0xF0, 0, 0xF0)) | WORD4(disk[2 * i], diskcolor, disk[2 * i + 1], diskcolor);
            }
        }
        if(comp.wd.seldrive->track != 0xFF)
        {
            sprintf(ln, "%02X", comp.wd.seldrive->track * 2 + comp.wd.side);
            text_i(temp.led.load + pitch - 4, ln, 0x05 + (diskcolor & 8));
        }
    }
}
//=============================================================================


//=============================================================================
static unsigned p_frames = 1;
static u64 led_updtime, p_time;
static double p_fps;
__inline void update_perf_led()
{
   u64 now = led_updtime - p_time;
   if (now >= temp.cpufq) // óñðåäíåíèå çà ñåêóíäó
   {
      p_fps = (p_frames * temp.cpufq) / double(now) + 0.005;
      p_frames = 0;
      p_time = led_updtime;
   }
   p_frames++;
}
//=============================================================================


//=============================================================================
static void perf_led()
{
   char bf[0x20]; unsigned PSZ;
   if(conf.led.perf_t)
   {
       sprintf(bf, "%6u*%2.2f", cpu.haltpos ? cpu.haltpos : cpu.t, p_fps);
       PSZ = 7;
   }
   else
   {
       sprintf(bf, "%2.2f fps", p_fps);
       PSZ = 5;
   }
   text_i(temp.led.perf, bf, 0x0E);
   if (cpu.haltpos) {
      unsigned char *ptr = temp.led.perf + pitch*8;
      unsigned xx; //Alone Coder 0.36.7
      for (/*unsigned*/ xx = 0; xx < PSZ; xx++) *(unsigned short*)(ptr+xx*2) = 0x9A00;
      unsigned mx = cpu.haltpos*PSZ*8/conf.frame;
      for (xx = 1; xx < mx; xx++) ptr[(xx>>2)&0xFE] |= (0x80 >> (xx & 7));
   }
}
//=============================================================================


//=============================================================================
static void input_led()
{
   if (input.kbdled != 0xFF) {
      unsigned char k0 = 0x99, k1 = 0x9F, k2 = 0x90;
      if(input.keymode == K_INPUT::KM_PASTE_HOLD)
      {
          k0 = 0xAA; k1 = 0xAF; k2 = 0xA0;
      }
      if(input.keymode == K_INPUT::KM_PASTE_RELEASE)
      {
          k0 = 0x22; k1 = 0x2F; k2 = 0x20;
      }

      unsigned i; //Alone Coder 0.36.7
      for (/*int*/ i = 0; i < 5; i++)
         temp.led.input[1+i*2*pitch] = temp.led.input[3+i*2*pitch] = k0;
      for(i = 0; i < 4; i++)
      {
          temp.led.input[pitch*(2 * i + 1)] = 0x7F;
          temp.led.input[pitch*(2 * i + 1) + 2] = 0xFE;
      }
      temp.led.input[pitch*1+1] = (input.kbdled & 0x08)? k2 : k1;
      temp.led.input[pitch*3+1] = (input.kbdled & 0x04)? k2 : k1;
      temp.led.input[pitch*5+1] = (input.kbdled & 0x02)? k2 : k1;
      temp.led.input[pitch*7+1] = (input.kbdled & 0x01)? k2 : k1;
      temp.led.input[pitch*1+3] = (input.kbdled & 0x10)? k2 : k1;
      temp.led.input[pitch*3+3] = (input.kbdled & 0x20)? k2 : k1;
      temp.led.input[pitch*5+3] = (input.kbdled & 0x40)? k2 : k1;
      temp.led.input[pitch*7+3] = (input.kbdled & 0x80)? k2 : k1;
   }
   static unsigned char joy[] =   { 0x10, 0x38, 0x1C, 0x1C, 0x1C, 0x1C, 0x08, 0x00, 0x7E, 0xFF, 0x00, 0xE7 };
   static unsigned char mouse[] = { 0x0C, 0x12, 0x01, 0x79, 0xB5, 0xB5, 0xB5, 0xFC, 0xFC, 0xFC, 0xFC, 0x78 };
   if(input.mouse_joy_led & 2)
   {
       for(size_t i = 0; i < sizeof joy; i++)
       {
           temp.led.input[4 + pitch * i] = joy[i];
           temp.led.input[4 + pitch * i + 1] = (temp.led.input[4 + pitch * i + 1] & 0xF0) + 0x0F;
       }
   }
   if(input.mouse_joy_led & 1)
   {
       for(size_t i = 0; i < sizeof mouse; i++)
       {
           temp.led.input[6 + pitch * i] = mouse[i];
           temp.led.input[6 + pitch * i + 1] = (temp.led.input[6 + pitch * i + 1] & 0xF0) + 0x0F;
       }
   }
   input.mouse_joy_led = 0; input.kbdled = 0xFF;
}
//=============================================================================


//=============================================================================
#ifdef MOD_MONITOR
static void debug_led()
{
   unsigned char *ptr = temp.led.osw;
   if (trace_rom | trace_ram) {
      set_banks();
      if (trace_rom) {
         const unsigned char off = 0x01, on = 0x0C;
         text_i(ptr + 2,           "B48", used_banks[(base_sos_rom - memory) / PAGE] ? on : off);
         text_i(ptr + 8,           "DOS", used_banks[(base_dos_rom - memory) / PAGE] ? on : off);
         text_i(ptr + pitch*8 + 2, "128", used_banks[(base_128_rom - memory) / PAGE] ? on : off);
         text_i(ptr + pitch*8 + 8, "SYS", used_banks[(base_sys_rom - memory) / PAGE] ? on : off);
         ptr += pitch*16;
      }
      if (trace_ram) {
         unsigned num_rows = conf.ramsize/128;
         unsigned j; //Alone Coder 0.36.7
         for (unsigned  i = 0; i < num_rows; i++) {
            char ln[9];
            for (/*unsigned*/ j = 0; j < 8; j++)
               ln[j] = used_banks[i*8+j]? '*' : '-';
            ln[j] = 0;
            text_i(ptr, ln, 0x0D);
            ptr += pitch*8;
         }
      }
      for (unsigned j = 0; j < MAX_PAGES; j++) used_banks[j] = 0;
   }
   for (unsigned w = 0; w < 4; w++) if (watch_enabled[w])
   {
      char bf[12]; sprintf(bf, "%8X", calc(&cpu, watch_script[w]));
      text_i(ptr,bf,0x0F); ptr += pitch*8;
   }
}
#endif
//=============================================================================





#ifdef MOD_MEMBAND_LED
//=============================================================================

static void show_highres_256_mband( unsigned char *dst)
{
    Z80 &cpu = CpuMgr.Cpu();
    unsigned char band[ 256];
    unsigned i;
    unsigned char out_attr;

    unsigned start = 0x0000;
    unsigned char *dst_at_start;
    int line_cnt = 256;
    unsigned char r;
    unsigned char w;
    unsigned char x;
       
    //-------------------------------------------------------------------------
    while (line_cnt > 0)
    {
        dst_at_start = dst;
 
        //---------------------------------------------------------------------
        //ïîëîñî÷êè îòäåëÿþùèå 16Ê ïî áîêàì
        if (    ((start & 0x3FFF) == 0x0000)    ||
                ((start & 0x3FFF) == 0x3F00)   
         )
        {
            dst[ 0] |= 0b00011110;
            dst[ 1] = (dst[1] & 0xF0) | 0x0B;  
        }
        //---------------------------------------------------------------------
        dst += 2;
        //---------------------------------------------------------------------
        for (i = 0;    i < 256;    i++)
        {
            band[i] = cpu.membits[ start++];
        }
        //---------------------------------------------------------------------
        for (unsigned p = 0;    p < 32;    p++, dst += 2)
        {
            r = 0;
            w = 0;
            x = 0;
            //-----------------------------------------------------------------
            // ñáîðêà 8 òî÷åê â áàéò
            for (unsigned b = 0;    b < 8;    b++)
            {
                r <<= 1;        // r *= 2;
                w <<= 1;        // w *= 2;
                x <<= 1;        // x *= 2;
                //-------------------------------------------------------------
                if (band[ p * 8 + b] & MEMBITS_R)       r |= 1;
                if (band[ p * 8 + b] & MEMBITS_W)       w |= 1;
                if (band[ p * 8 + b] & MEMBITS_X)       x |= 1;
                //-------------------------------------------------------------
            }
            //-----------------------------------------------------------------
               
            // çàïèñü áàéò + öâåò (4.4 paper ink)
            // dst[0] = r; dst[1] = 0x0C;       //100 green read      
            // dst[0] = w; dst[1] = 0x0A;       //010 red write
            // dst[0] = x; dst[1] = 0x0F;       //001 execute
           
            out_attr = 0x00;    //dst[1] = 0x00;
            dst[ 0] = r | w | x;
            //-----------------------------------------------------------------
            if (r != 0)         out_attr |= 0x0C;       //100 green read      
            if (w != 0)         out_attr |= 0x0A;       //010 red write
            if (x != 0)         out_attr |= 0x09;       //001 blue execute
            //-----------------------------------------------------------------
            dst[1] = out_attr;
        }
        //---------------------------------------------------------------------
        //ïîëîñî÷êè îòäåëÿþùèå 16Ê ïî áîêàì
        if (    ((start & 0x3FFF) == 0x0100) ||
                ((start & 0x3FFF) == 0x0000)   
         )
        {
            dst[ 0] |= 0b01111000;
            dst[ 1] = (dst[1] & 0xF0) | 0x0B;          
        }
        //---------------------------------------------------------------------
        dst = dst_at_start + pitch;
        line_cnt--;
    }
    //-------------------------------------------------------------------------
}
//=============================================================================



//=============================================================================
static void show_mband(unsigned char *dst, unsigned start)
{
   
    char xx[8];
    sprintf( xx, "%02X", start >> 8);
    text_i( dst, xx, 0x0B);
    dst += 4;   //öèôðû ñëåâà

    Z80 &cpu = CpuMgr.Cpu();
    unsigned char band[128];
    unsigned i; //Alone Coder 0.36.7
   
    //printf("memband---------------------\n");
    //òóò ðàáîòàåò ñðàçó è êàæäûé ôðåéì
   
    if ((start & 0b0011'1111'1111'1111) == 0)
    {
        char ln[ 64];
        cpu.BankNames( (start >> 14), ln);
        text_i( dst + 36, ln, 0x0B, 2);         //ram rom
    }
    //-------------------------------------------------------------------------
    for (/*unsigned*/ i = 0;    i < 128;    i++)
    {
        unsigned char res = 0;
        //---------------------------------------------------------------------
        for (unsigned q = 0;    q < conf.led.bandBpp;    q++)
            res |= cpu.membits[ start++];
        //---------------------------------------------------------------------
        band[ i] = res; //ñáîðêà "óñðåäíåííûõ" 128 çíà÷åíèé
    }
    //-------------------------------------------------------------------------
    for (unsigned p = 0;    p < 16;    p++, dst += 2)
    {
        unsigned char r = 0;
        unsigned char w = 0;
        unsigned char x = 0;
        //---------------------------------------------------------------------
        for (unsigned b = 0;    b < 8;    b++)
        {
            r <<= 1;    //r *= 2;
            w <<= 1;    //w *= 2;
            x <<= 1;    //x *= 2;
            //-----------------------------------------------------------------
            if (band[ p * 8 + b] & MEMBITS_R) r |= 1;
            if (band[ p * 8 + b] & MEMBITS_W) w |= 1;
            if (band[ p * 8 + b] & MEMBITS_X) x |= 1;
            //-----------------------------------------------------------------
        }
        //-------------------------------------------------------------------------

        unsigned char t = (p && !(p & 3))  ?  0x7F :
                                              0xFF;

        dst[ 0 * pitch] = t;    dst[ 0 * pitch + 1] = 0x9B;     //ðàìêà ?
                                                 
        dst[ 1 * pitch] = r;    dst[ 1 * pitch + 1] = 0x1C;     //100 green read
        dst[ 2 * pitch] = r;    dst[ 2 * pitch + 1] = 0x1C;
                                                 
        dst[ 3 * pitch] = w;    dst[ 3 * pitch + 1] = 0x1A;     //010 red write
        dst[ 4 * pitch] = w;    dst[ 4 * pitch + 1] = 0x1A;
                                                 
        dst[ 5 * pitch] = x;    dst[ 5 * pitch + 1] = 0x1F;     //white execute
        dst[ 6 * pitch] = x;    dst[ 6 * pitch + 1] = 0x1F;
                                                 
        dst[ 7 * pitch] = t;    dst[ 7 * pitch + 1] = 0x9B;     //ðàìêà ?
    }
    //-------------------------------------------------------------------------
    sprintf( xx, "%02X", (start - 1) >> 8);
    text_i( dst, xx, 0x0B, 2);                  //öèôðû ñïðàâà    
    //-------------------------------------------------------------------------
    for (i = 0;    i < 8;    i++)
    {
        dst[ i * pitch] |= 0x80;
        dst[ i * pitch - 17 * 2] |= 0x01;
    }
    //-------------------------------------------------------------------------
}
//=============================================================================
static void memband_led()
{
    unsigned char *dst = temp.led.memband;  
    //-------------------------------------------------------------------------
    for (unsigned start = 0x0000;    start < 0x10000;    )
    {
        show_mband( dst, start);
        start += conf.led.bandBpp * 128;
        dst += 7 * pitch;                       // +10*pitch; â îðèãèíàëå
    }
    //-------------------------------------------------------------------------
    Z80 &cpu = CpuMgr.Cpu();
    //-------------------------------------------------------------------------
    for (unsigned i = 0;    i < 0x10000;    i++)
        cpu.membits[ i] &= ripper | unsigned( ~(MEMBITS_R | MEMBITS_W | MEMBITS_X));
    //-------------------------------------------------------------------------
}
//=============================================================================


//=============================================================================
static void memband_256_led()
{
    unsigned char *dst = temp.led.memband_256;
   
    show_highres_256_mband( dst);
        //ïåðåìåñòèòü ñþäà!!!

    Z80 &cpu = CpuMgr.Cpu();
    //-------------------------------------------------------------------------
    for (unsigned i = 0;    i < 0x10000;    i++)
        cpu.membits[ i] &= ripper | unsigned( ~(MEMBITS_R | MEMBITS_W | MEMBITS_X));
    //-------------------------------------------------------------------------
}

//=============================================================================
#endif  // MOD_MEMBAND_LED

//=============================================================================

HANDLE hndKbdDev;

//=============================================================================
void init_leds()
{
    DefineDosDevice( DDD_RAW_TARGET_PATH, "Kbd_unreal_spec", "\\Device\\KeyboardClass0");
    hndKbdDev = CreateFile( "\\\\.\\Kbd_unreal_spec", GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
    //-------------------------------------------------------------------------
    if (hndKbdDev == INVALID_HANDLE_VALUE)
    {
       hndKbdDev = nullptr;
       conf.led.flash_ay_kbd = 0;
    }
    //-------------------------------------------------------------------------
}
//=============================================================================


//=============================================================================
void done_leds()
{
    if (hndKbdDev)
    {
        DefineDosDevice( DDD_REMOVE_DEFINITION, "Kbd_unreal_spec", nullptr);
        CloseHandle( hndKbdDev);
        hndKbdDev = nullptr;
    }
}
//=============================================================================


//=============================================================================
static void ay_kbd()
{
    static unsigned char pA, pB, pC;
    static unsigned prev_keyled = -1U;

    KEYBOARD_INDICATOR_PARAMETERS InputBuffer;
    InputBuffer.LedFlags = InputBuffer.UnitId = 0;
    //-------------------------------------------------------------------------
    if (ay[ 0].get_reg(  8) > pA) InputBuffer.LedFlags |= KEYBOARD_NUM_LOCK_ON;
    if (ay[ 0].get_reg(  9) > pB) InputBuffer.LedFlags |= KEYBOARD_CAPS_LOCK_ON;
    if (ay[ 0].get_reg( 10) > pC) InputBuffer.LedFlags |= KEYBOARD_SCROLL_LOCK_ON;
    //-------------------------------------------------------------------------
    pA = ay[ 0].get_reg(  8);
    pB = ay[ 0].get_reg(  9);
    pC = ay[ 0].get_reg( 10);

    DWORD xx;
    //-------------------------------------------------------------------------
    if (prev_keyled != InputBuffer.LedFlags)
    {
        prev_keyled = InputBuffer.LedFlags;
        DeviceIoControl(  hndKbdDev,
                          IOCTL_KEYBOARD_SET_INDICATORS,
                          &InputBuffer,
                          sizeof( KEYBOARD_INDICATOR_PARAMETERS),
                          nullptr,
                          0,
                          &xx,
                          nullptr
                );
    }
    //-------------------------------------------------------------------------
}
//=============================================================================


//=============================================================================
static void key_led()
{
    #define key_x 1U
    #define key_y 1U
    unsigned i; //Alone Coder 0.36.7
    //-------------------------------------------------------------------------
    for (/*int*/ i = 0;    i < 9;    i++)
    {
        text_16(  rbuf + (key_y + i) * pitch * 16 + key_x * 2,
                  "                                 ",
                  0x40
             );
    }
    //-------------------------------------------------------------------------
    static char ks[] = "cZXCVASDFGQWERT1234509876POIUYeLKJHssMNB";
    //-------------------------------------------------------------------------
    for (i = 0;    i < 8;    i++)
    {
        //---------------------------------------------------------------------
        for (unsigned j = 0;    j < 5;    j++)
        {
            unsigned x;
            unsigned y;
            unsigned at;
            //-----------------------------------------------------------------
            if (i < 4)
            {
                y = 7 - 2 * i + key_y;
                x = 3 * j + 2 + key_x;
            }
            //-----------------------------------------------------------------
            else
            {
                y = 2 * (i - 4) + 1 + key_y;
                x = 29 - 3 * j + key_x;
            }
            //-----------------------------------------------------------------
            unsigned a = u8( ks[ i * 5 + j]) * 0x100U + u8('
');
            at = (input.kbd[ i] & (1 << j))  ?  0x07 :
                                                ( (input.rkbd[ i] & (1 << j))  ?  0xA0:
                                                                                  0xD0
                                                        );
            text_16( rbuf + 2 * x + y * pitch * 16, (char*) &a, u8( at));
      }
   }
}
//=============================================================================


//=============================================================================
static void time_led()
{
    static u64 prev_time;
    static char bf[ 8];
    //-------------------------------------------------------------------------
    if (led_updtime - prev_time > 5000)
    {
        prev_time = led_updtime;
        SYSTEMTIME st;
        GetLocalTime( &st);
        sprintf( bf, "%2d:%02d", st.wHour, st.wMinute);
    }
    //-------------------------------------------------------------------------
    text_i( temp.led.time, bf, 0x0D);
}
//=============================================================================


//=============================================================================
// Âûçûâàåòñÿ ðàç â êàäð
void showleds()
{
    led_updtime = rdtsc();
    update_perf_led();
    //-------------------------------------------------------------------------
    if (temp.vidblock)
        return;
    //-------------------------------------------------------------------------
    pitch = temp.scx/4;
    //-------------------------------------------------------------------------
    if (statcnt)
    {
        statcnt--;
        text_i( rbuf + (((pitch / 2) - strlen( statusline) * 6 / 8) & 0xFE) + (temp.scy - 10) * pitch,
                statusline,
                0x09
            );
    }
    //-------------------------------------------------------------------------
    if (!conf.led.enabled)
        return;
    //-------------------------------------------------------------------------
    if (temp.led.ay)    ay_led();
    if (temp.led.perf)  perf_led();
    if (temp.led.load)  load_led();
    if (temp.led.input) input_led();
    if (temp.led.time)  time_led();
    //-------------------------------------------------------------------------
    #ifdef MOD_MONITOR
        if (temp.led.osw) debug_led();
    #endif
    //-------------------------------------------------------------------------


    // dbgchk - Ïðèçíàê íàëè÷èÿ àêòèâíûõ áðåêïîèíòîâ
    // isbrk(cpu) - is there breakpoints active or any other reason to use debug z80 loop?
   
   
    #ifdef MOD_MEMBAND_LED
    //-------------------------------------------------------------------------
        if (temp.led.memband)
        {      
            memband_led();
            cpu.dbgchk |= 1;    // äëÿ force memory band [NS]
        }
        //---------------------------------------------------------------------
        else if (temp.led.memband_256) // [NS]
        {
            memband_256_led(); 
            cpu.dbgchk |= 1;    // äëÿ force memory band [NS]
        }
    //-------------------------------------------------------------------------
    #endif
    //-------------------------------------------------------------------------
    if (conf.led.flash_ay_kbd && hndKbdDev)     ay_kbd();
    if (input.keymode == K_INPUT::KM_KEYSTICK)  key_led();
    //-------------------------------------------------------------------------
}
//=============================================================================