Top secrets sources NedoPC pentevo

Rev

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

#include "std.h"

#include "resource.h"
#include "emul.h"
#include "vars.h"
#include "debug.h"
#include "dbgbpx.h"
#include "dbgcmd.h"
#include "config.h"
#include "util.h"

#include "emul_no_modal_windows.h"      // hwnd-ы немодальных окон [NS]
#include "dx.h"                         // OnEnterGui [NS]
#include "draw.h"                       // apply_video() [NS]

//=============================================================================
bool group_bpx_list = TRUE;                                             // [NS]
bool group_bpr_list = TRUE;
bool group_bpw_list = TRUE;
//=============================================================================
enum
{
    DB_STOP = 0,
    DB_CHAR,
    DB_SHORT,
    DB_PCHAR,
    DB_PSHORT,
    DB_PINT,
    DB_PFUNC
};
//=============================================================================
typedef bool (__cdecl *func_t)();

static unsigned calcerr;

//=============================================================================
unsigned calc( const Z80 *cpu, uintptr_t *script)
{
    unsigned stack[ 64];
    unsigned *sp = stack-1, x;
    //-------------------------------------------------------------------------
    while (*script)
    {
        switch (*script++)
        {
            case 'M':                   *sp = cpu->DirectRm(*sp);               break;
            case '!':                   *sp = ! *sp;                            break;
            case '~':                   *sp = ~ *sp;                            break;
            case '+':                   *(sp-1) += *sp;                         goto arith;
            case '-':                   *(sp-1) -= *sp;                         goto arith;
            case '*':                   *(sp-1) *= *sp;                         goto arith;
            case '/':   if (*sp)        *(sp-1) /= *sp;                         goto arith;
            case '%':   if (*sp)        *(sp-1) %= *sp;                         goto arith;
            case '&':                   *(sp-1) &= *sp;                         goto arith;
            case '|':                   *(sp-1) |= *sp;                         goto arith;
            case '^':                   *(sp-1) ^= *sp;                         goto arith;
            case WORD2('-','>'):        *(sp-1) = cpu->DirectRm(*sp + sp[-1]);  goto arith;
            case WORD2('>','>'):        *(sp-1) >>= *sp;                        goto arith;
            case WORD2('<','<'):        *(sp-1) <<= *sp;                        goto arith;
            case WORD2('!','='):        *(sp-1) = (sp[-1] != *sp);              goto arith;
            case '=':
            case WORD2('=','='):        *(sp-1) = (sp[-1] == *sp);              goto arith;
            case WORD2('<','='):        *(sp-1) = (sp[-1] <= *sp);              goto arith;
            case WORD2('>','='):        *(sp-1) = (sp[-1] >= *sp);              goto arith;
            case WORD2('|','|'):        *(sp-1) = (sp[-1] || *sp);              goto arith;
            case WORD2('&','&'):        *(sp-1) = (sp[-1] && *sp);              goto arith;
            case '<':                   *(sp-1) = (sp[-1] < *sp);               goto arith;
            case '>':                   *(sp-1) = (sp[-1] > *sp);               goto arith;
arith:                sp--;  break;
            case DB_CHAR:
            case DB_SHORT:              x = unsigned(*script++);                goto push;
            case DB_PCHAR:              x = *(unsigned char*)*script++;         goto push;
            case DB_PSHORT:             x = 0xFFFF & *(unsigned*)*script++;     goto push;
            case DB_PINT:               x = *(unsigned*)*script++;              goto push;
            case DB_PFUNC:              x = ((func_t)*script++)();              goto push;
push:                 *++sp = x; break;
        } // switch (*script)
    } // while
    //-------------------------------------------------------------------------
    if (sp != stack)
        calcerr = 1;
    //-------------------------------------------------------------------------
    return *sp;
}
//=============================================================================


//=============================================================================
static bool __cdecl get_dos_flag()
{
    return (comp.flags & CF_DOSPORTS) != 0;
}
//=============================================================================

//=============================================================================
// АХТУНХ! В ЭТОЙ КОНСТРУКЦИИ НЕЛЬЗЯ НОРМАЛЬНО КОМЕНТИТЬ !!!
//
// соблюдать неповторяемость начал обратной елочкой !!!
// ABCD
// AB2
// AB
// A
// ибо сработает только самое первое похожее
// A
// ABCD = AB
// AB2
// AB


#define DECL_REGS(var, cpu)                                                     \
    static struct                                                               \
    {                                                                           \
        unsigned reg;                                                           \
        const void *ptr;                                                        \
        unsigned char size;                                                     \
    } var[] =                                                                   \
    {                                                                           \
                                                                                \
        { WORD4('I','N','T', 0 ),       &cpu.iff1,   1  },       /* INT [NS] */ \
        { WORD4('I','F','2', 0 ),       &cpu.iff2,   1  },       /* IF2 [NS] */ \
        { WORD4('H','L','T', 0 ),       &cpu.halted, 1  },       /* HLT [NS] */ \
        { WORD2('I','M'),               &cpu.im, 1 },         /* IM = 0 [NS] */ \
                                                              /* IM = 1 [NS] */ \
                                                              /* IM = 2 [NS] */ \
                                                                                \
        { WORD4('D','O','S', 0 ), (const void *)get_dos_flag, 0 }, /* DOS */    \
        { WORD4('O','U','T', 0 ),       &brk_port_out,  4  },      /* OUT */    \
        { WORD2('I','N'),               &brk_port_in,   4  },      /* IN  */    \
        { WORD4('V','A','L', 0 ),       &brk_port_val,  1  },      /* VAL */    \
        { WORD2('F','D'),               &comp.p7FFD,    1  },      /* FD  */    \
                                                                                \
        { WORD4('A','F','\'', 0 ),      &cpu.alt.af, 2  },                      \
        { WORD4('B','C','\'', 0 ),      &cpu.alt.bc, 2  },                      \
        { WORD4('D','E','\'', 0 ),      &cpu.alt.de, 2  },                      \
        { WORD4('H','L','\'', 0 ),      &cpu.alt.hl, 2  },                      \
        { WORD2('A','\''),              &cpu.alt.a,  1  },                      \
        { WORD2('F','\''),              &cpu.alt.f,  1  },                      \
        { WORD2('B','\''),              &cpu.alt.b,  1  },                      \
        { WORD2('C','\''),              &cpu.alt.c,  1  },                      \
        { WORD2('D','\''),              &cpu.alt.d,  1  },                      \
        { WORD2('E','\''),              &cpu.alt.e,  1  },                      \
        { WORD2('H','\''),              &cpu.alt.h,  1  },                      \
        { WORD2('L','\''),              &cpu.alt.l,  1  },                      \
                                                                                \
        { WORD4('a','f','\'', 0 ),      &cpu.alt.af, 2  },      /* [NS] */      \
        { WORD4('b','c','\'', 0 ),      &cpu.alt.bc, 2  },      /* [NS] */      \
        { WORD4('d','e','\'', 0 ),      &cpu.alt.de, 2  },      /* [NS] */      \
        { WORD4('h','l','\'', 0 ),      &cpu.alt.hl, 2  },      /* [NS] */      \
        { WORD4('a','F','\'', 0 ),      &cpu.alt.af, 2  },      /* [NS] */      \
        { WORD4('b','C','\'', 0 ),      &cpu.alt.bc, 2  },      /* [NS] */      \
        { WORD4('d','E','\'', 0 ),      &cpu.alt.de, 2  },      /* [NS] */      \
        { WORD4('h','L','\'', 0 ),      &cpu.alt.hl, 2  },      /* [NS] */      \
        { WORD4('A','f','\'', 0 ),      &cpu.alt.af, 2  },      /* [NS] */      \
        { WORD4('B','c','\'', 0 ),      &cpu.alt.bc, 2  },      /* [NS] */      \
        { WORD4('D','e','\'', 0 ),      &cpu.alt.de, 2  },      /* [NS] */      \
        { WORD4('H','l','\'', 0 ),      &cpu.alt.hl, 2  },      /* [NS] */      \
        { WORD2('a','\''),              &cpu.alt.a,  1  },      /* [NS] */      \
        { WORD2('f','\''),              &cpu.alt.f,  1  },      /* [NS] */      \
        { WORD2('b','\''),              &cpu.alt.b,  1  },      /* [NS] */      \
        { WORD2('c','\''),              &cpu.alt.c,  1  },      /* [NS] */      \
        { WORD2('d','\''),              &cpu.alt.d,  1  },      /* [NS] */      \
        { WORD2('e','\''),              &cpu.alt.e,  1  },      /* [NS] */      \
        { WORD2('h','\''),              &cpu.alt.h,  1  },      /* [NS] */      \
        { WORD2('l','\''),              &cpu.alt.l,  1  },      /* [NS] */      \
                                                                                \
        { WORD2('A','F'),       &cpu.af, 2      },              /* AF */        \
        { WORD2('B','C'),       &cpu.bc, 2      },              /* BC */        \
        { WORD2('D','E'),       &cpu.de, 2      },              /* DE */        \
        { WORD2('H','L'),       &cpu.hl, 2      },              /* HL */        \
        { 'A',                  &cpu.a,  1      },                              \
        { 'F',                  &cpu.f,  1      },                              \
        { 'B',                  &cpu.b,  1      },                              \
        { 'C',                  &cpu.c,  1      },                              \
        { 'D',                  &cpu.d,  1      },                              \
        { 'E',                  &cpu.e,  1      },                              \
        { 'H',                  &cpu.h,  1      },                              \
        { 'L',                  &cpu.l,  1      },                              \
                                                                                \
        { WORD2('P','C'),               &cpu.pc, 2 },           /* PC */        \
        { WORD2('S','P'),               &cpu.sp, 2 },           /* SP */        \
                                                                                \
        { WORD4('I','X','H', 0 ),       &cpu.xh, 1 },           /* IXH  [NS] */ \
        { WORD4('I','X','L', 0 ),       &cpu.xl, 1 },           /* IXL  [NS] */ \
        { WORD4('I','Y','H', 0 ),       &cpu.yh, 1 },           /* IYH  [NS] */ \
        { WORD4('I','Y','L', 0 ),       &cpu.yl, 1 },           /* IYL  [NS] */ \
                                                                                \
        { WORD2('X','H'),               &cpu.xh, 1 },           /* XH   [NS] */ \
        { WORD2('X','L'),               &cpu.xl, 1 },           /* XL   [NS] */ \
        { WORD2('Y','H'),               &cpu.yh, 1 },           /* YH   [NS] */ \
        { WORD2('Y','L'),               &cpu.yl, 1 },           /* YL   [NS] */ \
                                                                                \
        { WORD2('I','X'),               &cpu.ix, 2 },           /* IX */        \
        { WORD2('I','Y'),               &cpu.iy, 2 },           /* IY */        \
                                                                                \
        { 'I',                  &cpu.i,     1   },                              \
        { 'R',                  &cpu.r_low, 1   },  /* вроде бы d7 работает */   \
                                                                                \
        { 'T',                  &cpu.t,     4   },              /* T    [NS] */ \
    }

// АХТУНХ! В ЭТОЙ КОНСТРУКЦИИ НЕЛЬЗЯ НОРМАЛЬНО КОМЕНТИТЬ !!!

//      { WORD4('N','P','C', 0 ),       &cpu.nextpc, 2 }, - не работатет а жаль
//=============================================================================




//=============================================================================
static unsigned char toscript( char *script, uintptr_t *dst)
{
    uintptr_t *d1 = dst;
    //-------------------------------------------------------------------------
    static struct
    {
        unsigned short op;
        unsigned char prior;
    } prio[] =
    {
        {       '(',      10    },
        {       ')',      0     },
        {       '!',      1     },
        {       '~',      1     },
        {       'M',      1     },
        { WORD2('-','>'), 1     },
        {       '*',      2     },
        {       '%',      2     },
        {       '/',      2     },
        {       '+',      3     },
        {       '-',      3     },
        { WORD2('>','>'), 4     },
        { WORD2('<','<'), 4     },
        {       '>',      5     },
        {       '<',      5     },
        {       '=',      5     },
        { WORD2('>','='), 5     },
        { WORD2('<','='), 5     },
        { WORD2('=','='), 5     },
        { WORD2('!','='), 5     },
        {       '&',      6     },
        {       '^',      7     },
        {       '|',      8     },
        { WORD2('&','&'), 9     },
        { WORD2('|','|'), 10    }
    };
    //-------------------------------------------------------------------------
   
    const Z80 &cpu = CpuMgr.Cpu();

    DECL_REGS( regs, cpu);

    unsigned sp = 0;
    uintptr_t stack[ 128];
    //-------------------------------------------------------------------------
    for (char *p = script;    *p;    p++)
        if (p[1] != 0x27)
            *p = char( toupper( *p));
    //-------------------------------------------------------------------------
    while (*script)
    {
        //---------------------------------------------------------------------
        if (*(unsigned char*) script <= ' ')
        {
            script++;
            continue;
        }
        //---------------------------------------------------------------------
        if (*script == '\'')
        { // char
            *dst++ = DB_CHAR;
            *dst++ = uintptr_t( script[1]);
            //-----------------------------------------------------------------
            if (script[2] != '\'')
                return 0;
            //-----------------------------------------------------------------
            script += 3;
            continue;
        }
        //---------------------------------------------------------------------
        if (isalnum( *script) && *script != 'M')
        {
            unsigned r = -1U;
            unsigned p = *(unsigned*) script;
            unsigned ln = 0;
            //-----------------------------------------------------------------
            for (unsigned i = 0;    i < _countof( regs);    i++)
            {
                unsigned mask = 0xFF;
                ln = 1;
                //-------------------------------------------------------------
                if (regs[i].reg & 0xFF00)
                {
                    mask = 0xFFFF;
                    ln = 2;
                }
                //-------------------------------------------------------------
                if (regs[i].reg & 0xFF0000)
                {
                    mask = 0xFFFFFF;
                    ln = 3;
                }
                //-------------------------------------------------------------
                if (regs[i].reg == (p & mask))
                {
                    r = i;
                    break;
                }
                //-------------------------------------------------------------
            }
            //-----------------------------------------------------------------
            if (r != -1U)
            {
                script += ln;
                //-------------------------------------------------------------
                switch (regs[r].size)
                {
                    case 0:     *dst++ = DB_PFUNC;      break;
                    case 1:     *dst++ = DB_PCHAR;      break;
                    case 2:     *dst++ = DB_PSHORT;     break;
                    case 4:     *dst++ = DB_PINT;       break;
                    default:    errexit("BUG01");
                }
                //-------------------------------------------------------------
                *dst++ = (uintptr_t)regs[r].ptr;
            }
            //-----------------------------------------------------------------
            else
            { // number
                //-------------------------------------------------------------
                if (*script > 'F') return 0;
                //-------------------------------------------------------------
                for (r = 0;    isalnum( *script) && *script <= 'F';    script++)
                {
                    r = r * 0x10 + unsigned( (*script >= 'A') ? *script-'A' + 10 :
                                                                *script-'0');
                }
                //-------------------------------------------------------------
                *dst++ = DB_SHORT;
                *dst++ = r;
            }
            //-----------------------------------------------------------------
            continue;
        }
        //---------------------------------------------------------------------
        // find operation
        unsigned char pr = 0xFF;
        unsigned r = (unsigned)*script++;
        //---------------------------------------------------------------------
        if (strchr("<>=&|-!", (char)r) && strchr("<>=&|", *script))
            r += unsigned( 0x100 * (*script++));
        //---------------------------------------------------------------------
        for (unsigned i = 0; i < _countof( prio); i++)
        {
            if (prio[i].op == r)
            {
                pr = prio[i].prior;
                break;
            }
        }
        //---------------------------------------------------------------------
        if (pr == 0xFF)
            return 0;
        //---------------------------------------------------------------------
        if (r != '(')
        {
            while (sp && ((stack[ sp] >> 16 <= pr) || (r == ')' && (stack[ sp] & 0xFF) != '(')))
            { // get from stack
                *dst++ = stack[sp--] & 0xFFFF;
            }
        }
        //---------------------------------------------------------------------
        if (r == ')')
        {
            sp--;                       // del opening bracket
        }
        //---------------------------------------------------------------------
        else
        {
            stack[ ++sp] = r + 0x10000 * pr;    // put to stack
        }
        //---------------------------------------------------------------------
        if ((int) sp < 0)
            return 0;                   // no opening bracket
        //---------------------------------------------------------------------
    }
    //-------------------------------------------------------------------------
    // empty stack
    while (sp)
    {
        //---------------------------------------------------------------------
        if ((stack[ sp] & 0xFF) == '(')
            return 0; // no closing bracket
        //---------------------------------------------------------------------
        *dst++ = stack[ sp--] & 0xFFFF;
    }
    //-------------------------------------------------------------------------
    *dst = DB_STOP;

    calcerr = 0;
    calc( &cpu, d1);
    return u8( 1 - calcerr);
}
//=============================================================================

// тк дальше глюки npp подсветки
// такой костыль
        int npp_higlight_shit_costil = (')');   // [NS]

//=============================================================================
static void script2text( char *dst, const uintptr_t *src)
{
    char stack[ 64][ 0x200];
    char tmp[ 0x200];
    unsigned sp = 0;
    uintptr_t r;

    const Z80 &cpu = CpuMgr.Cpu();

    DECL_REGS( regs, cpu);
    //-------------------------------------------------------------------------
    while ((r = *src++))
    {
        //---------------------------------------------------------------------
        if (r == DB_CHAR)
        {
            sprintf( stack[ sp++], "'%c'", int( *src++));
            continue;
        }
        //---------------------------------------------------------------------
        if (r == DB_SHORT)
        {
            sprintf( stack[ sp], "0%X", unsigned( *src++));
            //-----------------------------------------------------------------
            if (isdigit( stack[ sp][ 1]))
                strcpy( stack[ sp], stack[ sp] + 1);
            //-----------------------------------------------------------------
            sp++;
            continue;
        }
        //---------------------------------------------------------------------
        if ((r >= DB_PCHAR) && (r <= DB_PFUNC))
        {
            unsigned sz = 0;
            //-----------------------------------------------------------------
            switch (r)
            {
                case DB_PCHAR:  sz = 1; break;
                case DB_PSHORT: sz = 2; break;
                case DB_PINT:   sz = 4; break;
                case DB_PFUNC:  sz = 0; break;
            }
            //-----------------------------------------------------------------
            unsigned i;
            for (i = 0;    i < _countof( regs);    i++)
            {
                if ((*src == (uintptr_t) regs[ i].ptr) && (sz == regs[ i].size))
                    break;
            }
            //-----------------------------------------------------------------
            *(unsigned*) &(stack[ sp++]) = regs[ i].reg;
            src++;
            continue;
        }
        //---------------------------------------------------------------------
        if ((r == 'M') || (r == '~') || (r == '!'))
        { // unary operators
            sprintf( tmp, "%c(%s)", int( r), stack[ sp - 1]);
            strcpy( stack[ sp - 1], tmp);
            continue;
        }
        //---------------------------------------------------------------------
        // else binary operators
        sprintf( tmp, "(%s%s%s)", stack[ sp - 2], (char*) &r, stack[ sp - 1]);
        sp--;
        strcpy( stack[ sp - 1], tmp);
    }
    //-------------------------------------------------------------------------
    if (!sp)
    {
        *dst = 0;
    }
    //-------------------------------------------------------------------------
    else
    {
        strcpy( dst, stack[ sp - 1]);
    }
    //-------------------------------------------------------------------------
}
//=============================================================================


//=============================================================================
static void SetBpxButtons( HWND dlg)
{
    int focus = -1;
    int text = 0;
    int box = 0;
   
    HWND focusedWnd = GetFocus();
    //-------------------------------------------------------------------------
    // Перевод фокуса и засерение груп при клацании
    //-------------------------------------------------------------------------
    // Condition BP - EDITTEXT / LISTBOX
    if ( (focusedWnd == GetDlgItem( dlg, IDE_CBP))      ||
         (focusedWnd == GetDlgItem( dlg, IDC_CBP))
     )
    {
        focus = 0;
        text = IDE_CBP;
        box = IDC_CBP;
    }
    //-------------------------------------------------------------------------
    // Execute BP - EDITTEXT / LISTBOX
    if ( (focusedWnd == GetDlgItem( dlg, IDE_BPX))      ||
         (focusedWnd == GetDlgItem( dlg, IDC_BPX))
     )
    {
        focus = 1;
        text = IDE_BPX;
        box = IDC_BPX;
    }
    //-------------------------------------------------------------------------
    // Read BP - EDITTEXT / LISTBOX
    if ( (focusedWnd == GetDlgItem( dlg, IDE_MEM_RD))   ||
         (focusedWnd == GetDlgItem( dlg, IDC_MEM_RD))
     )
    {
        focus = 2;
        text = IDE_MEM_RD;
        box = IDC_MEM_RD;
    }
    //-------------------------------------------------------------------------
    // Write BP - EDITTEXT / LISTBOX
    if ( (focusedWnd == GetDlgItem( dlg, IDE_MEM_WR))   ||
         (focusedWnd == GetDlgItem( dlg, IDC_MEM_WR))
     )
    {
        focus = 3;
        text = IDE_MEM_WR;
        box = IDC_MEM_WR;
    }
    //-------------------------------------------------------------------------
    /*
            // DEPRECATED WR/RD
            if (        (focusedWnd == GetDlgItem( dlg, IDE_MEM))       ||
                        (focusedWnd == GetDlgItem( dlg, IDC_MEM))       ||
                        (focusedWnd == GetDlgItem( dlg, IDC_MEM_R))     ||
                        (focusedWnd == GetDlgItem( dlg, IDC_MEM_W))
             )
            {
                focus = 2;
                text = IDE_MEM;
                box = IDC_MEM;
            }
    */

    //-------------------------------------------------------------------------
    SendDlgItemMessage( dlg, IDE_CBP,    EM_SETREADONLY, (BOOL) (focus != 0), 0);
    SendDlgItemMessage( dlg, IDE_BPX,    EM_SETREADONLY, (BOOL) (focus != 1), 0);
    SendDlgItemMessage( dlg, IDE_MEM_RD, EM_SETREADONLY, (BOOL) (focus != 2), 0); // [NS]
    SendDlgItemMessage( dlg, IDE_MEM_WR, EM_SETREADONLY, (BOOL) (focus != 3), 0); // [NS]
    //-------------------------------------------------------------------------
    int del0 = 0;
    int add0 = 0;
    int del1 = 0;
    int add1 = 0;
    int del2 = 0;
    int add2 = 0;
    int del3 = 0; // [NS]
    int add3 = 0; // [NS]
    //-------------------------------------------------------------------------
    unsigned max = unsigned( SendDlgItemMessage( dlg, box,  LB_GETCOUNT,      0, 0));
    unsigned cur = unsigned( SendDlgItemMessage( dlg, box,  LB_GETCURSEL,     0, 0));
    unsigned len = unsigned( SendDlgItemMessage( dlg, text, WM_GETTEXTLENGTH, 0, 0));
    //-------------------------------------------------------------------------
    if (max && cur >= max)
        SendDlgItemMessage( dlg, box, LB_SETCURSEL, cur = 0, 0);
    //-------------------------------------------------------------------------
    // Condition BP
    if (focus == 0)
    {
        if (len && max < MAX_CBP) add0 = 1;
        if (cur < max) del0 = 1;
    }
    //-------------------------------------------------------------------------
    // Execute BP
    if (focus == 1)
    {
        if (len) add1 = 1;
        if (cur < max) del1 = 1;
    }
    //-------------------------------------------------------------------------
    // Read BP
    if (focus == 2)
    {
        /*
        //---------------------------------------------------------------------
        if (    (IsDlgButtonChecked( dlg, IDC_MEM_R) == BST_UNCHECKED) &&
                (IsDlgButtonChecked( dlg, IDC_MEM_W) == BST_UNCHECKED)
         )
        {
            len = 0;
        }
        //---------------------------------------------------------------------
        */

        if (len) add2 = 1;
        if (cur < max) del2 = 1;
    }
    //-------------------------------------------------------------------------
    // Write BP
    if (focus == 3)
    {
        if (len) add3 = 1;
        if (cur < max) del3 = 1;
    }
    //-------------------------------------------------------------------------

    EnableWindow( GetDlgItem( dlg, IDB_CBP_ADD),  add0);
    EnableWindow( GetDlgItem( dlg, IDB_CBP_DEL),  del0);
    EnableWindow( GetDlgItem( dlg, IDB_CBP_EDIT), del0); // совпадает с del
   
    EnableWindow( GetDlgItem( dlg, IDB_BPX_ADD),  add1);
    EnableWindow( GetDlgItem( dlg, IDB_BPX_DEL),  del1);
    EnableWindow( GetDlgItem( dlg, IDB_BPX_EDIT), del1); // совпадает с del
   
    EnableWindow( GetDlgItem( dlg, IDB_MEM_RD_ADD),  add2); // [NS]
    EnableWindow( GetDlgItem( dlg, IDB_MEM_RD_DEL),  del2);
    EnableWindow( GetDlgItem( dlg, IDB_MEM_RD_EDIT), del2); // совпадает с del
   
    EnableWindow( GetDlgItem( dlg, IDB_MEM_WR_ADD),  add3); // [NS]
    EnableWindow( GetDlgItem( dlg, IDB_MEM_WR_DEL),  del3);
    EnableWindow( GetDlgItem( dlg, IDB_MEM_WR_EDIT), del3); // совпадает с del
   
   
    unsigned defid = 0;
    //-------------------------------------------------------------------------
    if (add0) defid = IDB_CBP_ADD;
    if (add1) defid = IDB_BPX_ADD;
    if (add2) defid = IDB_MEM_RD_ADD;
    if (add3) defid = IDB_MEM_WR_ADD;
    //-------------------------------------------------------------------------
    if (defid)
        SendMessage( dlg, DM_SETDEFID, defid, 0);
    //-------------------------------------------------------------------------
}
//=============================================================================


//=============================================================================
/*
// лютейший говнокод неизвестного аффтара
// даже не знание про LB_DELETESTRING не оправдание килотоннам тоннам LB_GETCOUNT
static void ClearListBox( HWND box)
{
    //-------------------------------------------------------------------------
    while (SendMessage( box, LB_GETCOUNT, 0, 0))
    {
        SendMessage( box, LB_DELETESTRING, 0, 0);
    }
    //-------------------------------------------------------------------------
}
*/

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


//=============================================================================
static void FillCondBox( HWND dlg, unsigned cursor)
{
    HWND box = GetDlgItem( dlg, IDC_CBP);
   
    SendMessage( box, WM_SETREDRAW, FALSE, 0);  // отключаем перерисовку списка [NS]
   
    //ClearListBox( box);
    SendMessage( box, LB_RESETCONTENT, 0, 0);   // [NS]

    Z80 &cpu = CpuMgr.Cpu();
    //-------------------------------------------------------------------------
    for (unsigned i = 0;    i < cpu.cbpn;    i++)
    {
        char tmp[ 0x200];
        script2text( tmp, cpu.cbp[ i]);
        SendMessage( box, LB_ADDSTRING, 0, (LPARAM) tmp);
    }
    //-------------------------------------------------------------------------
    SendMessage( box, LB_SETCURSEL, cursor, 0);
   
    SendMessage( box, WM_SETREDRAW, TRUE, 0);   // включаем перерисовку списка [NS]
}
//=============================================================================


//=============================================================================
static void FillBpxBox( HWND dlg, unsigned address)
{
    //printf("FillBpxBox ");
    HWND box = GetDlgItem( dlg, IDC_BPX);

    SendMessage( box, WM_SETREDRAW, FALSE, 0);  // отключаем перерисовку списка [NS]

    //ClearListBox( box);       // очистка тоже долго с перерисовкой!!!
                                // напорядки больше чем создание !!!
    SendMessage( box, LB_RESETCONTENT, 0, 0);   // [NS]
   
    unsigned selection = 0;

    Z80 &cpu = CpuMgr.Cpu();
    unsigned end;               // Alone Coder 0.36.7
    //-------------------------------------------------------------------------
    for (unsigned start = 0;    start < 0x10000;    )
    {
        //---------------------------------------------------------------------
        if (!(cpu.membits[ start] & MEMBITS_BPX))
        {
            start++;
            continue;
        }
        //---------------------------------------------------------------------
        for (   /*unsigned*/ end = start
                ;
                (end < 0xFFFF)                          &&      // диапазон поиска
                (group_bpx_list)                        &&      // отключение групировки
                (cpu.membits[ end + 1] & MEMBITS_BPX)   &&
                // + У блока должна быть такая же отключенность
                // иначе это разные бряки
                ((cpu.bp_disable_bits[ end + 1] & BP_DISABLE_BPX) == (cpu.bp_disable_bits[ end] & BP_DISABLE_BPX))     
                ;
                end++ );
        //---------------------------------------------------------------------
        char tmp[ 16];
        //---------------------------------------------------------------------
        if (start == end)
        {
            if (cpu.bp_disable_bits[ start] & BP_DISABLE_BPX)
            {
                sprintf( tmp, "%04X <-- DISABLED", start);
            }
            else
            {
                sprintf( tmp, "%04X", start);
            }
        }
        //---------------------------------------------------------------------
        else
        {
            // "-" между цифр нельзя менять !!!!
            // тк диапазон для заливки\удаления\отключения
            // ВНЕЗАПНО читаетсо прямо из этого текста
            //
            // по идеи весь блок с одинаковым режимом
            if (cpu.bp_disable_bits[ start] & BP_DISABLE_BPX)
            {
                sprintf( tmp, "%04X-%04X <-- DISABLED", start, end);
            }
            else
            {
                sprintf( tmp, "%04X-%04X", start, end);
            }
        }
        //---------------------------------------------------------------------
        SendMessage( box, LB_ADDSTRING, 0, (LPARAM) tmp);
       
                //      int i_temp = SendMessage( box, LB_ADDSTRING, 0, (LPARAM) tmp);
                //      printf("%x\n",i_temp);
                //TZT
                        //SendDlgItemMessage(hDlg, id, iMsg, wParam, lParam);
                        //SendMessage(hwnd, message, wParam, lParam);
                //      i_temp = SendMessage( box, LB_GETITEMDATA, i_temp, 0);
                //      printf("  %x\n",i_temp);

        //---------------------------------------------------------------------
        if ((start <= address) && (address <= end))
            selection = unsigned( SendMessage( box, LB_GETCOUNT, 0, 0));
        //---------------------------------------------------------------------
        start = end + 1;
    }
    //-------------------------------------------------------------------------
    if (selection)
        SendMessage( box, LB_SETCURSEL, selection - 1, 0);
    //-------------------------------------------------------------------------
    SendMessage( box, WM_SETREDRAW, TRUE, 0);   // включаем перерисовку списка [NS]

    needclr++;  // обновить окно дебагера
}
//=============================================================================





//=============================================================================
static void Fill_Mem_RD_Box( HWND dlg, unsigned address)                // [NS]
{
    //printf("Fill_Mem_RD_Box ");
    HWND box = GetDlgItem( dlg, IDC_MEM_RD);

    SendMessage( box, WM_SETREDRAW, FALSE, 0);  // отключаем перерисовку списка [NS]
   
    //ClearListBox( box);
    SendMessage( box, LB_RESETCONTENT, 0, 0);   // [NS]

    unsigned selection = 0;

    Z80 &cpu = CpuMgr.Cpu();
    unsigned end;               // Alone Coder 0.36.7
    //-------------------------------------------------------------------------
    for (unsigned start = 0;    start < 0x10000;    )
    {
        //---------------------------------------------------------------------
        if (!(cpu.membits[ start] & MEMBITS_BPR))
        {
            start++;
            continue;
        }
        //---------------------------------------------------------------------
        for (   /*unsigned*/ end = start
                ;
                (end < 0xFFFF)                          &&
                (group_bpr_list)                        &&      // отключение групировки
                (cpu.membits[ end + 1] & MEMBITS_BPR)   &&
                // + У блока должна быть такая же отключенность
                // иначе это разные бряки
                ((cpu.bp_disable_bits[ end + 1] & BP_DISABLE_BPR) == (cpu.bp_disable_bits[ end] & BP_DISABLE_BPR))     
                ;
                end++ );
        //---------------------------------------------------------------------
        char tmp[ 16];
        //---------------------------------------------------------------------
        if (start == end)
        {
            if (cpu.bp_disable_bits[ start] & BP_DISABLE_BPR)
            {
                sprintf( tmp, "%04X <-- DISABLED", start);
            }
            else
            {
                sprintf( tmp, "%04X", start);
            }
        }
        //---------------------------------------------------------------------
        else
        {
            // "-" между цифр нельзя менять !!!!
            // тк диапазон для заливки\удаления\отключения
            // ВНЕЗАПНО читаетсо прямо из этого текста
            //
            // по идеи весь блок с одинаковым режимом
            if (cpu.bp_disable_bits[ start] & BP_DISABLE_BPR)
            {
                sprintf( tmp, "%04X-%04X <-- DISABLED", start, end);
            }
            else
            {
                sprintf( tmp, "%04X-%04X", start, end);
            }
        }
        //---------------------------------------------------------------------
        SendMessage( box, LB_ADDSTRING, 0, (LPARAM) tmp);
        //---------------------------------------------------------------------
        if ((start <= address) && (address <= end))
            selection = unsigned( SendMessage( box, LB_GETCOUNT, 0, 0));
        //---------------------------------------------------------------------
        start = end + 1;
    }
    //-------------------------------------------------------------------------
    if (selection)
        SendMessage( box, LB_SETCURSEL, selection - 1, 0);
    //-------------------------------------------------------------------------
    SendMessage( box, WM_SETREDRAW, TRUE, 0);   // включаем перерисовку списка [NS]
   
    needclr++;  // обновить окно дебагера
}
//=============================================================================


//=============================================================================
static void Fill_Mem_WR_Box( HWND dlg, unsigned address)                // [NS]
{
    HWND box = GetDlgItem( dlg, IDC_MEM_WR);

    SendMessage( box, WM_SETREDRAW, FALSE, 0);  // отключаем перерисовку списка [NS]

    //ClearListBox( box);                       // очистка тоже долго с перерисовкой!!!
    SendMessage( box, LB_RESETCONTENT, 0, 0);   // [NS]

    unsigned selection = 0;

    SendMessage( box, WM_SETREDRAW, FALSE, 0);  // отключаем перерисовку списка [NS]
   
    Z80 &cpu = CpuMgr.Cpu();
    unsigned end;               // Alone Coder 0.36.7
    //-------------------------------------------------------------------------
    for (unsigned start = 0;    start < 0x10000;    )
    {
        //---------------------------------------------------------------------
        if (!(cpu.membits[ start] & MEMBITS_BPW))
        {
            start++;
            continue;
        }
        //---------------------------------------------------------------------
        for (   /*unsigned*/ end = start
                ;
                (end < 0xFFFF)                          &&
                (group_bpw_list)                        &&      // отключение групировки
                (cpu.membits[ end + 1] & MEMBITS_BPW)   &&
                // + У блока должна быть такая же отключенность
                // иначе это разные бряки
                ((cpu.bp_disable_bits[ end + 1] & BP_DISABLE_BPW) == (cpu.bp_disable_bits[ end] & BP_DISABLE_BPW))
                ;
                end++ );
        //---------------------------------------------------------------------
        char tmp[ 16];
        //---------------------------------------------------------------------
        if (start == end)
        {
            if (cpu.bp_disable_bits[ start] & BP_DISABLE_BPW)
            {
                sprintf( tmp, "%04X <-- DISABLED", start);
            }
            else
            {
                sprintf( tmp, "%04X", start);
            }
        }
        //---------------------------------------------------------------------
        else
        {
            // "-" между цифр нельзя менять !!!!
            // тк диапазон для заливки\удаления\отключения
            // ВНЕЗАПНО читаетсо прямо из этого текста
            //
            // по идеи весь блок с одинаковым режимом
            if (cpu.bp_disable_bits[ start] & BP_DISABLE_BPW)
            {
                sprintf( tmp, "%04X-%04X <-- DISABLED", start, end);
            }
            else
            {
                sprintf( tmp, "%04X-%04X", start, end);
            }
        }
        //---------------------------------------------------------------------
        SendMessage( box, LB_ADDSTRING, 0, (LPARAM) tmp);
        //---------------------------------------------------------------------
        if ((start <= address) && (address <= end))
            selection = unsigned( SendMessage( box, LB_GETCOUNT, 0, 0));
        //---------------------------------------------------------------------
        start = end + 1;
    }
    //-------------------------------------------------------------------------
    if (selection)
        SendMessage( box, LB_SETCURSEL, selection - 1, 0);
    //-------------------------------------------------------------------------
    SendMessage( box, WM_SETREDRAW, TRUE, 0);   // включаем перерисовку списка [NS]

    needclr++;  // обновить окно дебагера
}
//=============================================================================



//=============================================================================
static char MoveBpxFromBoxToEdit( HWND dlg, unsigned box, unsigned edit)
{
    HWND hBox = GetDlgItem( dlg, int( box));
    unsigned max = unsigned( SendDlgItemMessage( dlg, box, LB_GETCOUNT,  0, 0));
    unsigned cur = unsigned( SendDlgItemMessage( dlg, box, LB_GETCURSEL, 0, 0));
    //-------------------------------------------------------------------------
    if (cur >= max)
        return 0;
    //-------------------------------------------------------------------------
    char tmp[ 0x200];
    SendMessage( hBox, LB_GETTEXT, cur, (LPARAM) tmp);
   
    char *temp_addr = strstr( tmp, " <-");
    //-------------------------------------------------------------------------
    // если строка не найдена то strstr возвращает 0 !!!!
    if ((temp_addr) != 0)
    {
        //типо затираем " <-- DISABLED"
        *temp_addr = 0;
    }
    //-------------------------------------------------------------------------
    /*
    if ((box == IDC_MEM) && *tmp)
    {
        char *last = tmp + strlen( tmp);
        unsigned r = BST_UNCHECKED;
        unsigned w = BST_UNCHECKED;
        //---------------------------------------------------------------------
        if (last[ -1] == 'W')
        {
            w = BST_CHECKED;
            last--;
        }
        //---------------------------------------------------------------------
        if (last[ -1] == 'R')
        {
            r = BST_CHECKED;
            last--;
        }
        //---------------------------------------------------------------------
        if (last[ -1] == ' ')
            last--;
        //---------------------------------------------------------------------
        *last = 0;
        CheckDlgButton( dlg, IDC_MEM_R, r);
        CheckDlgButton( dlg, IDC_MEM_W, w);
    }
    */

    //-------------------------------------------------------------------------
    SetDlgItemText( dlg, edit, tmp);
    return 1;
}
//=============================================================================


//=============================================================================
struct MEM_RANGE
{
    unsigned start;
    unsigned end;
};
//=============================================================================


//=============================================================================
static int GetMemRamge( char *str, MEM_RANGE &range)
{
    //-------------------------------------------------------------------------
    while (*str == ' ')
        str++;
    //-------------------------------------------------------------------------
    for (range.start = 0;    ishex( *str);    str++)
        range.start = range.start * 0x10 + hex( *str);
    //-------------------------------------------------------------------------
    if (*str == '-')
    {
        //---------------------------------------------------------------------
        for (range.end = 0, str++;    ishex( *str);    str++)
            range.end = range.end * 0x10 + hex( *str);
        //---------------------------------------------------------------------
    }
    //-------------------------------------------------------------------------
    else
    {
        range.end = range.start;
    }
    //-------------------------------------------------------------------------
    while (*str == ' ')
        str++;
    //-------------------------------------------------------------------------
    if (*str)
        return 0;
    //-------------------------------------------------------------------------
    if (range.start > range.end)                // [NS]
    {
        unsigned temp = range.end;
        range.end = range.start;
        range.start = temp;
    }
    //-------------------------------------------------------------------------
    if ((range.start > 0xFFFF) || (range.end > 0xFFFF))
        return 0;
    //-------------------------------------------------------------------------
    return 1;
}
//=============================================================================









//=============================================================================
void conddlg_update_texts( HWND dlg)                                    // [NS]
{
    LPCSTR temp_CPU_name;
    //-------------------------------------------------------------------------
    if ( (CpuMgr.GetCurrentCpu()) == 0 )
    {
        temp_CPU_name = "Current CPU: ZX-CPU";
    }
    //-------------------------------------------------------------------------
    else
    {
        temp_CPU_name = "Current CPU: GS-CPU";
    }
    //-------------------------------------------------------------------------
    //SetWindowText( GetDlgItem( dlg, IDT_CURRENT_CPU_INDICATOR), temp_CPU_name);
    SetWindowText( GetDlgItem( dlg, IDB_SWITCH_CPU), temp_CPU_name);
}
//=============================================================================























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


    static int conddlg_current_visible_cpu = 0;
   
//=============================================================================
// обработчик сообщений диалога breakpoint-ов

static INT_PTR CALLBACK conddlg( HWND dlg, UINT msg, WPARAM wp, LPARAM lp)
{
    (void) lp;
       
    // бекапим текущий CPU
    // тк conddlg ввызываетсо рекурсивно !!!!
    // нужно возвращать всегда предыдущее состояние !!
    // NOT STATIC !!!
    int current_cpu_back = CpuMgr.GetCurrentCpu();      // NOT STATIC !!!
   
    // меняем текущий CPU
    CpuMgr.SetCurrentCpu( conddlg_current_visible_cpu);
   
    Z80 &cpu = CpuMgr.Cpu();
   
    // НА ВСЕХ ВЫХОДАХ ИЗ conddlg()
    // НУЖНО ВОСТАНАВЛИВАТЬ CPU на место!!!!
    // это проще чем поправить все записи
   
    // printf("msg %x wp %x lp %x\n",msg,wp,lp);
   
    //-------------------------------------------------------------------------
    // цвета для listbox-ов
    static HBRUSH hBrushStatic;
    static COLORREF color_cbp = { RGB(   0, 100, 200) };
    static COLORREF color_bpx = { RGB(   0,   0, 255) };
    static COLORREF color_bpw = { RGB( 160,  16,  16) };
    static COLORREF color_bpr = { RGB(  16, 140,  16) };
    //-------------------------------------------------------------------------
 
    unsigned id = LOWORD( wp);
    unsigned code = HIWORD( wp);
    unsigned char mask = 0;
    unsigned char disable_bp_mask = 0;

    //=========================================================================
    if (msg == WM_INITDIALOG)                                           // [NS]
    {      
        // для разукрашки listbox-ов
        hBrushStatic = CreateSolidBrush( GetSysColor( COLOR_BTNHIGHLIGHT));
       
        // текущий видимый проц на момент входа
        // нужно при входе из дебагера когда активен GS по хоткею
        conddlg_current_visible_cpu = current_cpu_back;
        CpuMgr.SetCurrentCpu( conddlg_current_visible_cpu);
        Z80 &cpu = CpuMgr.Cpu();
        //printf("current_visible_cpu %x\n",current_visible_cpu);
    }
    //=========================================================================                                
    if (msg == WM_DESTROY)                                              // [NS]
    {
        DeleteObject( hBrushStatic);
    }
    //=========================================================================

    // ODT_LISTBOX
    // LB_GETLISTBOXINFO 0x01B2
   

    //=========================================================================
    // разукрашка listbox-ов методом научного тыка                       // [NS]
    // к сожалению мы не знаем как красить отдельные строки
    // так покрасим хоть шо нибудь (так лучше различаютсо колонки)
    if (msg == WM_CTLCOLORLISTBOX)
    {
        // int i;
        // i = GetWindowLong ((HWND) lp, GWL_ID);      
        //---------------------------------------------------------------------
        if      (lp == (WPARAM) GetDlgItem( dlg, IDC_CBP))
        {
            SetTextColor ((HDC) wp, color_cbp);
        }
        //---------------------------------------------------------------------
        else if (lp == (WPARAM) GetDlgItem( dlg, IDC_BPX))
        {
            SetTextColor ((HDC) wp, color_bpx);
        }
        //---------------------------------------------------------------------
        else if (lp == (WPARAM) GetDlgItem( dlg, IDC_MEM_RD))
        {
            SetTextColor ((HDC) wp, color_bpr);
        }
        //---------------------------------------------------------------------
        else if (lp == (WPARAM) GetDlgItem( dlg, IDC_MEM_WR))
        {
            SetTextColor ((HDC) wp, color_bpw);
        }
        //---------------------------------------------------------------------
        //SetBkColor ((HDC) wp, GetSysColor( COLOR_BTNHIGHLIGHT));
       
        // возвращаем CPU на место перед выходом
        CpuMgr.SetCurrentCpu( current_cpu_back);
       
        return (LRESULT) hBrushStatic;
    }
    //=========================================================================
   

    //=========================================================================
    // Контексные Менюшки
    //     а шо так можно мы узнали при помощи winuser.h
    //     и метода научного тыка приплясывая с бубном
    //     всякие там Педзольды молчат как партизанэн
    //     а правые клики мышой тупо сюдава недоходят о_О
    //     даже как noclient
    //
    if (msg == WM_CONTEXTMENU)  // [NS]
    {
        // wp - HWND того куда мы ткнули
        // lp - координаты куда мы ткнули в screen формате
        bool display_listbox_menu;
        int current_listbox_menu;
        //=====================================================================
        // Conditional BP
        if      (wp == (WPARAM) GetDlgItem( dlg, IDC_CBP))
        {
            display_listbox_menu = TRUE;
            current_listbox_menu = IDC_CBP;
        }
        //---------------------------------------------------------------------
        // Execute BP
        else if (wp == (WPARAM) GetDlgItem( dlg, IDC_BPX))
        {
            display_listbox_menu = TRUE;
            current_listbox_menu = IDC_BPX;
        }
        //---------------------------------------------------------------------
        // Read BP
        else if (wp == (WPARAM) GetDlgItem( dlg, IDC_MEM_RD))
        {
            display_listbox_menu = TRUE;
            current_listbox_menu = IDC_MEM_RD;
        }
        //---------------------------------------------------------------------
        // Write BP
        else if (wp == (WPARAM) GetDlgItem( dlg, IDC_MEM_WR))
        {
            display_listbox_menu = TRUE;
            current_listbox_menu = IDC_MEM_WR;
        }
        //---------------------------------------------------------------------
        else
        {
            display_listbox_menu = FALSE;       // никуда не попали
        }
        //=====================================================================
        if (display_listbox_menu)
        {
            int xPos = LOWORD( lp);     // в screen формате
            int yPos = HIWORD( lp);
            // printf("old x %d y %d\n",xPos,yPos);
            POINT click_pos;
            click_pos.x = xPos;
            click_pos.y = yPos;
           
            // переводим в формат координат listbox-а
            ScreenToClient( (HWND) wp, &click_pos);
            //printf("new x %d y %d\n",click_pos.x,click_pos.y);
            // имитируем клик чтобы переместить гребаный фокус
            // почему то отправка на на dlg на работает
            // работает только на hwnd listbox-а
            SendMessage( (HWND) wp, WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG( click_pos.x, click_pos.y));

        //MF_END
        // MF_MENUBARBREAK
        // MF_MENUBREAK
        // MF_STRING | MF_SYSMENU смещает надпись вправо
       
            //-----------------------------------------------------------------
            // Выбираем что писать Enable или Disable
            char brk_disable_enable_text[ 16] = "Disable";
            bool brk_disable_possible = TRUE;
            bool brk_edit_possible = TRUE;
            bool brk_delete_possible = TRUE;
            bool brk_xxx_all_possible = TRUE;
            //-----------------------------------------------------------------
            if (current_listbox_menu != IDC_CBP)
            {
                HWND hBox = GetDlgItem( dlg, int( current_listbox_menu));       //IDC_PPX
                unsigned cur = unsigned( SendDlgItemMessage( dlg, current_listbox_menu, LB_GETCURSEL, 0, 0));
                unsigned max = unsigned( SendDlgItemMessage( dlg, current_listbox_menu, LB_GETCOUNT,  0, 0));
                //-------------------------------------------------------------
                if (cur >= max)
                {
                    brk_disable_possible = FALSE;
                    brk_edit_possible = FALSE;
                    brk_delete_possible = FALSE;
                    brk_xxx_all_possible = FALSE;
                    goto skip_disable_enable_text_printing;
                    // ДАЛЬШЕ НЕЛЬЗЯ РАБОТАТЬ С НЕВАЛИДНЫМИ ДАННЫМИ !!!
                    // или можно словить access denied с падением !!!
                }
                //-------------------------------------------------------------
                char tmp_strng[ 0x200];
                SendMessage( hBox, LB_GETTEXT, cur, (LPARAM) tmp_strng);
                char *temp_addr = strstr( tmp_strng, "-");
                //-------------------------------------------------------------
                // если строка не найдена то strstr возвращает 0 !!!!
                if ((temp_addr) != 0)
                {
                    *temp_addr = 0;     //типо затираем "-xxxx <--..."
                }
                //-------------------------------------------------------------
                unsigned cursor_addr;
                sscanf( tmp_strng, "%X", &cursor_addr);
                //Z80 &cpu = CpuMgr.Cpu();      // cpu.xxx = текущий CPU
                int mask = 0;
                //-------------------------------------------------------------
                switch (current_listbox_menu)
                {
                    case IDC_BPX:       mask = u8( BP_DISABLE_BPX);     break;
                    case IDC_MEM_RD:    mask = u8( BP_DISABLE_BPR);     break;
                    case IDC_MEM_WR:    mask = u8( BP_DISABLE_BPW);     break;
                }
                //-------------------------------------------------------------
                if (cpu.bp_disable_bits[ cursor_addr] & mask)
                {
                    sprintf( brk_disable_enable_text, "Enable");
                }
                else
                {
                    sprintf( brk_disable_enable_text, "Disable");
                }
                //-------------------------------------------------------------
            } // not IDC_CBP
            //-----------------------------------------------------------------
            // IDC_CBP
            else
            {
                unsigned cur = unsigned( SendDlgItemMessage( dlg, current_listbox_menu, LB_GETCURSEL, 0, 0));
                unsigned max = unsigned( SendDlgItemMessage( dlg, current_listbox_menu, LB_GETCOUNT,  0, 0));
                //-------------------------------------------------------------
                if (cur >= max)
                {
                    brk_disable_possible = FALSE;
                    brk_edit_possible = FALSE;
                    brk_delete_possible = FALSE;
                    brk_xxx_all_possible = FALSE;
                    goto skip_disable_enable_text_printing;
                }
                //-------------------------------------------------------------
            }
            //-----------------------------------------------------------------
skip_disable_enable_text_printing:
            //-----------------------------------------------------------------
           
           
            //-----------------------------------------------------------------
            HMENU context_menu = CreatePopupMenu();
                                                               
            int mf_flag;
                                                                //=================================
            mf_flag = ( (current_listbox_menu != IDC_CBP) &&
                        (brk_disable_possible) 
                                                )  ?  MF_STRING :
                                                      MF_STRING | MF_GRAYED;
                                                                 
            AppendMenu( context_menu, mf_flag, IDM_BRK_DISABLE, brk_disable_enable_text );
            //                                                          "Disable/Enable"
            AppendMenu( context_menu, MF_SEPARATOR, 0, nullptr); //================================
            mf_flag = (brk_edit_possible)  ?  MF_STRING :
                                              MF_STRING | MF_GRAYED;
            AppendMenu( context_menu, mf_flag, IDM_BRK_EDIT,            "Edit"         );
            //-------------------------------------------------------------------------------------
            mf_flag = (brk_delete_possible)  ?  MF_STRING :
                                                MF_STRING | MF_GRAYED;
            AppendMenu( context_menu, mf_flag, IDM_BRK_DELETE,          "Delete"       );
            AppendMenu( context_menu, MF_SEPARATOR, 0, nullptr); //================================
            mf_flag = ( (current_listbox_menu != IDC_CBP) &&
                        (brk_xxx_all_possible) 
                                                )  ?  MF_STRING:
                                                      MF_STRING | MF_GRAYED;
            AppendMenu( context_menu, mf_flag, IDM_BRK_ENABLE_ALL,      "Enable All"   );
            //-------------------------------------------------------------------------------------
            AppendMenu( context_menu, mf_flag, IDM_BRK_DISABLE_ALL,     "Disable All"  );
            AppendMenu( context_menu, MF_SEPARATOR, 0, nullptr); //================================
            AppendMenu( context_menu, mf_flag, IDM_BRK_DELETE_ALL,      "Delete All"   );
                                                                //=================================
            //-----------------------------------------------------------------
            // TPM_LAYOUTRTL выравниввниие по правому краю
            int cmd = TrackPopupMenu(   context_menu,                   // handle of shortcut menu
                                        TPM_RETURNCMD | TPM_NONOTIFY | TPM_LEFTALIGN | TPM_TOPALIGN, //uFlags
                                        xPos,                           // x
                                        yPos,                           // y
                                        0,                              // nReserved
                                        dlg,    //      или (HWND) wp        // hWnd
                                        nullptr         //points to RECT that specifies no-dismissal area
                                 );
            //-----------------------------------------------------------------
            DestroyMenu( context_menu);
            //-----------------------------------------------------------------
            Z80 &cpu = CpuMgr.Cpu();    // cpu.xxx = текущий CPU
            //-----------------------------------------------------------------
            switch (cmd)
            {
                //=============================================================
                // Disable
                case IDM_BRK_DISABLE:
                {
                    //---------------------------------------------------------
                    switch (current_listbox_menu)
                    {
                        //case IDC_CBP:         goto;
                        case IDC_BPX:           goto disable_bpx;
                        case IDC_MEM_RD:        goto disable_bpr;
                        case IDC_MEM_WR:        goto disable_bpw;
                    }
                    //---------------------------------------------------------
                    break;
                }
                //=============================================================
                // Edit
                case IDM_BRK_EDIT:
                {
                    //---------------------------------------------------------
                    switch (current_listbox_menu)
                    {
                        case IDC_CBP:           goto cbp_edit_label;
                        case IDC_BPX:           goto bpx_edit_label;
                        case IDC_MEM_RD:        goto bpr_edit_label;
                        case IDC_MEM_WR:        goto bpw_edit_label;
                    }
                    //---------------------------------------------------------
                    break;
                }
                //=============================================================
                // Delete
                case IDM_BRK_DELETE:
                {
                    //---------------------------------------------------------
                    switch (current_listbox_menu)
                    {
                        case IDC_CBP:           goto del_cond;
                        case IDC_BPX:           goto del_bpx;
                        case IDC_MEM_RD:        goto del_mem_rd;
                        case IDC_MEM_WR:        goto del_mem_wr;
                    }
                    //---------------------------------------------------------
                    break;
                }
                //=============================================================
                // Enable All
                case IDM_BRK_ENABLE_ALL:
                {
                    //---------------------------------------------------------
                    switch (current_listbox_menu)
                    {
                        //-----------------------------------------------------
                        case IDC_BPX: // Enable All
                        {
                            SetFocus( GetDlgItem( dlg, IDC_BPX));
                            //-------------------------------------------------
                            for (unsigned i = 0x0000;    i <= 0xFFFF;    i++)
                            {  
                                if (cpu.membits[i] & MEMBITS_BPX)
                                {
                                    // ставим флаг выключености
                                    cpu.bp_disable_bits[ i] &= u8( ~BP_DISABLE_BPX);
                                }
                            }
                            //-------------------------------------------------
                            FillBpxBox(  dlg, 0);       // [NS]
                            // обновить окно дебагера
                            needclr++;
                            goto set_buttons_and_return;
                        }
                        //-----------------------------------------------------
                        case IDC_MEM_RD: // Enable All
                        {
                            SetFocus( GetDlgItem( dlg, IDE_MEM_RD));
                            //-------------------------------------------------
                            for (unsigned i = 0x0000;    i <= 0xFFFF;    i++)
                            {
                                if (cpu.membits[i] & MEMBITS_BPR)
                                {
                                    // ставим флаг выключености
                                    cpu.bp_disable_bits[ i] &= u8( ~BP_DISABLE_BPR);
                                }
                            }
                            //-------------------------------------------------
                            Fill_Mem_RD_Box(  dlg, 0);  // [NS]
                            // обновить окно дебагера
                            needclr++;
                            goto set_buttons_and_return;
                        }
                        //-----------------------------------------------------
                        case IDC_MEM_WR: // Enable All
                        {
                            SetFocus( GetDlgItem( dlg, IDE_MEM_WR));
                            //-------------------------------------------------
                            for (unsigned i = 0x0000;    i <= 0xFFFF;    i++)
                            {
                                if (cpu.membits[i] & MEMBITS_BPW)
                                {
                                    // ставим флаг выключености
                                    cpu.bp_disable_bits[ i] &= u8( ~BP_DISABLE_BPW);
                                }
                            }
                            //-------------------------------------------------
                            Fill_Mem_WR_Box(  dlg, 0);  // [NS]
                            // обновить окно дебагера
                            needclr++;
                            goto set_buttons_and_return;
                        }
                        //-----------------------------------------------------
                    } // switch (current_listbox_menu)
                    //---------------------------------------------------------
                    break;
                } // case IDM_BRK_ENABLE_ALL:
                //=============================================================
               
               
               
                //=============================================================
                // Disable All
                case IDM_BRK_DISABLE_ALL:
                {
                    // отключать НЕЛЬЗЯ простым циклом 0-FFFF !!!!!
                    // тк потом будут создаватсо отключенные бряки!!!
                    //
                    // нужно проверять стоит ли бряк
                    // и если он есть тогда только отключать !!!!
                    //---------------------------------------------------------
                    switch (current_listbox_menu)
                    {
                        //-----------------------------------------------------
                        case IDC_BPX:
                        {
                            SetFocus( GetDlgItem( dlg, IDC_BPX));
                            //-------------------------------------------------
                            for (unsigned i = 0x0000;    i <= 0xFFFF;    i++)
                            {  
                                if (cpu.membits[i] & MEMBITS_BPX)
                                {
                                    // ставим флаг выключености
                                    cpu.bp_disable_bits[ i] |= u8( BP_DISABLE_BPX);
                                }
                            }
                            //-------------------------------------------------
                            FillBpxBox(  dlg, 0);       // [NS]
                            // обновить окно дебагера
                            needclr++;
                            goto set_buttons_and_return;
                        }
                        //-----------------------------------------------------
                        case IDC_MEM_RD:
                        {
                            SetFocus( GetDlgItem( dlg, IDE_MEM_RD));
                            //-------------------------------------------------
                            for (unsigned i = 0x0000;    i <= 0xFFFF;    i++)
                            {
                                if (cpu.membits[i] & MEMBITS_BPR)
                                {
                                    // ставим флаг выключености
                                    cpu.bp_disable_bits[ i] |= u8( BP_DISABLE_BPR);
                                }
                            }
                            //-------------------------------------------------
                            Fill_Mem_RD_Box(  dlg, 0);  // [NS]
                            // обновить окно дебагера
                            needclr++;
                            goto set_buttons_and_return;
                        }
                        //-----------------------------------------------------
                        case IDC_MEM_WR:
                        {
                            SetFocus( GetDlgItem( dlg, IDE_MEM_WR));
                            //-------------------------------------------------
                            for (unsigned i = 0x0000;    i <= 0xFFFF;    i++)
                            {
                                if (cpu.membits[i] & MEMBITS_BPW)
                                {
                                    // ставим флаг выключености
                                    cpu.bp_disable_bits[ i] |= u8( BP_DISABLE_BPW);
                                }
                            }
                            //-------------------------------------------------
                            Fill_Mem_WR_Box(  dlg, 0);  // [NS]
                            // обновить окно дебагера
                            needclr++;
                            goto set_buttons_and_return;
                        }
                        //-----------------------------------------------------
                    } // switch (current_listbox_menu)
                    //---------------------------------------------------------
                    break;
                } // case IDM_BRK_DISABLE_ALL:
                //=============================================================
               
               
               
                //=============================================================
                // Delete All
                case IDM_BRK_DELETE_ALL:
                {
                    //---------------------------------------------------------
                    switch (current_listbox_menu)
                    {
                        //-----------------------------------------------------
                        case IDC_BPX:
                        {
                            SetFocus( GetDlgItem( dlg, IDC_BPX));
                            //-------------------------------------------------
                            for (unsigned i = 0x0000;    i <= 0xFFFF;    i++)
                            {
                                // удаляем бряк
                                cpu.membits[ i] &= u8( ~(MEMBITS_BPX));        
                                // удаляем флаг выключености
                                cpu.bp_disable_bits[ i] &= u8( ~(BP_DISABLE_BPX));
                            }
                            //-------------------------------------------------
                            FillBpxBox(  dlg, 0);       // [NS]
                            // обновить окно дебагера
                            needclr++;
                            goto set_buttons_and_return;
                        }
                        //-----------------------------------------------------
                        case IDC_MEM_RD:
                        {
                            SetFocus( GetDlgItem( dlg, IDE_MEM_RD));
                            //-------------------------------------------------
                            for (unsigned i = 0x0000;    i <= 0xFFFF;    i++)
                            {
                                // удаляем бряк
                                cpu.membits[ i] &= u8( ~(MEMBITS_BPR));        
                                // удаляем флаг выключености
                                cpu.bp_disable_bits[ i] &= u8( ~(BP_DISABLE_BPR));
                            }
                            //-------------------------------------------------
                            Fill_Mem_RD_Box(  dlg, 0);  // [NS]
                            // обновить окно дебагера
                            needclr++;
                            goto set_buttons_and_return;
                        }
                        //-----------------------------------------------------
                        case IDC_MEM_WR:
                        {
                            SetFocus( GetDlgItem( dlg, IDE_MEM_WR));
                            //-------------------------------------------------
                            for (unsigned i = 0x0000;    i <= 0xFFFF;    i++)
                            {
                                // удаляем бряк
                                cpu.membits[ i] &= u8( ~(MEMBITS_BPW));        
                                // удаляем флаг выключености
                                cpu.bp_disable_bits[ i] &= u8( ~(BP_DISABLE_BPW));
                            }
                            //-------------------------------------------------
                            Fill_Mem_WR_Box(  dlg, 0);  // [NS]
                            // обновить окно дебагера
                            needclr++;
                            goto set_buttons_and_return;
                        }
                        //-----------------------------------------------------
                    } // switch (current_listbox_menu)
                    //---------------------------------------------------------
                    break;
                } // case IDM_BRK_DELETE_ALL:
                //=============================================================
               
               
               
               
            } // switch (cmd)
            //-----------------------------------------------------------------
        } // (display_listbox_menu)
        //=====================================================================
    } //if (msg == WM_CONTEXTMENU)
    //=========================================================================


    //-------------------------------------------------------------------------
    // if (msg == WM_DESTROY)
    // {
    //     printf("conddlg WM_DESTROY\n");
    // }
    //=========================================================================
    if (msg == WM_CLOSE)        // [NS]
    {
        //printf("conddlg WM_CLOSE\n");
        DestroyWindow( dlg);
        hwnd_bp_dialog = NULL;  // теперь окно можно снова вызвать
    }
    //=========================================================================
    // глушим звук (иначе буфер зацикленно играет по кругу)
    // тк дефолтный виндовый обработчик WM_MOVE
    // не возвращает управления на время перемещения
    if (msg == WM_MOVE)         // [NS]
    {
        OnEnterGui();
    }
    //=========================================================================
    // включаем обратно
    if (msg == WM_EXITSIZEMOVE) // [NS]
    {
        OnExitGui();
    }
    //=========================================================================
    if (msg == WM_INITDIALOG)
    {
        FillCondBox( dlg, 0);
        FillBpxBox(  dlg, 0);
        Fill_Mem_RD_Box(  dlg, 0);      // [NS]
        Fill_Mem_WR_Box(  dlg, 0);      // [NS]
        //FillMemBox(  dlg, 0);         // Deprecated
        conddlg_update_texts( dlg);     // [NS]

        // [NS]                                                        
        CheckDlgButton( dlg, IDC_BPX_GROUP,    group_bpx_list  ?  BST_CHECKED :
                                                                  BST_UNCHECKED);
        CheckDlgButton( dlg, IDC_MEM_RD_GROUP, group_bpr_list  ?  BST_CHECKED :
                                                                  BST_UNCHECKED);
        CheckDlgButton( dlg, IDC_MEM_WR_GROUP, group_bpw_list  ?  BST_CHECKED :
                                                                  BST_UNCHECKED);
       
        SetFocus( GetDlgItem( dlg, IDE_CBP));

set_buttons_and_return:         // вызываетсо отовсюду
        SetBpxButtons( dlg);
       
        // возвращаем CPU на место перед выходом
        CpuMgr.SetCurrentCpu( current_cpu_back);
       
        return 1;
    }
    //=========================================================================
    if ((msg == WM_SYSCOMMAND) && ((wp & 0xFFF0) == SC_CLOSE))
    {
        //printf("conddlg SC_CLOSE \n");
        EndDialog( dlg, 0);
    }
    //=========================================================================
    if (msg != WM_COMMAND)
    {
        // возвращаем CPU на место перед выходом
        CpuMgr.SetCurrentCpu( current_cpu_back);
       
        return 0;
    }
    //=========================================================================
   
   
    //=========================================================================

    //-------------------------------------------------------------------------
    // нет никакого OK и Cancel у этого окна [NS]
    // но эта хуита срабатывает если при входе нажать enter
    //  if (id == IDCANCEL || id == IDOK)
    //  {
    //     printf("conddlg not existed IDCANCEL IDOK \n");
    //     EndDialog( dlg, 0);
    //  }
    //    
    //-------------------------------------------------------------------------
    char tmp[ 0x200];
   
   
    //=========================================================================
    if (   (    ((id == IDE_BPX) || (id == IDE_CBP) || (id == IDE_MEM_RD) || (id == IDE_MEM_WR))        &&
                ((code == EN_SETFOCUS) || (code == EN_CHANGE))
           )
           ||
           (    ((id == IDC_BPX) || (id == IDC_CBP) || (id == IDC_MEM_RD) || (id == IDC_MEM_WR))        &&
                (code == LBN_SETFOCUS)
           )
      )
    {
        goto set_buttons_and_return;
    }
    //=========================================================================
    /*
    // больше нету
    if ((id == IDC_MEM_R) || (id == IDC_MEM_W))
        goto set_buttons_and_return;
    */

    //=========================================================================
   
   
                                        // [NZ]
   
   
   
   
    //=========================================================================
    if (id == IDC_BPX_GROUP)
    {
        group_bpx_list = FALSE;
        //---------------------------------------------------------------------
        if (IsDlgButtonChecked( dlg, IDC_BPX_GROUP) == BST_CHECKED)
        {
            group_bpx_list = TRUE;
        }
        //---------------------------------------------------------------------
        FillBpxBox( dlg, 0);
        goto set_buttons_and_return;
    }
    //-------------------------------------------------------------------------
    if (id == IDC_MEM_RD_GROUP)
    {
        group_bpr_list = FALSE;
        //---------------------------------------------------------------------
        if (IsDlgButtonChecked( dlg, IDC_MEM_RD_GROUP) == BST_CHECKED)
        {
            group_bpr_list = TRUE;
        }
        //---------------------------------------------------------------------
        Fill_Mem_RD_Box( dlg, 0);
        goto set_buttons_and_return;
    }
    //-------------------------------------------------------------------------
    if (id == IDC_MEM_WR_GROUP)
    {
        group_bpw_list = FALSE;
        //---------------------------------------------------------------------
        if (IsDlgButtonChecked( dlg, IDC_MEM_WR_GROUP) == BST_CHECKED)
        {
            group_bpw_list = TRUE;
        }
        //---------------------------------------------------------------------
        Fill_Mem_WR_Box( dlg, 0);
        goto set_buttons_and_return;
    }
    //=========================================================================
   
               
               
               
    //=========================================================================
    if (id == IDB_CBP_EDIT)                                             // [NS]
    {
cbp_edit_label:
        if (MoveBpxFromBoxToEdit( dlg, IDC_CBP, IDE_CBP))
        {
            goto del_cond;
        }
    }
    //-------------------------------------------------------------------------
    if (id == IDB_BPX_EDIT)                                             // [NS]
    {
bpx_edit_label:
        if (MoveBpxFromBoxToEdit( dlg, IDC_BPX, IDE_BPX))
        {
            goto del_bpx;
        }
    }
    //-------------------------------------------------------------------------
    if (id == IDB_MEM_RD_EDIT)                                          // [NS]
    {
bpr_edit_label:
        if (MoveBpxFromBoxToEdit( dlg, IDC_MEM_RD, IDE_MEM_RD))
        {
            goto del_mem_rd;
        }
    }
    //-------------------------------------------------------------------------
    if (id == IDB_MEM_WR_EDIT)                                          // [NS]
    {
bpw_edit_label:
        if (MoveBpxFromBoxToEdit( dlg, IDC_MEM_WR, IDE_MEM_WR))
        {
            goto del_mem_wr;
        }
    }
    //=========================================================================
   
   
   
   
   
   
    //=========================================================================
    // отключение бряка
    if (code == LBN_DBLCLK)
    {
        //if (id == IDC_CBP)
        //{
        //      ;
        //}
        //---------------------------------------------------------------------
        // дабл клик в execute break listbox-е
        if (id == IDC_BPX)
        {
            //printf("LBN_DBLCLK IDC_BPX\n");
disable_bpx:
            SetFocus( GetDlgItem( dlg, IDE_BPX));
            id = IDC_BPX;
            disable_bp_mask = u8( BP_DISABLE_BPX);
disable_range:
            unsigned cur = unsigned( SendDlgItemMessage( dlg, id, LB_GETCURSEL, 0, 0));
            unsigned max = unsigned( SendDlgItemMessage( dlg, id, LB_GETCOUNT,  0, 0));
            //-----------------------------------------------------------------
            if (cur >= max)
            {
                // возвращаем CPU на место перед выходом
                CpuMgr.SetCurrentCpu( current_cpu_back);
       
                return 0;
            }
            //-----------------------------------------------------------------
            SendDlgItemMessage( dlg, id, LB_GETTEXT, cur, (LPARAM) tmp);
            unsigned start, end;
            sscanf( tmp, "%X", &start);
            //-----------------------------------------------------------------
            if (tmp[ 4] == '-')
            {
                sscanf( tmp + 5, "%X", &end);
            }
            //-----------------------------------------------------------------
            else
            {
                end = start;
            }
            //-----------------------------------------------------------------
            Z80 &cpu = CpuMgr.Cpu();
            //-----------------------------------------------------------------
            for (unsigned i = start;    i <= end;    i++)
                cpu.bp_disable_bits[ i] ^= disable_bp_mask;
            //---------------------------------------------------------------------
         
         
               
                // НЕ ТОЛЬКО ДЛЯ (id == IDC_BPX) !!!!
                // ниже сюда goto
                //---------------------------------------------------------------------
                // Exe BP
                if (id == IDC_BPX)
                {
                    FillBpxBox( dlg, 0);
                }
                //---------------------------------------------------------------------
                // Read BP
                else if (id == IDC_MEM_RD)
                {
                    Fill_Mem_RD_Box( dlg, 0);
                }
                //---------------------------------------------------------------------
                // Write BP
                else if (id == IDC_MEM_WR)
                {
                    Fill_Mem_WR_Box( dlg, 0);
                }
                //---------------------------------------------------------------------
               
               
                /*
                // DEBUG !!!!!!!!!!!!1
                FillBpxBox( dlg, 0);
                Fill_Mem_RD_Box( dlg, 0);
                Fill_Mem_WR_Box( dlg, 0);
                */

               
            //---------------------------------------------------------------------
            if (cur && (cur == max))
                cur--;
            //---------------------------------------------------------------------
            SendDlgItemMessage( dlg, id, LB_SETCURSEL, cur, 0);
            cpu.dbgchk = isbrk( cpu);
            goto set_buttons_and_return;
        }
        //---------------------------------------------------------------------
        // дабл клик в memory read break listbox-е
        if (id == IDC_MEM_RD)
        {
disable_bpr:
            //printf("LBN_DBLCLK IDC_MEM_RD\n");
            SetFocus( GetDlgItem( dlg, IDE_MEM_RD));
            id = IDC_MEM_RD;
            disable_bp_mask = u8( BP_DISABLE_BPR);
            goto disable_range;
        }
        //---------------------------------------------------------------------
        // дабл клик в memory write listbox-е
        if (id == IDC_MEM_WR)
        {
disable_bpw:
            //printf("LBN_DBLCLK IDC_MEM_WR\n");
            SetFocus( GetDlgItem( dlg, IDE_MEM_WR));
            id = IDC_MEM_WR;
            disable_bp_mask = u8( BP_DISABLE_BPW);
            goto disable_range;
        }
        //---------------------------------------------------------------------
    }
    //=========================================================================
    //
    if (id == IDB_SWITCH_CPU)
    {
        // бекапим текущий CPU
        ///current_cpu_back = CpuMgr.GetCurrentCpu();  
        conddlg_current_visible_cpu ^= 1;              
        // меняем текущий CPU
        CpuMgr.SetCurrentCpu( conddlg_current_visible_cpu);    

        //Z80 &cpu = CpuMgr.Cpu();
       
        /*
        Z80 &cpu0 = CpuMgr.Cpu();
        cpu0.dbgbreak = 0;
        CpuMgr.SwitchCpu();
        Z80 &cpu1 = CpuMgr.Cpu();
        */

       
        FillCondBox( dlg, 0);
        FillBpxBox(  dlg, 0);
        Fill_Mem_RD_Box(  dlg, 0);      // [NS]
        Fill_Mem_WR_Box(  dlg, 0);      // [NS]
       
       
        conddlg_update_texts( dlg);
       
        // возвращаем CPU на место
        //CpuMgr.SetCurrentCpu( current_cpu_back);     

        //needclr++;    // нужно обновить окно дебагера
                        // теперь не нужно тк не синхронно
        goto set_buttons_and_return;
    }
    //-------------------------------------------------------------------------






    /*
    // редактирование по двойному клику
    if (code == LBN_DBLCLK)
    {
        if ((id == IDC_CBP) && MoveBpxFromBoxToEdit( dlg, IDC_CBP, IDE_CBP))    goto del_cond;
        if ((id == IDC_BPX) && MoveBpxFromBoxToEdit( dlg, IDC_BPX, IDE_BPX))    goto del_bpx;
        if ((id == IDC_MEM) && MoveBpxFromBoxToEdit( dlg, IDC_MEM, IDE_MEM))    goto del_mem;
    }
    */

    //-------------------------------------------------------------------------
    if (id == IDB_CBP_ADD)
    {
        SendDlgItemMessage( dlg, IDE_CBP, WM_GETTEXT, sizeof tmp, (LPARAM) tmp);
        SetFocus( GetDlgItem( dlg, IDE_CBP));
        Z80 &cpu = CpuMgr.Cpu();
        //---------------------------------------------------------------------
        if (!toscript( tmp, cpu.cbp[ cpu.cbpn]))
        {
            MessageBox( dlg,
                        "Error in expression\nPlease do RTFM",
                        nullptr,
                        MB_ICONERROR
                     );
            // возвращаем CPU на место перед выходом
            CpuMgr.SetCurrentCpu( current_cpu_back);
           
            return 1;
        }
        //---------------------------------------------------------------------
        SendDlgItemMessage( dlg, IDE_CBP, WM_SETTEXT, 0, 0);
        FillCondBox( dlg, cpu.cbpn++);
        cpu.dbgchk = isbrk( cpu);
        goto set_buttons_and_return;
    }
    //-------------------------------------------------------------------------
    if (id == IDB_BPX_ADD)
    {
        SendDlgItemMessage( dlg, IDE_BPX, WM_GETTEXT, sizeof tmp, (LPARAM) tmp);
        SetFocus( GetDlgItem( dlg, IDE_BPX));
        MEM_RANGE range;
        //---------------------------------------------------------------------
        if (!GetMemRamge( tmp, range))
        {
            MessageBox( dlg,
                        "Invalid breakpoint address / range",
                        nullptr,
                        MB_ICONERROR
                     );
                     
            // возвращаем CPU на место перед выходом
            CpuMgr.SetCurrentCpu( current_cpu_back);
           
            return 1;
        }
        //---------------------------------------------------------------------
        Z80 &cpu = CpuMgr.Cpu();
        //---------------------------------------------------------------------
        for (unsigned i = range.start;    i <= range.end;    i++)
        {
            cpu.membits[i] |= MEMBITS_BPX;
        }
        //---------------------------------------------------------------------
        SendDlgItemMessage( dlg, IDE_BPX, WM_SETTEXT, 0, 0);
        FillBpxBox( dlg, range.start);
        cpu.dbgchk = isbrk( cpu);
        goto set_buttons_and_return;
    }
    //-------------------------------------------------------------------------
   
   
    //-------------------------------------------------------------------------
    if (id == IDB_MEM_RD_ADD)   // [NS]
    {
        SendDlgItemMessage( dlg, IDE_MEM_RD, WM_GETTEXT, sizeof tmp, (LPARAM) tmp);
        SetFocus( GetDlgItem( dlg, IDE_MEM_RD));
        MEM_RANGE range;
        //---------------------------------------------------------------------
        if (!GetMemRamge( tmp, range))
        {
            MessageBox( dlg,
                        "Invalid breakpoint address / range",
                        nullptr,
                        MB_ICONERROR
                     );
                     
            // возвращаем CPU на место перед выходом
            CpuMgr.SetCurrentCpu( current_cpu_back);
           
            return 1;
        }
        //---------------------------------------------------------------------
        Z80 &cpu = CpuMgr.Cpu();
        //---------------------------------------------------------------------
        for (unsigned i = range.start;    i <= range.end;    i++)
        {
            cpu.membits[i] |= MEMBITS_BPR;
        }
        //---------------------------------------------------------------------
        SendDlgItemMessage( dlg, IDE_MEM_RD, WM_SETTEXT, 0, 0);
        Fill_Mem_RD_Box( dlg, range.start);
        cpu.dbgchk = isbrk( cpu);
        goto set_buttons_and_return;
    }
    //-------------------------------------------------------------------------
   
   

    //-------------------------------------------------------------------------
    if (id == IDB_MEM_WR_ADD)
    {
        SendDlgItemMessage( dlg, IDE_MEM_WR, WM_GETTEXT, sizeof tmp, (LPARAM) tmp);
        SetFocus( GetDlgItem( dlg, IDE_MEM_WR));
        MEM_RANGE range;
        //---------------------------------------------------------------------
        if (!GetMemRamge( tmp, range))
        {
            MessageBox( dlg,
                        "Invalid breakpoint address / range",
                        nullptr,
                        MB_ICONERROR
                     );
                     
            // возвращаем CPU на место перед выходом
            CpuMgr.SetCurrentCpu( current_cpu_back);
           
            return 1;
        }
        //---------------------------------------------------------------------
        Z80 &cpu = CpuMgr.Cpu();
        //---------------------------------------------------------------------
        for (unsigned i = range.start;    i <= range.end;    i++)
        {
            cpu.membits[i] |= MEMBITS_BPW;
        }
        //---------------------------------------------------------------------
        SendDlgItemMessage( dlg, IDE_MEM_WR, WM_SETTEXT, 0, 0);
        Fill_Mem_WR_Box( dlg, range.start);
        cpu.dbgchk = isbrk( cpu);
        goto set_buttons_and_return;
    }
    //-------------------------------------------------------------------------
   
   
   
    //=========================================================================
    if (id == IDB_CBP_DEL)
    {
del_cond:
        SetFocus( GetDlgItem( dlg, IDE_CBP));
        unsigned cur = unsigned( SendDlgItemMessage( dlg, IDC_CBP, LB_GETCURSEL, 0, 0));
        Z80 &cpu = CpuMgr.Cpu();
        //---------------------------------------------------------------------
        if (cur >= cpu.cbpn)
        {
            // возвращаем CPU на место перед выходом
            CpuMgr.SetCurrentCpu( current_cpu_back);
           
            return 0;
        }
        //---------------------------------------------------------------------
        cpu.cbpn--;
        memcpy( cpu.cbp[ cur],
                cpu.cbp[ cur + 1],
                sizeof( cpu.cbp[ 0]) * (cpu.cbpn - cur)
            );
        //---------------------------------------------------------------------
        if (cur && cur == cpu.cbpn)
            cur--;
        //-------------------------------------------------------------------------
        FillCondBox( dlg, cur);
        cpu.dbgchk = isbrk( cpu);
        goto set_buttons_and_return;
    }
    //-------------------------------------------------------------------------
   
   
    //-------------------------------------------------------------------------
    // Удаление BPX (и за одноо BPW, BPR)
    if (id == IDB_BPX_DEL)
    {
del_bpx:
        SetFocus( GetDlgItem( dlg, IDE_BPX));
        id = IDC_BPX;
        mask = u8( ~MEMBITS_BPX);
        disable_bp_mask = u8( ~BP_DISABLE_BPX);
del_range:
        unsigned cur = unsigned( SendDlgItemMessage( dlg, id, LB_GETCURSEL, 0, 0));
        //printf("cur %d\n",cur);
        unsigned max = unsigned( SendDlgItemMessage( dlg, id, LB_GETCOUNT,  0, 0));
        //printf("max %d\n",max);
        //---------------------------------------------------------------------
        if (cur >= max)
        {
            // возвращаем CPU на место перед выходом
            CpuMgr.SetCurrentCpu( current_cpu_back);
           
            return 0;
        }
        //---------------------------------------------------------------------
        SendDlgItemMessage( dlg, id, LB_GETTEXT, cur, (LPARAM) tmp);
        unsigned start, end;
        sscanf( tmp, "%X", &start);
        //---------------------------------------------------------------------
        if (tmp[ 4] == '-')
        {
            sscanf( tmp + 5, "%X", &end);
        }
        //---------------------------------------------------------------------
        else
        {
            end = start;
        }
        //---------------------------------------------------------------------
        Z80 &cpu = CpuMgr.Cpu();
        //---------------------------------------------------------------------
        for (unsigned i = start;    i <= end;    i++)
        {
            cpu.membits[ i] &= mask;                    // удаляем бряк
            cpu.bp_disable_bits[ i] &= disable_bp_mask; // удаляем флаг выключености
        }
        //---------------------------------------------------------------------
       
           
            // не только для (id == IDB_BPX_DEL)
            // ниже goto
            //-----------------------------------------------------------------
            if (id == IDC_BPX)
            {
                FillBpxBox( dlg, 0);
            }
            //-----------------------------------------------------------------
            else if (id == IDC_MEM_RD)                                  // [NS]
            {
                Fill_Mem_RD_Box( dlg, 0);
            }
            //-----------------------------------------------------------------
            else if (id == IDC_MEM_WR)                                  // [NS]
            {
                Fill_Mem_WR_Box( dlg, 0);
            }
            //-----------------------------------------------------------------
           
           
            /*
            // DEBUG !!!!!!!!!!!!!!!!!!
            FillBpxBox( dlg, 0);
            Fill_Mem_RD_Box( dlg, 0);
            Fill_Mem_WR_Box( dlg, 0);
            */

           
        //---------------------------------------------------------------------
        if (cur && (cur == max))
            cur--;
        //---------------------------------------------------------------------
        SendDlgItemMessage( dlg, id, LB_SETCURSEL, cur, 0);
        cpu.dbgchk = isbrk( cpu);
        goto set_buttons_and_return;
    }
    //-------------------------------------------------------------------------
    if (id == IDB_MEM_RD_DEL)
    {
del_mem_rd:
        SetFocus( GetDlgItem( dlg, IDE_MEM_RD));
        id = IDC_MEM_RD;
        mask = u8( ~(MEMBITS_BPR));
        disable_bp_mask = u8( ~BP_DISABLE_BPR);
        goto del_range;
    }
    //-------------------------------------------------------------------------
    if (id == IDB_MEM_WR_DEL)
    {
del_mem_wr:
        SetFocus( GetDlgItem( dlg, IDE_MEM_WR));
        id = IDC_MEM_WR;
        mask = u8( ~(MEMBITS_BPW));
        disable_bp_mask = u8( ~BP_DISABLE_BPW);
        goto del_range;
    }

    // возвращаем CPU на место перед выходом
    CpuMgr.SetCurrentCpu( current_cpu_back);
   
    return 0;
}
//=============================================================================
// создание диалогового окна бряков
void mon_bpdialog()
{
    // DialogBox( hIn, MAKEINTRESOURCE( IDD_COND), wnd, conddlg);       // orig

    //-------------------------------------------------------------------------
    // создаем окно                                                  // [NS]
    // только если оно еще не создано
    // иначе у нас обрабатываютсо сообщения только от одного окна
    // и нужен массив hwnd-овов
    if (hwnd_bp_dialog == NULL)
    {
        hwnd_bp_dialog = CreateDialog( hIn, MAKEINTRESOURCE( IDD_COND), wnd, conddlg);  // [NS]
    }
    //-------------------------------------------------------------------------
    // щас окно поверх всех унриальных окон почему то
    // а так тут нужно переводить фокус на окно
    // которрое могло потерятсо
    /*
    else
    {
        ShowWindow( hwnd_bp_dialog, SW_SHOWNORMAL);     //SW_SHOWMINNOACTIVE
    }*/

}
//=============================================================================
































//=============================================================================
// обработка сообщений окна вачесов
static INT_PTR CALLBACK watchdlg( HWND dlg, UINT msg, WPARAM wp, LPARAM lp)
{
    (void) lp;

    char tmp[ 0x200];
    unsigned i;
    //-------------------------------------------------------------------------
    static const int ids1[] =
    {
        IDC_W1_ON,
        IDC_W2_ON,
        IDC_W3_ON,
        IDC_W4_ON
    };
    //-------------------------------------------------------------------------
    static const int ids2[] =
    {
        IDE_W1,
        IDE_W2,
        IDE_W3,
        IDE_W4
    };
    //-------------------------------------------------------------------------
    if (msg == WM_CLOSE)        // [NS]
    {
        DestroyWindow( dlg);
        hwnd_watchdlg = NULL;   // теперь окно можно снова вызвать
    }
    //-------------------------------------------------------------------------
    if (msg == WM_INITDIALOG)
    {
        //---------------------------------------------------------------------
        for (i = 0;    i < 4;    i++)
        {
            CheckDlgButton( dlg, ids1[i], watch_enabled[i]  ?   BST_CHECKED :
                                                                BST_UNCHECKED);
            script2text( tmp, watch_script[i]);
            SetWindowText( GetDlgItem( dlg, ids2[i]), tmp);
        }
        //---------------------------------------------------------------------
        CheckDlgButton( dlg, IDC_TR_RAM,    trace_ram  ?  BST_CHECKED :
                                                          BST_UNCHECKED);
        //---------------------------------------------------------------------
        CheckDlgButton( dlg, IDC_TR_ROM,    trace_rom  ?  BST_CHECKED : // r0146 fixed было trace_ram [NS]
                                                          BST_UNCHECKED);
        //---------------------------------------------------------------------
        CheckDlgButton( dlg, IDC_LED_DEBUG, (conf.led.osw & 0x80000000)  ?  BST_CHECKED :       // [NS]
                                                                            BST_UNCHECKED);
        //---------------------------------------------------------------------
reinit:
        //---------------------------------------------------------------------
        for (i = 0;    i < 4;    i++)
            EnableWindow( GetDlgItem( dlg, ids2[ i]), watch_enabled[ i]);
        //---------------------------------------------------------------------
        return 1;
    }
    //-------------------------------------------------------------------------
    // Клацание птичек [Trace RAM banks] и [Trace ROM banks]
    if ((msg == WM_COMMAND)  &&  (      (LOWORD( wp) == IDC_TR_RAM)     ||
                                        (LOWORD( wp) == IDC_TR_ROM)
                                )
     )
    {
        trace_ram = IsDlgButtonChecked( dlg, IDC_TR_RAM) == BST_CHECKED;
        trace_rom = IsDlgButtonChecked( dlg, IDC_TR_ROM) == BST_CHECKED;
    }
    //-------------------------------------------------------------------------
    // Клацание птички включения вачесов [NS]
    if ((msg == WM_COMMAND)  &&  (      (LOWORD( wp) == IDC_LED_DEBUG) )
     )
    {
        conf.led.osw =  (conf.led.osw & 0x7FFFFFFF)
                        |
                ((IsDlgButtonChecked( dlg, IDC_LED_DEBUG) == BST_CHECKED)  ?  0x80000000 :
                                                                              0  );
        apply_video();  // без него не включаетсо ? [NS]
    }
    //-------------------------------------------------------------------------    
    // тк как отследить enter в поле редактирования мы не знаем
    // делаем кнопочку применить
    if ((msg == WM_COMMAND)  &&  (      (LOWORD( wp) == ID_APPLY) )
     )
    {
        //---------------------------------------------------------------------
        for (i = 0;    i < 4;    i++)
        {
            if (watch_enabled[ i])
            {
                SendDlgItemMessage( dlg, ids2[i], WM_GETTEXT, sizeof tmp, (LPARAM)tmp);
                //-------------------------------------------------------------
                if (!toscript( tmp, watch_script[i]))
                {
                    sprintf( tmp, "Watch %u: error in expression\nPlease do RTFM", i+1);
                    MessageBox( dlg, tmp, nullptr, MB_ICONERROR);
                    watch_enabled[ i] = 0;
                    SetFocus( GetDlgItem( dlg, ids2[i]));
                    return 0;
                }
                //-------------------------------------------------------------
            }
        }
        //---------------------------------------------------------------------
    }
    //-------------------------------------------------------------------------
   
    // видимо обработка 4-х кнопок вклюючения вачеса
    if ((msg == WM_COMMAND)  &&  (      (LOWORD( wp) == ids1[0]) ||
                                        (LOWORD( wp) == ids1[1]) ||
                                        (LOWORD( wp) == ids1[2]) ||
                                        (LOWORD( wp) == ids1[3])
                                  )
     )
    {
        //---------------------------------------------------------------------
        for (i = 0;    i < 4;    i++)
            watch_enabled[i] = IsDlgButtonChecked( dlg, ids1[ i]) == BST_CHECKED;
        //---------------------------------------------------------------------
        goto reinit;
    }    
    //-------------------------------------------------------------------------
    if (        ((msg == WM_SYSCOMMAND) && ((wp & 0xFFF0) == SC_CLOSE)) ||
                ((msg == WM_COMMAND) && (LOWORD( wp) == IDCANCEL))
     )
    {
        trace_ram = IsDlgButtonChecked( dlg, IDC_TR_RAM) == BST_CHECKED;
        trace_rom = IsDlgButtonChecked( dlg, IDC_TR_ROM) == BST_CHECKED;
       
        // *(&conf.led.ay + 5) = ((*(&conf.led.ay + 5)) & 0x7FFFFFFF)
        conf.led.osw =  (conf.led.osw & 0x7FFFFFFF)
                        |
                ((IsDlgButtonChecked( dlg, IDC_LED_DEBUG) == BST_CHECKED)  ?  0x80000000 :
                                                                              0  );
        apply_video();  // без него не включаетсо ? [NS]
        //---------------------------------------------------------------------
        for (i = 0;    i < 4;    i++)
        {
            if (watch_enabled[ i])
            {
                SendDlgItemMessage( dlg, ids2[i], WM_GETTEXT, sizeof tmp, (LPARAM)tmp);
                //-------------------------------------------------------------
                if (!toscript( tmp, watch_script[i]))
                {
                    sprintf( tmp, "Watch %u: error in expression\nPlease do RTFM", i+1);
                    MessageBox( dlg, tmp, nullptr, MB_ICONERROR);
                    watch_enabled[ i] = 0;
                    SetFocus( GetDlgItem( dlg, ids2[i]));
                    return 0;
                }
                //-------------------------------------------------------------
            }
        }
        //---------------------------------------------------------------------
        EndDialog( dlg, 0);
    }
    //-------------------------------------------------------------------------
    return 0;
}
//=============================================================================
void mon_watchdialog()
{
    //DialogBox( hIn, MAKEINTRESOURCE( IDD_OSW), wnd, watchdlg);
    //-------------------------------------------------------------------------
    // создаем окно                                                  // [NS]
    // только если оно еще не создано
    // иначе у нас обрабатываютсо сообщения только от одного окна
    // и нужен массив hwnd-овов
    if (!hwnd_watchdlg)
    {
        hwnd_watchdlg = CreateDialog( hIn, MAKEINTRESOURCE( IDD_OSW), wnd, watchdlg);   // [NS]
    }
    //-------------------------------------------------------------------------
}
//=============================================================================






//=============================================================================
static void LoadBpx()
{
    char Line[ 100];
    char BpxFileName[ FILENAME_MAX];

    addpath( BpxFileName, "bpx.ini");

    FILE *BpxFile = fopen( BpxFileName, "rt");
    //-------------------------------------------------------------------------
    if (!BpxFile)
        return;
    //-------------------------------------------------------------------------
    while (!feof( BpxFile))
    {
        fgets( Line, sizeof( Line), BpxFile);
        Line[ sizeof( Line) - 1] = 0;
        char Type = -1;
        int Start = -1;
        int End = -1;
        int CpuIdx = -1;
        int n = sscanf( Line, "%c%1d=%i-%i", &Type, &CpuIdx, &Start, &End);
        //---------------------------------------------------------------------
        if (n < 3 || CpuIdx < 0 || CpuIdx >= (int) CpuMgr.GetCount() || Start < 0)
            continue;
        //---------------------------------------------------------------------
        if (End < 0)
            End = Start;
        //---------------------------------------------------------------------
        unsigned mask = 0;
        //---------------------------------------------------------------------
        switch (Type)
        {
            case 'r':   mask |= MEMBITS_BPR;    break;
            case 'w':   mask |= MEMBITS_BPW;    break;
            case 'x':   mask |= MEMBITS_BPX;    break;
            default:    continue;
        }
        //---------------------------------------------------------------------
        Z80 &cpu = CpuMgr.Cpu( u32( CpuIdx));
        //---------------------------------------------------------------------
        for (unsigned i = unsigned( Start);    i <= unsigned( End);    i++)
            cpu.membits[ i] |= mask;
        //---------------------------------------------------------------------
        cpu.dbgchk = isbrk( cpu);
    }
    fclose( BpxFile);
}
//=============================================================================




//=============================================================================
static void SaveBpx()
{
    char BpxFileName[ FILENAME_MAX];

    addpath( BpxFileName, "bpx.ini");

    FILE *BpxFile = fopen( BpxFileName, "wt");
    //-------------------------------------------------------------------------
    if (!BpxFile)
        return;
    //-------------------------------------------------------------------------
    for (unsigned CpuIdx = 0;    CpuIdx < CpuMgr.GetCount();    CpuIdx++)
    {
        Z80 &cpu = CpuMgr.Cpu( CpuIdx);
        //---------------------------------------------------------------------
        for (int i = 0;    i < 3;    i++)
        {
            //-----------------------------------------------------------------
            for (unsigned Start = 0;    Start < 0x10000;    )
            {
                static const unsigned Mask[] =
                {
                    MEMBITS_BPR,
                    MEMBITS_BPW,
                    MEMBITS_BPX
                };
                //-------------------------------------------------------------
                if (!(cpu.membits[ Start] & Mask[ i]))
                {
                    Start++;
                    continue;
                }
                //-------------------------------------------------------------
                unsigned active = cpu.membits[ Start];
                unsigned End;
                //-------------------------------------------------------------
                for (End = Start;    End < 0xFFFF && !((active ^ cpu.membits[ End + 1]) & Mask[i]);    End++);
                //-------------------------------------------------------------
                static const char Type[] = { 'r', 'w', 'x' };
                //-------------------------------------------------------------
                if (active & Mask[i])
                {
                    //---------------------------------------------------------
                    if (Start == End)
                    {
                        fprintf( BpxFile, "%c%1u=0x%04X\n", Type[ i], CpuIdx, Start);
                    }
                    //---------------------------------------------------------
                    else
                    {
                        fprintf( BpxFile, "%c%1u=0x%04X-0x%04X\n", Type[ i], CpuIdx, Start, End);
                    }
                    //---------------------------------------------------------
                }
                //-------------------------------------------------------------
                Start = End + 1;
            }
            //-----------------------------------------------------------------
        }
        //---------------------------------------------------------------------
    }
    //-------------------------------------------------------------------------
    fclose( BpxFile);
}
//=============================================================================




//=============================================================================
void init_bpx()
{
    LoadBpx();
}
//=============================================================================


//=============================================================================
void done_bpx()
{
    SaveBpx();
}
//=============================================================================