Top secrets sources NedoPC pentevo

Rev

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

#include "std.h"

#include "emul.h"
#include "vars.h"
#include "debug.h"
#include "dbgtrace.h"
#include "dbglabls.h"
#include "dbgpaint.h"
#include "dbgcmd.h"
#include "memory.h"
#include "z80asm.h"
#include "z80/op_system.h"
#include "util.h"


// äîáàâèòü â ìåéê !!!1
#include "gsz80.h"              // äëÿ z80gs::GSCPUFQ   [NS]


//unsigned trace_PC_in_view;    //ôëàã ÷òî PC íàõîäèòñÿ â ïîëåçðåíèÿ     //[NS]

unsigned trace_follow_regs_in_view;     //ôëàã ÷òî PC íàõîäèòñÿ â ïîëåçðåíèÿ     //[NS]


//unsigned trace_follow_request;        // .conf ôëàã ÷òî íóæíî ïåðåâåñòè ôîêóñ íà regs //[NS]

//unsigned trace_follow_regs;   // òåïåðü conf.trace_follow_regs






//=============================================================================
bool get_labels( unsigned addr, char *line)                             // [NS]
{
    Z80 &cpu = CpuMgr.Cpu();

    sprintf( line, "   > ");
    int ptr = 5;
    //-------------------------------------------------------------------------
    // .... LABELS xxx xx,xx
    //if (trace_labels)
    {
        char *virtlbl = mon_labels.find(((unsigned char *)NULL) + addr);        //NEDOREPO
        char *lbl = mon_labels.find( am_r( addr));
        //---------------------------------------------------------------------
        if (virtlbl)
            lbl = virtlbl;              //NEDOREPO
        //---------------------------------------------------------------------
//      if (lbl) for (int k = 0;  k < 10  && lbl[k];  line[ptr++] = lbl[k++]); //Alone Coder    //ÏÎËÍÎÑÒÜÞ ÓÄÀËÅÍÎ Â NEDOREPO
        if (lbl)
        {
            for (int k = 0;    (k < 10) && lbl[k];    )
                line[ptr++] = lbl[k++]; //Alone Coder
        }
        else
        {
            return FALSE;
        }
        //---------------------------------------------------------------------
    }
    //-------------------------------------------------------------------------
    // çàëèâêà ñòðîêè îò îïêîäà äî ìíåìîíèêè
    while (ptr < 32)
        line[ ptr++] = ' ';
    //-------------------------------------------------------------------------
    return TRUE;
}
//=============================================================================



//=============================================================================
int disasm_line( unsigned addr, char *line)
{
    Z80 &cpu = CpuMgr.Cpu();
    unsigned char dbuf[ 16 + 129];                      /*Alone Code 0.36.7*/
    ptrdiff_t i;                                        //Alone Coder 0.36.7
    //-------------------------------------------------------------------------
    for (/*int*/ i = 0;    i < 16;    i++)
        dbuf[i] = cpu.DirectRm( addr + unsigned(i));
    //-------------------------------------------------------------------------
    sprintf( line, "%04X ", addr);
    int ptr = 5;
    ptrdiff_t len = disasm( dbuf, addr, char( trace_labels)) - dbuf;
    //8000 ..DDCB0106 rr (ix+1)
    //-------------------------------------------------------------------------
    // .... LABELS xxx xx,xx
    if (trace_labels)
    {
        char *virtlbl = mon_labels.find(((unsigned char *)NULL) + addr);        //NEDOREPO
        char *lbl = mon_labels.find( am_r(addr));
        //---------------------------------------------------------------------
        if (virtlbl)
            lbl = virtlbl;              //NEDOREPO
        //---------------------------------------------------------------------
//      if (lbl) for (int k = 0;  k < 10  && lbl[k];  line[ptr++] = lbl[k++]); //Alone Coder    //ÏÎËÍÎÑÒÜÞ ÓÄÀËÅÍÎ Â NEDOREPO
        if (lbl)
            for (int k = 0;    (k < 10) && lbl[k];    )
                line[ptr++] = lbl[k++]; //Alone Coder
        //---------------------------------------------------------------------
    }
    //-------------------------------------------------------------------------
    // .... OPCODES xx,xx
    else
    {
        ptrdiff_t len1 = len;
        //---------------------------------------------------------------------
        if (len > 4)
        {
            len1 = 4;
            *(short*)(line + ptr) = WORD2('.', '.');
            ptr += 2;
        }
        //---------------------------------------------------------------------
        for (i = len - len1;    i < len;    i++)
        {
            sprintf(line + ptr, "%02X", dbuf[i]);
            ptr += 2;
        }
        //---------------------------------------------------------------------
    }
    //-------------------------------------------------------------------------
    // çàëèâêà ñòðîêè îò îïêîäà äî ìíåìîíèêè
    while (ptr < 16)
        line[ ptr++] = ' ';
    //-------------------------------------------------------------------------
    strcpy( line + ptr, asmbuf);
    return int( len);
}
//=============================================================================
#define TWF_BRANCH  0x010000U
#define TWF_BRADDR  0x020000U
#define TWF_LOOPCMD 0x040000U
#define TWF_CALLCMD 0x080000U
#define TWF_BLKCMD  0x100000U
#define TWF_HALTCMD 0x200000U
// Ìëàäøèå 16áèò - àäðåñ z80
// ñòàðøèå 16áèò - ôëàãè TWF_xxxx
//=============================================================================


//=============================================================================
static unsigned tracewndflags()                                         //????
{
    Z80 &cpu = CpuMgr.Cpu();
    unsigned readptr = cpu.pc, base = cpu.hl;
    unsigned char opcode = 0; unsigned char ed = 0;
    //-------------------------------------------------------------------------
    for (;;)
    {
        opcode = cpu.DirectRm(readptr++);
        if (opcode == 0xDD)
            base = cpu.ix;
        else if (opcode == 0xFD)
            base = cpu.iy;
        else if (opcode == 0xED)
            ed = 1;
        else
            break;
    }
    //-------------------------------------------------------------------------
    unsigned fl = 0;
    if (opcode == 0x76) // halt
    {
        u32 addr;
        if (cpu.im < 2)         //!!!! òî÷íî ëè äëÿ âñåõ?????
        {
            addr = 0x38;
        }
        else // im2
        {
            unsigned vec = unsigned(cpu.i << 8U) | cpu.IntVec();
            addr = u32((cpu.DirectRm(vec+1) << 8U) | cpu.DirectRm(vec));
        }
        return TWF_HALTCMD | addr;
    }
//-----------------------------------------------------------------------------
    if (ed)
    {
        //---------------------------------------------------------------------
        if ((opcode & 0xF4) == 0xB0) // ldir/lddr | cpir/cpdr | inir/indr | otir/otdr
            return TWF_BLKCMD;
        //---------------------------------------------------------------------
        if ((opcode & 0xC7) != 0x45)
            return 0; // reti/retn
        //---------------------------------------------------------------------
ret:
        return (cpu.DirectRm(cpu.sp) | unsigned(cpu.DirectRm(cpu.sp+1) << 8U)) | TWF_BRANCH | TWF_BRADDR;
    }
    //-------------------------------------------------------------------------
    if (opcode == 0xC9)                                         // ret
        goto ret;
    //-------------------------------------------------------------------------
    if (opcode == 0xC3)                                         // jp
    {
jp:    
        return (cpu.DirectRm(readptr) | unsigned(cpu.DirectRm(readptr+1) << 8U)) | TWF_BRANCH | fl;
    }
    //-------------------------------------------------------------------------
    if (opcode == 0xCD)                                         // call
    {
        fl = TWF_CALLCMD;
        goto jp;
    }
    //-------------------------------------------------------------------------
    static const unsigned char flags[] = { ZF,CF,PV,SF };

    if ((opcode & 0xC1) == 0xC0)
    {
        unsigned char flag = flags[(opcode >> 4) & 3];
        unsigned char res = cpu.f & flag;
        //---------------------------------------------------------------------
        if (!(opcode & 0x08))
            res ^= flag;
        if (!res)
            return 0;
        //---------------------------------------------------------------------
        if ((opcode & 0xC7) == 0xC0)                            // ret cc
            goto ret;
        //---------------------------------------------------------------------
        if ((opcode & 0xC7) == 0xC4)                            // call cc
        {
            fl = TWF_CALLCMD;
            goto jp;
        }
        //---------------------------------------------------------------------
        if ((opcode & 0xC7) == 0xC2)                            // jp cc
        {
            fl = TWF_LOOPCMD;
            goto jp;
        }
        //---------------------------------------------------------------------
    }
    //-------------------------------------------------------------------------
    if (opcode == 0xE9)
        return base | TWF_BRANCH | TWF_BRADDR;          // jp (hl/ix/iy)
    //-------------------------------------------------------------------------
    if ((opcode & 0xC7) == 0xC7)
        return (opcode & 0x38) | TWF_CALLCMD | TWF_BRANCH;      // rst #xx
    //-------------------------------------------------------------------------
    if ((opcode & 0xC7) == 0x00)
    {
        //---------------------------------------------------------------------
        if (!opcode || opcode == 0x08)
            return 0;
        //---------------------------------------------------------------------
        int offs = (signed char)cpu.DirectRm(readptr++);
        unsigned addr = unsigned(offs + int(readptr)) | TWF_BRANCH;
        if (opcode == 0x18)
            return addr;                                        // jr
        //---------------------------------------------------------------------
        if (opcode == 0x10)
            return (cpu.b==1)? 0 : addr | TWF_LOOPCMD;          // djnz
        //---------------------------------------------------------------------
        unsigned char flag = flags[(opcode >> 4) & 1];          // jr cc
        unsigned char res = cpu.f & flag;
        if (!(opcode & 0x08))
            res ^= flag;
        //---------------------------------------------------------------------
        return res  ?   addr | TWF_LOOPCMD :
                        0;
        //---------------------------------------------------------------------
    }
    return 0;
}
//=============================================================================


//=============================================================================
static unsigned trcurs_y;
unsigned asmii;
static char asmpc[64], dumppc[12];
const unsigned cs[3][2] = { {0,4}, {5,10}, {16,16} };

//=============================================================================
// îáíîâëåíèå îêíà äèçàñìà â äåáàãåðå

void showtrace()
{

#define DBG_ATTR_TITLES         0x5D//0x71      //white blue


        char trace_follow_regs_text[10];

            switch (conf.trace_follow_regs)
            {
                case REG_AF:    sprintf( trace_follow_regs_text, "(AF)");       break;
                case REG_BC:    sprintf( trace_follow_regs_text, "(BC)");       break;
                case REG_DE:    sprintf( trace_follow_regs_text, "(DE)");       break;
                case REG_HL:    sprintf( trace_follow_regs_text, "(HL)");       break;
                case REG_AF1:   sprintf( trace_follow_regs_text, "(AF\')");     break;
                case REG_BC1:   sprintf( trace_follow_regs_text, "(BC\')");     break;
                case REG_DE1:   sprintf( trace_follow_regs_text, "(DE\')");     break;
                case REG_HL1:   sprintf( trace_follow_regs_text, "(HL\')");     break;
                case REG_IX:    sprintf( trace_follow_regs_text, "(IX)");               break;
                case REG_IY:    sprintf( trace_follow_regs_text, "(IY)");               break;
                case REG_SP:    sprintf( trace_follow_regs_text, "(SP)");               break;
                case REG_PC:    sprintf( trace_follow_regs_text, "(PC)");               break;
                default:        sprintf( trace_follow_regs_text, "(None)");     break;
            }

                            tprint(     trace_x + 26,
                                        trace_y - 1,
                                        trace_follow_regs_text,
                                        DBG_ATTR_TITLES
                              );
               
    //printf("showtrace()\n");

//ïåðåìåñòèòü â debug.h !!!!
#define DBG_ATTR_BCKGRND                0x00    //0     0
#define DBG_ATTR_BCKGRND_ACTIVE         0x10    //blue  0
#define DBG_ATTR_BCKGRND_BRIGHT         0X80    //br+   0

#define DBG_ATTR_TRACE_LINES            0x0F    //0             br+WHITE
#define DBG_ATTR_TRACE_LINES_ROM        0x07    //0             WHITE


#define DBG_ATTR_TRACE_BREAK_EX         0x0A    //0             red


#define DBG_ATTR_TRACE_BREAK_R_BACK     0x40    //red           0
#define DBG_ATTR_TRACE_BREAK_W_BACK     0x20    //green         0
#define DBG_ATTR_TRACE_BREAK_RW_BACK    0x60    //yellow        0
#define DBG_ATTR_TRACE_REG_PC_BACK      0xD0    //br+WHITE      0
#define DBG_ATTR_TRACE_REG_FOLLOW_BACK  0xF0    //br+WHITE      0



#define DBG_ATTR_TRACE_SELECTED         0xB0    //br+MAGENTAA   0


#define DBG_ATTR_TRACE_BRANCH_DIRECTION         0x0A    //0     br+RED
#define DBG_ATTR_TRACE_BRANCH_DIRECTION_INV     0x0D    //0     br+CYAN

#define DBG_ATTR_TRACE_BRANCH_DESTINATION       0x0D    //0     br+CYAN

#define DBG_ATTR_TRACE_CURRENT_Z80              0x5D//0x70      //white 0
#define DBG_ATTR_TRACE_LAST_BRANCH              0x5D//0x70      //white 0



/*
ìàñèâ õðàíèò àäðåñà âñåõ îòîáðàæàåìûõ ñòðîê â äåáàãåðå
cpu.trpc[00] - 00E5
cpu.trpc[01] - 00E7
cpu.trpc[02] - 00E8

cpu.trpc[18] - 0109
cpu.trpc[19] - 010C
cpu.trpc[20] - 010F

+ åùå ñòðîêà ñ àäðåñîì íà÷àëà ñëåäóþùåé ñòðàíèöû
cpu.trpc[21] - 0112
*/



//    trace_follow_regs = 4;


restart_showtrace:


   
    //trace_PC_in_view = 0;
    trace_follow_regs_in_view = 0;

    Z80 &cpu = CpuMgr.Cpu();
//  char line[ 40];             //Alone Coder 0.36.7
    char line[ 16 + 129];       //Alone Coder 0.36.7

    cpu.trace_curs &= 0xFFFF;
    cpu.trace_top &= 0xFFFF;
    cpu.pc &= 0xFFFF;
    cpu.trace_mode = (cpu.trace_mode + 3) % 3;

    cpu.pc_trflags = tracewndflags();
    cpu.nextpc = (cpu.pc_trflags & TWF_HALTCMD)  ?  (cpu.pc_trflags & 0xFFFF):
                                                    ((cpu.pc + unsigned( disasm_line( cpu.pc, line))) & 0xFFFF );
    unsigned pc = cpu.trace_top;
    asmii = -1U;        //êóðñîð â íå ïîëÿ çðåíèÿ
   
//  unsigned char atr0 = (activedbg == WNDTRACE)   ?    W_SEL : //0x17
//                                                      W_NORM; //0x07

    unsigned char attr1;        //temp attr
    unsigned char current_back_attr = (activedbg == WNDTRACE)  ?  DBG_ATTR_BCKGRND_ACTIVE :     //(âûäåëåííîå îêíî)
                                                                  DBG_ATTR_BCKGRND;
                                                               
    unsigned char attr_lines = (current_back_attr | DBG_ATTR_TRACE_LINES);
    unsigned char attr_lines_rom = (current_back_attr | DBG_ATTR_TRACE_LINES_ROM);
    //-------------------------------------------------------------------------
    unsigned ii; //Alone Coder 0.36.7
   
    //-------------------------------------------------------------------------

    for (ii = 0;    ii < trace_size;    ii++)
    {
        pc &= 0xFFFF;
        cpu.trpc[ ii] = pc;
        int len = disasm_line( pc, line);
     
        //---------------------------------------------------------------------
        char *ptr = line + strlen( line);       //âèäèìî çà÷èñòêà ñòðîêè
        //---------------------------------------------------------------------
        while (ptr < line + 32)
            *ptr++ = ' ';
        //---------------------------------------------------------------------
        line[ 32] = 0;
        //---------------------------------------------------------------------


       
#define FLAG_FOLLOW     0x01
#define FLAG_BP_X       0x02
#define FLAG_BP_R       0x04
#define FLAG_BP_W       0x08

#define FLAG_PC         0x10    //+FLAG_FOLLOW

        //---------------------------------------------------------------------
        //attr1 = attr_lines;

        attr1 = (bankr[ (pc >> 14) & 3] != bankw[ (pc >> 14) & 3])  ?  attr_lines_rom   :
                                                                       attr_lines ;

       
        int temp_line_flags = 0;
        //int temp_line_pc_flag = 0;
       
        //---------------------------------------------------------------------
        if (pc == (cpu.pc & 0xFFFF))
        {
            temp_line_flags |= FLAG_PC;
        }
        //---------------------------------------------------------------------
        int follow_regs_value;
       
        if (conf.trace_follow_regs == REG_AF)   follow_regs_value = cpu.af;
        if (conf.trace_follow_regs == REG_BC)   follow_regs_value = cpu.bc;
        if (conf.trace_follow_regs == REG_DE)   follow_regs_value = cpu.de;
        if (conf.trace_follow_regs == REG_HL)   follow_regs_value = cpu.hl;
                                     
        if (conf.trace_follow_regs == REG_AF1)  follow_regs_value = cpu.alt.af;
        if (conf.trace_follow_regs == REG_BC1)  follow_regs_value = cpu.alt.bc;
        if (conf.trace_follow_regs == REG_DE1)  follow_regs_value = cpu.alt.de;
        if (conf.trace_follow_regs == REG_HL1)  follow_regs_value = cpu.alt.hl;
                                     
        if (conf.trace_follow_regs == REG_IX)   follow_regs_value = cpu.ix;
        if (conf.trace_follow_regs == REG_IY)   follow_regs_value = cpu.iy;
        if (conf.trace_follow_regs == REG_SP)   follow_regs_value = cpu.sp;
        if (conf.trace_follow_regs == REG_PC)   follow_regs_value = cpu.pc;

        follow_regs_value &= 0xFFFF;    //òê â ñòàðøèõ áèòàõ ìîæåò áûòü ëåâûé ìóñîð ÐÅÀËÜÍÎ!!!
    //-------------------------------------------------------------------------
    // Åñëè ñëåäèì çà êàêèì òî ðåãèñòðîì
    if (conf.trace_follow_regs)
    {
        if (pc == follow_regs_value)
        {
            temp_line_flags |= FLAG_FOLLOW;
            trace_follow_regs_in_view = 1;      //trace_PC_in_view = 1; }
        }
    }
    //-------------------------------------------------------------------------
    // Åñëè íå ñëåäèì
    else
    {
        trace_follow_regs_in_view = 1;
        conf.trace_follow_request = 0;
    }
    //-------------------------------------------------------------------------
   
       
//      if (pc == cpu.pc) { temp_line_flags |= FLAG_PC; trace_follow_regs_in_view = 1; } //trace_PC_in_view = 1; }
       
       
        if (cpu.membits[ pc] & MEMBITS_BPX)     temp_line_flags |= FLAG_BP_X;
        if (cpu.membits[ pc] & MEMBITS_BPR)     temp_line_flags |= FLAG_BP_R;
        if (cpu.membits[ pc] & MEMBITS_BPW)     temp_line_flags |= FLAG_BP_W;
        //---------------------------------------------------------------------
        switch ((temp_line_flags & (FLAG_BP_X | FLAG_BP_R | FLAG_BP_W)))
        {
            //X only ----------------------------------------------------------
            case (FLAG_BP_X):                           //...O
                attr1 = (attr1 & 0xF0) | DBG_ATTR_TRACE_BREAK_EX;       break;  //+ back
            //RW --------------------------------------------------------------
            case (FLAG_BP_R):                           //..O.
                attr1 = (attr1 & 0x0F) | DBG_ATTR_TRACE_BREAK_R_BACK;   break;  //+ ink
            case (FLAG_BP_W):                           //.O..
                attr1 = (attr1 & 0x0F) | DBG_ATTR_TRACE_BREAK_W_BACK;   break;  //+ ink
            case (FLAG_BP_R | FLAG_BP_W):               //.OO.
                attr1 = (attr1 & 0x0F) | DBG_ATTR_TRACE_BREAK_RW_BACK;  break;  //+ ink
            //RW + X ----------------------------------------------------------
            case (FLAG_BP_X | FLAG_BP_R):               //..OO
                attr1 = DBG_ATTR_TRACE_BREAK_EX | DBG_ATTR_TRACE_BREAK_R_BACK;  break;
            case (FLAG_BP_X | FLAG_BP_W):               //.O.O
                attr1 = DBG_ATTR_TRACE_BREAK_EX | DBG_ATTR_TRACE_BREAK_W_BACK;  break;
            case (FLAG_BP_X | FLAG_BP_R | FLAG_BP_W):   //.OOO
                attr1 = DBG_ATTR_TRACE_BREAK_EX | DBG_ATTR_TRACE_BREAK_RW_BACK; break;
        }
        //---------------------------------------------------------------------
        switch ((temp_line_flags & (FLAG_BP_X | FLAG_PC | FLAG_FOLLOW)))
        {      
            //Follow ïîâåðx PC  -----------------------------------------------
            case (FLAG_FOLLOW):                        
            case (FLAG_FOLLOW | FLAG_PC):              
                attr1 = DBG_ATTR_TRACE_REG_FOLLOW_BACK;
                break;
            //Follow ïîâåðõ PC + X --------------------------------------------
            case (FLAG_BP_X | FLAG_FOLLOW):                            
            case (FLAG_BP_X | FLAG_FOLLOW | FLAG_PC):          
                attr1 = DBG_ATTR_TRACE_REG_FOLLOW_BACK | DBG_ATTR_TRACE_BREAK_EX;
                break;
            //PC --------------------------------------------------------------
            case (FLAG_PC):    
                attr1 = DBG_ATTR_TRACE_REG_PC_BACK;
                break;         
            //PC + X ----------------------------------------------------------
            case (FLAG_PC | FLAG_BP_X):        
                attr1 = DBG_ATTR_TRACE_REG_PC_BACK | DBG_ATTR_TRACE_BREAK_EX;
                break;
            //-----------------------------------------------------------------
        }
           

               

//      //---------------------------------------------------------------------
//      // àòðèáóò ñòðîêè ñ (òåêóùèì PC) / (îáû÷íàÿ ñòðîêà)
//      attr1 = (pc == cpu.pc)  ?       DBG_ATTR_TRACE_REG_PC_BACK :    //W_TRACEPOS : 
//                                      attr_lines;                     //atr0;
//      //---------------------------------------------------------------------


//      // àòðèáóò âñåé ñòðîêè ñ áðÿêîì
//      //                                      òàê æå ïîòîì ìîæíî áóäåò îòîáðàæàòü ðàçíûå âèäû áðÿêîâ
//      //                                      ðàçíûìè öâåòàìè
//
//      if (cpu.membits[pc] & MEMBITS_BPX)      //EX
//      {
//              attr1 = (attr1 & 0xF0) | DBG_ATTR_TRACE_BREAK_EX;       // + back
//      }

       
                // TEZT !!!!!!!!!!!!!1
                char labels_line[ 16 + 129];
               
                if (get_labels( pc, labels_line))
                {
                    tprint(     trace_x,
                                (trace_y + ii),
                                labels_line,
                                ((current_back_attr & 0xF0) | 0x0E)     //F)
                                );
                               
                    //trace_y_displace++;
                    //trace_size_1--;
                    ii++;
                    cpu.trpc[ ii] = pc;
                }
                // TEZT !!!!!!!!!!!!!1
               
               

        //---------------------------------------------------------------------
        tprint(         trace_x,
                        (trace_y + ii),         //trace_y + ii,
                        line,
                        attr1
               );
               
        //---------------------------------------------------------------------
        // âûäåëåíèå ïîëîæåíèÿ êóðñîðà â îêíå äèçàñìà
        // ÍÅ ÍÀ ÂÑÞ ÑÒÐÎÊÓ! à òîëüêî â àêòèâíîì ñòîëáöå
       
       
        if (pc == cpu.trace_curs)
        {
            asmii = ii;                         // óñòàíîâêà "êóðñîðà ïî ðåàëüíîìó ïîëîæåíèþ
            cpu.graph_trace_cursor_pos = ii;    // [NS]
            //-----------------------------------------------------------------
            if (activedbg == WNDTRACE)
            {
                for (unsigned q = 0;    q < cs[ cpu.trace_mode][ 1];    q++)
                {
                    txtscr[     s80 * s30               +
                                (trace_y + ii) * s80    +
                                trace_x                 +
                                cs[ cpu.trace_mode][ 0] +
                                q
                           ] = (DBG_ATTR_TRACE_SELECTED);       //W_CURS;
                }
            }
            //-----------------------------------------------------------------
        }
        //---------------------------------------------------------------------
        if (cpu.pc_trflags & TWF_BRANCH)
        {
            //-----------------------------------------------------------------
            if (pc == cpu.pc)
            {
                unsigned addr = cpu.pc_trflags & 0xFFFF;
                //-------------------------------------------------------------
                // ñèìâîë ñòðåëî÷êè íàïðàâëåíèÿ ïåðåõîäà
                unsigned arr = (addr <= cpu.pc)  ?  0x18 :
                                                    0x19;       // up/down arrow
                attr1 = (       (pc == cpu.trace_curs)  &&
                                (activedbg == WNDTRACE) &&
                                (cpu.trace_mode == 2)
                         )  
                            ?   // ñòðåëî÷êà íàïðàâëåíèÿ ïåðåõîäà ïîä êóðñîðîì
                                DBG_ATTR_TRACE_BRANCH_DIRECTION_INV :   //W_TRACE_JINFO_CURS_FG :  // 0x0D 0 br+CYAN
                                // ñòðåëî÷êà íàïðàâëåíèÿ
                                DBG_ATTR_TRACE_BRANCH_DIRECTION;        //W_TRACE_JINFO_NOCURS_FG; // 0x02 0 red       
                //-------------------------------------------------------------
                // îòðèñîâêà ñòðåëî÷êà íàïðàâëåíèÿ ïåðåõîäà ââåðõ/âíèç     
                if (cpu.pc_trflags & TWF_BRADDR)
                {
                    sprintf(    line,
                                "%04X%c",
                                addr,
                                int( arr)
                            );
                // àäðåñ + ñòðåëî÷êà ïðè RET    (5B13 C9 ret   0038^)
                    tprint_fg(  trace_x + 32 - 5,
                                trace_y + ii,
                                line,
                                attr1   //ink only      //color
                              );
                }
                else
                {
                // ñòðåëî÷êà ïðè JP CALL        (0043 2003 jr nz,0048   v)
                    tprint_fg(  trace_x + 32 - 1,
                                trace_y + ii,
                                (char*) &arr,
                                attr1   //ink only      //color
                              );
                }
             }
            //-----------------------------------------------------------------
            // ñòðåëî÷êà âîçëå àäðåñà êóäà ïðîèñõîäèò ïåðåõîä   (5B00 F5 push af   <)
            if (pc == (cpu.pc_trflags & 0xFFFF))
            {
                unsigned arr = 0x11; // left arrow
                tprint_fg(      trace_x + 32 - 1,
                                trace_y + ii,
                                (char*) &arr,
                                DBG_ATTR_TRACE_BRANCH_DESTINATION       //W_TRACE_JARROW_FOREGR //0x0D  br+CYAN
                          );
            }
            //-----------------------------------------------------------------
        }
        //---------------------------------------------------------------------
        pc += unsigned( len);
    }
    //-------------------------------------------------------------------------
    cpu.trpc[ ii] = pc;         // îáíîâëÿåì ìàñèâ àäðåñîâ
    //-------------------------------------------------------------------------
    // íà âñÿêèé
    cpu.trace_top &= 0xFFFF;    // [NS]
    cpu.trace_curs &= 0xFFFF;
                                       
    if (conf.trace_follow_request)                                      // [NS]
    {
        //printf("trace_follow_request \n");
        //if (!trace_PC_in_view)  //???
        if ((!trace_follow_regs_in_view) && (conf.trace_follow_regs))
        {
            //printf("(!trace_PC_in_view)\n");
            switch (conf.trace_follow_regs)
            {
                case REG_AF: cpu.trace_top = cpu.trace_curs = cpu.af;   break;
                case REG_BC: cpu.trace_top = cpu.trace_curs = cpu.bc;   break;
                case REG_DE: cpu.trace_top = cpu.trace_curs = cpu.de;   break;
                case REG_HL: cpu.trace_top = cpu.trace_curs = cpu.hl;   break;
                case REG_AF1: cpu.trace_top = cpu.trace_curs = cpu.alt.af;      break;
                case REG_BC1: cpu.trace_top = cpu.trace_curs = cpu.alt.bc;      break;
                case REG_DE1: cpu.trace_top = cpu.trace_curs = cpu.alt.de;      break;
                case REG_HL1: cpu.trace_top = cpu.trace_curs = cpu.alt.hl;      break;
                case REG_IX: cpu.trace_top = cpu.trace_curs = cpu.ix;   break;
                case REG_IY: cpu.trace_top = cpu.trace_curs = cpu.iy;   break;
                case REG_SP: cpu.trace_top = cpu.trace_curs = cpu.sp;   break;
                case REG_PC: cpu.trace_top = cpu.trace_curs = cpu.pc;   break;
            }
            //cpu.trace_top = cpu.trace_curs = cpu.pc;
            //printf("restart_showtrace ");
            goto restart_showtrace;
        }
        else
        {
            //printf("trace_follow_request = 0;");
            conf.trace_follow_request = 0;
        }
    }
 
    //-------------------------------------------------------------------------
    // Kóðñîð ïîñðåäè êîìàíäû !!!                       // [NS]
    // èëè page down
    if (asmii == -1U)                          
    {
        // printf("(asmii == -1U) ");
        // ïåðåñòàâëÿåì âåðõ íà ïîëîæåíèå êóðñîðà è äèçàñìèì åùå ðàç
       
        //---------------------------------------------------------------------
        // Page down
        if (cpu.graph_trace_cursor_pos == (trace_size - 1))
        {
            cpu.trace_curs = cpu.trpc[ cpu.graph_trace_cursor_pos];
        }
        //---------------------------------------------------------------------
        // Êóðñîð ïîñðåäè êîìàíäû
        // òåêóùèìè ñðåäñòâàìè ìîæåì îòäèçàñìèòü òîëüêî êîãäà îíî â trace_top
        //      íóæíî ïðàâèòü äèçàñìåð äëÿ îáðàáîòêè êóðñîðà ïîñðåäè êîìàíäû
        else
        {
            cpu.graph_trace_cursor_pos = 0;
            cpu.trace_top = cpu.trace_curs;     //cpu.trpc[0]; 
            //cpu.trace_curs = cpu.trpc[0];
        }
        //---------------------------------------------------------------------
        //printf("restart_showtrace 2");
        goto restart_showtrace;
    }
    //-------------------------------------------------------------------------
   


    unsigned char dbuf[16];
   //-------------------------------------------------------------------------
    unsigned i; //Alone Coder
    for (/*int*/ i = 0;    i < 16;    i++)
        dbuf[i] = cpu.DirectRm( cpu.trace_curs + i);
    //-------------------------------------------------------------------------
    ptrdiff_t len = disasm(     dbuf,
                                cpu.trace_curs,
                                0
                           ) - dbuf;
    strcpy( asmpc, asmbuf);

    //-------------------------------------------------------------------------
    // îïêîäû êîìàíä â ðåæèìå ðåäàêòèðîâàíèÿ
    for (/*int*/ i = 0;    i < len && i < 5;    i++)
        sprintf(        dumppc + i * 2,
                        "%02X",
                        cpu.DirectRm(cpu.trace_curs + i)
                );

    //-------------------------------------------------------------------------
    // ïå÷àòü òåêóùåãî z80
    char cpu_num[ 10];
//    _snprintf(        cpu_num,
//                      sizeof(cpu_num),
//                      "Z80(%u)",
//                      CpuMgr.GetCurrentCpu()
//              );
    if ( (CpuMgr.GetCurrentCpu()) == 0 )        //(NS)
    {
        sprintf( cpu_num, "ZX-CPU" );//"ZX-Z80" );      //È çà÷åì íàì íóæíî áûëî óãàäûâàòü ãäå ìû ùàñ?
    }
    else
    {
        sprintf( cpu_num, "GS-CPU" );//"GS-Z80" );
    }
             
    tprint(     trace_x,
                trace_y-1,
                cpu_num,
                DBG_ATTR_TRACE_CURRENT_Z80      //W_TITLE
           );
    //-------------------------------------------------------------------------
    // ïå÷àòü àäðåñà ïîñëåäíåãî ïåðåõîäà
    char lbr[18];       //lbr[5];
    _snprintf(  lbr,
                sizeof(lbr),
                "Last branch(%04hX)",   //"%04hX",
                cpu.last_branch
              );
    tprint(     trace_x+8,
                trace_y-1,
                lbr,
                DBG_ATTR_TRACE_LAST_BRANCH      //W_TITLE
          );
    //-------------------------------------------------------------------------
    // ðàìî÷êà
    frame(      trace_x,
                trace_y,
                32,
                trace_size,
                FRAME
         );
    //-------------------------------------------------------------------------
   
} //void showtrace()
//=============================================================================


//=============================================================================
void c_lbl_import() //menu for importing labels from XAS/ALASM ???      // â ìåíþ WNDTRACE äåáàãåðà
{                                                                       // è "cpu.importl" õîòêåé
   mon_labels.import_menu();                                            // ñêîðåé âñåãî óæå ñëîìàí?
}
//=============================================================================

      /* ------------------------------------------------------------- */
static unsigned save_pos[8] = { -1U,-1U,-1U,-1U,-1U,-1U,-1U,-1U };
static unsigned save_cur[8] = { -1U,-1U,-1U,-1U,-1U,-1U,-1U,-1U };
static unsigned stack_pos[32] = { -1U }, stack_cur[32] = { -1U };

//=============================================================================
void push_pos();                                                        //????
void push_pos()
{
    Z80 &cpu = CpuMgr.Cpu();
    memmove(&stack_pos[1], &stack_pos[0], sizeof stack_pos - sizeof *stack_pos);
    memmove(&stack_cur[1], &stack_cur[0], sizeof stack_cur - sizeof *stack_cur);
    stack_pos[0] = cpu.trace_top; stack_cur[0] = cpu.trace_curs;
}
//=============================================================================


//=============================================================================
// Ïîëó÷åíèå àäðåñà ïðåäûäóùåé êîìàíäû
//    õç êàê îíî ðàáîòàåò è íà ñêîëüêî òî÷íî
static unsigned cpu_up(unsigned ip)
{
    Z80 &cpu = CpuMgr.Cpu();
    //printf("ip = %X\n",ip);
    unsigned char buf1[0x10];
    unsigned p1 = (ip > sizeof buf1)  ? ip - sizeof buf1 :
                                        0;
    //-------------------------------------------------------------------------
    for (unsigned i = 0;    i < sizeof buf1;    i++)
        buf1[i] = cpu.DirectRm(p1 + i);
    //-------------------------------------------------------------------------
    const unsigned char *dispos = buf1;
    const unsigned char *prev;
    //-------------------------------------------------------------------------
    do {
        prev = dispos;
        dispos = disasm(dispos, 0, 0);
    } while ((unsigned)(dispos - buf1 + p1) < ip);
    //-------------------------------------------------------------------------
    return unsigned(prev - buf1 + p1);
}
//=============================================================================




//=============================================================================
// óñòàðåâøèé goto adress â îêíå äèçàñìà                // "cpu.goto" õîòåêåé
// òàêîé æå êàê â îêíå ìåìîðè âèåâåðà
// æìåì êíîïêó, ââîäèì àäðåñ ðó÷êàìè
void cgoto()                                           
{
    Z80 &cpu = CpuMgr.Cpu();
    int v = input4(trace_x, trace_y, cpu.trace_top);
    if (v != -1)
        cpu.trace_top = cpu.trace_curs = unsigned(v);
}
//=============================================================================


//=============================================================================
// SET_PC_TO_CURSOR                                     // â ìåíþ WNDTRACE äåáàãåðà
void csetpc()                                           // è "cpu.setpc" õîòêåé
{
    Z80 &cpu = CpuMgr.Cpu();
    cpu.pc = cpu.trace_curs;
}
//=============================================================================


//=============================================================================
void center()   // edit instruction ???
{                                                       //"cpu.asm" õîòêåé
    //-------------------------------------------------------------------------
    // íåëüçÿ ðåäàêòèðîâàòü êîãäà êóðñîð íå íàéäåí !!!!
    // (ïîñðåäè êîìàíäû) íóæíî ðåäèçàñìèòü
    if (asmii == -1U)
    {
        printf("asmii/trace cursor error\n");
        return;
    }
    //-------------------------------------------------------------------------
    Z80 &cpu = CpuMgr.Cpu();
    //-------------------------------------------------------------------------
    // addr
    if (!cpu.trace_mode) // = 0
        sprintf(        str,
                        "%04X",
                        cpu.trace_curs
                );
    //-------------------------------------------------------------------------
    // dump
    else if (cpu.trace_mode == 1)
        strcpy( str, dumppc);
    //-------------------------------------------------------------------------
    // disasm
    else
        strcpy( str, asmpc);
    //-------------------------------------------------------------------------
    // â ñëó÷àå âõîäà â ðåæèì ðåäàêòèðîâàíèÿ íà÷àëîì ââîäà òåêñòà
    // èäåò î÷èñòêà âñåé ñòðîêè
    //    ÍÎ center ìîæåò áûòü íå òîëüêî íà Enter-e !!!!!
    //    íóæíà ïðîâåðêà èìåííî íà center hotkey
    //    èíà÷å íåëüçÿ ïåðåíàçíà÷èòü center !!!!! [NS]
    if (input.lastkey != VK_RETURN)
    {
        //---------------------------------------------------------------------
        // ïðÿìîé ââîä çíà÷åíèé â ñòîëáöå àäðåñà íå î÷èùàåò ñòðîêó àäðåñà
        if (cpu.trace_mode != 0) // addr
        {
            *str = 0;
        }
        //---------------------------------------------------------------------
        // øëÿïà - óùåðáíûé ââîä çíà÷åíèÿ êîòîðûì ìû âîøëè â ðåæèì ðåäàêòèðîâàíèÿ
        PostThreadMessage(      GetCurrentThreadId(),
                                WM_KEYDOWN,
                                input.lastkey,
                                1
                        );
    }
    //-------------------------------------------------------------------------
    for (    ;    ;    )
    {
        //---------------------------------------------------------------------
        // asmii êàê ðàç òèïî òåêóùèé êóðñîð
       
        if (!inputhex(  (trace_x + cs[ cpu.trace_mode][ 0]),
                        (trace_y + trcurs_y + asmii),           //trcurs_y âîîáùå íå èñïîëüçóåòñî
                        (cs[ cpu.trace_mode][ 1]),
                        (cpu.trace_mode < 2),           //0...1 - hex=TRUE 2 - hex=FALSE
                        (cpu.trace_mode == 2) ? FALSE : //ëþäñêîé ñïîñîá ââîäà òåêñòà
                                                TRUE    //hex-û æå óäîáíî ââîäèòü insert-îì
                      )
         )
        {
            break;
        }
        //---------------------------------------------------------------------
        // addr
        if (!cpu.trace_mode)
        {
            push_pos();
            sscanf(     str,
                        "%X",
                        &cpu.trace_top
                   );
            cpu.trace_curs = cpu.trace_top;
            //-----------------------------------------------------------------
            printf("asmii %d ",asmii);
            for (unsigned i = 0;    i < asmii;    i++)
            {
                printf("** ");
                cpu.trace_top = cpu_up(cpu.trace_top);
            }
            printf("\n");
            //-----------------------------------------------------------------
            break;
        }
        //---------------------------------------------------------------------
        // dump
        else if (cpu.trace_mode == 1)
        {
            char *p; //Alone Coder 0.36.7
            //-----------------------------------------------------------------
            for (/*char * */p = str + strlen(str) - 1;    p >= str && *p == ' ';    *p-- = 0);
            //-----------------------------------------------------------------
            unsigned char dump[8];
            unsigned i;
            //-----------------------------------------------------------------
            for (p = str, i = 0;    ishex(*p) && ishex(p[1]);    p += 2)
                dump[i++] = hex(p);
            //-----------------------------------------------------------------
            if (*p)
                continue;
            //-----------------------------------------------------------------
            for (unsigned j = 0;    j < i;    j++)
                cpu.DirectWm(cpu.trace_curs+j, dump[j]);
            //-----------------------------------------------------------------
            break;
        }
        //---------------------------------------------------------------------
        // disasm
        else
        {
            unsigned sz = assemble_cmd((unsigned char*)str, cpu.trace_curs);
            //-----------------------------------------------------------------
            if (sz)
            {
                //-------------------------------------------------------------
                for (unsigned i = 0;    i < sz;    i++)
                    cpu.DirectWm(cpu.trace_curs + i, asmresult[i]);
                //-------------------------------------------------------------
                showtrace();
                void cdown();
                cdown();
                break;
            }
            //-----------------------------------------------------------------
        }
    }
}
//=============================================================================


//=============================================================================
char dispatch_trace()                           //????
{
// if (input.lastkey >= 'A' && input.lastkey < 'Z')
// {
        //printf("dispatch_trace %c\n",input.lastkey);
// (NS) ââîä öèôð æî òîæû íóæåí â îêíå äèçàñìà
   if ((input.lastkey >= '0' && input.lastkey <= '9') || (input.lastkey >= 'A' && input.lastkey <= 'Z'))
   {
       center();
       return 1;
   }
   return 0;
}
//=============================================================================
// FIND TEXT â îêíå äèçàñìà                     // â ìåíþ WNDTRACE äåáàãåðà
void cfindtext()                                // è "cpu.findtext" õîòêåé
{
   Z80 &cpu = CpuMgr.Cpu();
   unsigned char oldmode = editor; editor = ED_MEM;
   int rs = find1dlg(cpu.trace_curs);
   editor = oldmode;
   if (rs != -1)
       cpu.trace_top = cpu.trace_curs = unsigned(rs);
}
//=============================================================================
// FIND CODE â îêíå äèçàñìà                     // â ìåíþ WNDTRACE äåáàãåðà
void cfindcode()                                // è "cpu.findcode" õîòêåé
{
   Z80 &cpu = CpuMgr.Cpu();
   unsigned char oldmode = editor; editor = ED_MEM;
   int rs = find2dlg(cpu.trace_curs);
   editor = oldmode;
   if (rs != -1)
       cpu.trace_top = cpu.trace_curs = unsigned(rs);
}
//=============================================================================
// set breakpoint                               // â ìåíþ WNDTRACE äåáàãåðà
void cbpx()                                     // è "cpu.bpx" õîòêåé
{                      
    Z80 &cpu = CpuMgr.Cpu();
    cpu.membits[ cpu.trace_curs] ^= MEMBITS_BPX;
}
//=============================================================================v
void cbpr()                                     // â ìåíþ WNDTRACE äåáàãåðà
{                                               // [NS]
    Z80 &cpu = CpuMgr.Cpu();                   
    cpu.membits[ cpu.trace_curs] ^= MEMBITS_BPR;
}
//=============================================================================
void cbpw()                                     // â ìåíþ WNDTRACE äåáàãåðà
{                                               //(NS)
    Z80 &cpu = CpuMgr.Cpu();                   
    cpu.membits[cpu.trace_curs] ^= MEMBITS_BPW;
}
//=============================================================================






//=============================================================================
// GOTO PC                                      // â ìåíþ WNDTRACE äåáàãåðà
void cfindpc()                                  // è "cpu.findpc" õîòêåé
{
    //printf("cfindpc\n");
    Z80 &cpu = CpuMgr.Cpu();
    cpu.trace_top = cpu.trace_curs = cpu.pc;
   
//    cup();    è äàæå òàêàÿ êîíñòðóêöèÿ íå ðàáîòàòåò
//    cup();    õîòÿ íå ðàáîòàåò òîëüêî íà öåïî÷êå ðàçíî÷èòàåìûõ îïêîäîâ?
//    cup();
//    cup();
//    cup();
//    cpu.trace_curs = cpu.pc;
                                        //íîðìàëüíî îòñòóïèòü ñ çàïàñîì íå ïîëó÷àåòñî
                                        //íà÷àëüíûé àäðåñ ìîæåò ïîïàñòü íà ïîë êîìàíäû
                                        //è è òîãäà àäðåñ òåêóùåãî PC íå îòîáðàçèòñî
}
//=============================================================================



//=============================================================================
// ïåðåõîä ê àäðåñó â îêíå äèçàñìà                                      // [NS]
//    èç îêíà äèçàñìà

void mon_goto_disasm_addr( unsigned addr)                              
{
//  unsigned addr = cpu.af;
    addr &= 0xFFFF;                     // îáðåçêà òê ìîæåò áûòü ôèãíÿ âûøî
    Z80 &cpu = CpuMgr.Cpu();
    cpu.trace_top = cpu.trace_curs = addr;
}

void mon_goto_disasm_rAF()      { Z80 &cpu = CpuMgr.Cpu();      mon_goto_disasm_addr( cpu.af);  }
void mon_goto_disasm_rBC()      { Z80 &cpu = CpuMgr.Cpu();      mon_goto_disasm_addr( cpu.bc);  }
void mon_goto_disasm_rDE()      { Z80 &cpu = CpuMgr.Cpu();      mon_goto_disasm_addr( cpu.de);  }
void mon_goto_disasm_rHL()      { Z80 &cpu = CpuMgr.Cpu();      mon_goto_disasm_addr( cpu.hl);  }
                                 
void mon_goto_disasm_rAF1()     { Z80 &cpu = CpuMgr.Cpu();      mon_goto_disasm_addr( cpu.alt.af);      }
void mon_goto_disasm_rBC1()     { Z80 &cpu = CpuMgr.Cpu();      mon_goto_disasm_addr( cpu.alt.bc);      }
void mon_goto_disasm_rDE1()     { Z80 &cpu = CpuMgr.Cpu();      mon_goto_disasm_addr( cpu.alt.de);      }
void mon_goto_disasm_rHL1()     { Z80 &cpu = CpuMgr.Cpu();      mon_goto_disasm_addr( cpu.alt.hl);      }
                                 
void mon_goto_disasm_rIX()      { Z80 &cpu = CpuMgr.Cpu();      mon_goto_disasm_addr( cpu.ix);  }
void mon_goto_disasm_rIY()      { Z80 &cpu = CpuMgr.Cpu();      mon_goto_disasm_addr( cpu.iy);  }

void mon_goto_disasm_rSP()      { Z80 &cpu = CpuMgr.Cpu();      mon_goto_disasm_addr( cpu.sp);  }
void mon_goto_disasm_rPC()      { Z80 &cpu = CpuMgr.Cpu();      mon_goto_disasm_addr( cpu.pc);  }

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


//=============================================================================
// move cursor up (âèäèìî â îêíå äèçàñìà)                       //"cpu.up" õîòêåé
void cup()                                     
{
    Z80 &cpu = CpuMgr.Cpu();
    //-------------------------------------------------------------------------
    // ïðîñòîé ïåðåõîä â ñåðåäèíå ýêðàíà
    if (cpu.graph_trace_cursor_pos > 0)
    {
        cpu.graph_trace_cursor_pos--;
        cpu.trace_curs = cpu.trpc[ cpu.graph_trace_cursor_pos];
    }  
    //-------------------------------------------------------------------------
    // ñêðîëë ýêðàíà òîëüêî ñ ñàìîé âåðõíåé ïîçèöèè
    else
    {
        //---------------------------------------------------------------------
        // Ïðîñòîé ïåðåõîä
        if (cpu.trace_top > 0x0000)
        {
            cpu.trace_top = cpu.trace_curs = cpu_up(cpu.trace_top);
        }
        //---------------------------------------------------------------------
        // Ïåðåõîä ñ 0x0000 ê 0xFFFF
        else
        {
        //  cpu.trace_top = cpu.trace_curs = 0xFFFF;
            cpu.trace_top = cpu.trace_curs = cpu_up(0x10000);
        }
        //---------------------------------------------------------------------
        cpu.graph_trace_cursor_pos = 0;
    }
    //-------------------------------------------------------------------------
   
   
  // ïåðåâîä êóðñîðà â ñàìûé âåðõ â ëþáîì ñëó÷àå
 //   cpu.trace_curs = cpu.trace_top;
 //   cpu.graph_trace_cursor_pos = 0;
    //-------------------------------------------------------------------------
//    printf("cpu.trpc -");
//    for (int tmp = 0; tmp <= trace_size; tmp++)
//    {
//        //printf("tmp,cpu.trpc[%04d] - %04X\n",tmp,cpu.trpc[tmp]);
//        printf(" %04X",cpu.trpc[tmp]);
//    }
//    printf("\n");
    //-------------------------------------------------------------------------
   
    cpu.trace_top &= 0xFFFF;
    cpu.trace_curs &= 0xFFFF;
   
    //-------------------------------------------------------------------------
    return;
    //-------------------------------------------------------------------------








/*

   Z80 &cpu = CpuMgr.Cpu();








//   printf("cpu.trace_curs %d\n",cpu.trace_curs);
//   printf("cpu.trace_top %d\n",cpu.trace_top);  

    // printf("cup()\n");  


// ìîæåò âîîáùå íå òðîãàòü cpu.trace_curs, cpu.trace_top
// à ñðàçó âûçûâàòü follow PC
// õîòÿ ýòî íàâåðíî áóäåò áîëåå ðåñóðñîåìêî
//      à òàê ìîæíî áóäåò ëàçèòü ïî äèçàñìó ñ çàæàòûì ñòåïîì áåç ïîòåðè êóðñîðà
//      èëè òàì àóòîñòåï/òðåéñ
//              íàâåðíîå òàêîå ëó÷øî âûíåñòè íà îòäåëüíóþ êíîïêó?

 
    signed int trace_top_1;
    //-------------------------------------------------------------------------
    if (cpu.trace_curs < 500)
    {
        //---------------------------------------------------------------------
        if (cpu.trace_top > 0xF000)
        {
            printf("cpu.trace_top > 0xF000\n");
            trace_top_1 = (cpu.trace_top - 0xFFFF) - 1;
        }
        //---------------------------------------------------------------------
        else
        {
            printf("cpu.trace_top = normal\n");
            trace_top_1 = cpu.trace_top;
        }
        //---------------------------------------------------------------------
    }
    //-------------------------------------------------------------------------
   
   
    // êîãäà cpu.trace_top = FFFF à cpu.trace_curs = 0000
    // óñëîâèå íå ñðàáàòûâàåò
    // è òîï-îì ñòàíîâèòñî êóðñîð ñî ñòðàøíûì äåðãîñìûêîì
   
    //printf("cpu.trace_curs %x  cpu.trace_top %x trace_top_1 %d\n",cpu.trace_curs,cpu.trace_top,trace_top_1);

    signed int trace_cursor_1 = cpu.trace_curs;
    // ïî÷åìó òî (cpu.trace_curs > trace_top_1) íå äàåò true â ñëó÷àå (10 > -10) o_O
    // äàæå ïðè -O0
    // íî âûíåñåíî â îòäåëüíóþ ïåðåìåííóþ ðàáîîòàåò
   
    //-------------------------------------------------------------------------
//  if (cpu.trace_curs > cpu.trace_top)
    if (        (trace_cursor_1 > trace_top_1) &&
                (cpu.trace_curs != cpu.trace_top)        //äëÿ ïåðåõîäàà ââåðõ ñ âåðõíåé ñòðîêè
      )    
    {
        //printf("(cpu.trace_curs > trace_top_1) \n");
        //---------------------------------------------------------------------
       
       
        for (unsigned i = 1; i < trace_size; i++)       //trace_size = 21
        {
            //printf(" i %d\n",i);
            if (cpu.trpc[i] == cpu.trace_curs)
            {
                // printf(" cpu.trpc[i] == cpu.trace_curs\n",i);
                cpu.trace_curs = cpu.trpc[i - 1];
                cpu.graph_trace_cursor_pos = i - 1;
                //printf ("cpu.trpc[i-1] %d\n",cpu.trpc[i-1]);
            }
            //printf("i %d\n",i);
        }
        //---------------------------------------------------------------------
    }
    //-------------------------------------------------------------------------
    else
    {
        //ïåðåõîä âûøå ñàìîãî âåðõíåãî ïîëîæåíèÿ
        //---------------------------------------------------------------------
        if (cpu.trace_curs != 0) // [NS]
        {
            cpu.trace_top = cpu.trace_curs = cpu_up(cpu.trace_curs);
            //printf ("1\n");
        }
        //---------------------------------------------------------------------
        else
        {
            //ïåðåõîä ñ 0000 ê FFFF (ðàíüøå óïèðàëîñü è ýòî äèêî áåñèëî)
            cpu.trace_top = cpu.trace_curs = cpu_up(0x10000);
            //printf ("2\n");
        }
        //---------------------------------------------------------------------
    }
    //-------------------------------------------------------------------------
        cpu.trace_top &= 0xFFFF;
        cpu.trace_curs &= 0xFFFF;
 
 
 
 */

 
 
}
//=============================================================================
void cdown()                                            //"cpu.down" õîòêåé
{
    // printf("cdown()\n");
       
    Z80 &cpu = CpuMgr.Cpu();
    //-------------------------------------------------------------------------
    for (unsigned i = 0;    i < trace_size;    i++)
    {
        // printf(" i %d\n",i);
        //---------------------------------------------------------------------
        if (cpu.trpc[ i] == cpu.trace_curs)
        {
            cpu.trace_curs = cpu.trpc[ i + 1];
            cpu.graph_trace_cursor_pos = i + 1;
            //-----------------------------------------------------------------
            if (i + 1 == trace_size)
            {
                // printf(" (i+1 == trace_size)\n",i);
                cpu.trace_top = cpu.trpc[ 1];
            }
            //-----------------------------------------------------------------
            break;
        }
        //---------------------------------------------------------------------
    }
    //-------------------------------------------------------------------------
}
//=============================================================================
// âèäèìî trace_mode 0,1,2 ýòî àäðåñ, îïêîä, äèçàñì ?
// ÷òî èç íèõ êòî íàäî óòîøíÿòü
//=============================================================================
void cleft()  { CpuMgr.Cpu().trace_mode--; }            // "cpu.left" õîòêåé
//=============================================================================
void cright() { CpuMgr.Cpu().trace_mode++; }            // "cpu.right" õîòêåé
//=============================================================================
void chere()    //trace to cursor????                   // â ìåíþ WNDTRACE äåáàãåðà
{                                                       // è "cpu.here" õîòêåé
    //printf("chere()\n");
    Z80 &cpu = CpuMgr.Cpu();
    cpu.dbgbreak = 0;
    dbgbreak = 0;
    cpu.dbgchk = 1;
 
    cpu.dbg_stophere = cpu.trace_curs;
}
//=============================================================================


//=============================================================================
void cpgdn()    //next page                             // "cpu.pgdn" õîòêåé
{
    Z80 &cpu = CpuMgr.Cpu();
   
   
    // âíà÷àëå ïåðåõîä ê ïîñëåäíåé ñòðîêå
    //-------------------------------------------------------------------------
    if (cpu.graph_trace_cursor_pos < (trace_size - 1))
    {
        cpu.trace_curs = cpu.trpc[ trace_size - 1];
        cpu.graph_trace_cursor_pos = trace_size - 1;
    }
    //-------------------------------------------------------------------------
    // Ïåðåõîä íà ñëåä ñòðàíèöó òîëüêî êîãäà êóðñîð â ñàìîì íèçó
    // ïî òèïó explorer.exe
    else        //if (cpu.graph_trace_cursor_pos == (trace_size - 1))
    {
        cpu.graph_trace_cursor_pos = trace_size - 1;
        //---------------------------------------------------------------------
        // óïèðàåìñÿ â 0xFFFF
        if (cpu.trace_curs == 0xFFFF)
        {
            cpu.trace_top = 0xFFFF - (trace_size - 1);
            cpu.trace_curs = 0xFFFF;
            return;
        }
        //---------------------------------------------------------------------
        // ïîñëåäíèå øàãè óìåíüøåííûé è óïèðàþòñî â FFFF
        if ((cpu.trace_top < (0xFFFF - (trace_size - 1))) && (cpu.trace_top > (0xFFFF - (2 * (trace_size - 1)) - 1)))
        {
            //
            //FFEA_FFFE first -> FFEB_FFFF
            //FFD8_FFEC
            //FFD7_FFEB last  -> FFEB_FFFF
            cpu.trace_top = 0xFFFF - (trace_size - 1);
            cpu.trace_curs = 0xFFFF;
        }
        //---------------------------------------------------------------------
        // FFEC...FFFF íîðìàëüíûé pddown
        else
        {
            cpu.trace_top = cpu.trpc[ trace_size];
        }
    }
    //-------------------------------------------------------------------------

    //-------------------------------------------------------------------------    



       

        //      //-------------------------------------------------------------
        //      printf("cpu.trpc -");
        //      for (int tmp = 0; tmp <= trace_size; tmp++)
        //      {
        //          //printf("tmp,cpu.trpc[%04d] - %04X\n",tmp,cpu.trpc[tmp]);
        //          printf(" %04X",cpu.trpc[tmp]);
        //      }
        //      printf("\n");
        //      //-------------------------------------------------------------
   return;
   
   
   
   
   
   
   
   
   
/*             
    Z80 &cpu = CpuMgr.Cpu();
    unsigned curs = 0;
    //-------------------------------------------------------------------------
    for (unsigned i = 0;    i < trace_size;    i++)
        if (cpu.trace_curs == cpu.trpc[i])
            curs = i;
    //-------------------------------------------------------------------------
    cpu.trace_top = cpu.trpc[trace_size];
    showtrace();
    cpu.trace_curs = cpu.trpc[curs];
  */
 
   
}
//=============================================================================


//=============================================================================
void cpgup()            //prev page                     // "cpu.pgup" õîòêåé
{
    Z80 &cpu = CpuMgr.Cpu();
    //-------------------------------------------------------------------------
    // Ïåðåõîä íà ïðåä ñòðàíèöó òîëüêî êîãäà êóðñîð â ñàìîì âåðõó
    // ïî òèïó explorer.exe
    if (cpu.graph_trace_cursor_pos == 0)
    {
        unsigned i;             //Alone Coder 0.36.7
        //---------------------------------------------------------------------
        // òóïî ïîâòîðÿåì 20 ðàç :rofl:
        for (i = 0;    i < trace_size;    i++)
            cpu.trace_top = cpu_up( cpu.trace_top);
        //---------------------------------------------------------------------
    }
    //-------------------------------------------------------------------------
    // ïåðåâîä êóðñîðà â ñàìûé âåðõ â ëþáîì ñëó÷àå
    cpu.trace_curs = cpu.trace_top;
    cpu.graph_trace_cursor_pos = 0;
    //-------------------------------------------------------------------------
//    printf("cpu.trpc -");
//    for (int tmp = 0; tmp <= trace_size; tmp++)
//    {
//        //printf("tmp,cpu.trpc[%04d] - %04X\n",tmp,cpu.trpc[tmp]);
//        printf(" %04X",cpu.trpc[tmp]);
//    }
//    printf("\n");
    //-------------------------------------------------------------------------
    return;
    //-------------------------------------------------------------------------



//    îðèãèíàëüíûé êîä è óùåðáíûé è òóãî îòëàæèâàåìûé
//    unsigned curs = 0;
//    unsigned i;               //Alone Coder 0.36.7
//    //-------------------------------------------------------------------------
//    for (/*unsigned*/ i = 0;    i < trace_size;    i++)
//      if (cpu.trace_curs == cpu.trpc[i])
//          curs = i;
//    //-------------------------------------------------------------------------
//    for (i = 0;    i < trace_size;    i++)
//      cpu.trace_top = cpu_up(cpu.trace_top);
//    //-------------------------------------------------------------------------
//    showtrace();
//    cpu.trace_curs = cpu.trpc[curs];
//              //-------------------------------------------------------------
//              printf("cpu.trpc -");
//              for (int tmp = 0; tmp <= trace_size; tmp++)
//              {
//                  //printf("tmp,cpu.trpc[%04d] - %04X\n",tmp,cpu.trpc[tmp]);
//                  printf(" %04X",cpu.trpc[tmp]);
//              }
//              printf("\n");
//              //-------------------------------------------------------------


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


//=============================================================================
// pop cursor position from jumpstack                   // â ìåíþ WNDTRACE äåáàãåðà
void pop_pos()  //IDA mode                              // è "cpu.back" õîòêåé
{               // back from "goto to branch destination"
                // íà ñàìîì äåëå ýòî Return to previous possition
                // òê ïåðåõîä ïî àäðåñó ïðè ââîäå êèäàåò àäðåñ â ñòåê
   Z80 &cpu = CpuMgr.Cpu();
   if (stack_pos[0] == -1U)
       return;
   cpu.trace_curs = stack_cur[0];
   cpu.trace_top = stack_pos[0];
   memcpy(&stack_pos[0], &stack_pos[1], sizeof stack_pos - sizeof *stack_pos);
   memcpy(&stack_cur[0], &stack_cur[1], sizeof stack_cur - sizeof *stack_cur);
   stack_pos[(sizeof stack_pos / sizeof *stack_pos)-1] = -1U;
}
//=============================================================================



//=============================================================================
// Goto Operand Address                         ZX/GS - ok
// push cursor position and goto instruction operand    // â ìåíþ WNDTRACE äåáàãåðà
void cjump()    // IDA mode                             // "cpu.context" õîòêåé
{               // ïåðåõîä íà àäðåñ îïåðàíäà !!!
    Z80 &cpu = CpuMgr.Cpu();
    char *ptr = nullptr;
    //-------------------------------------------------------------------------
    for (char *p = asmpc;    *p;    p++)
      if (ishex(p[0]) & ishex(p[1]) & ishex(p[2]) & ishex(p[3])) ptr = p;
    //-------------------------------------------------------------------------
    if (!ptr)
        return;
    //-------------------------------------------------------------------------
    push_pos();
    unsigned addr;
    sscanf( ptr, "%04X", &addr);
    cpu.trace_curs = cpu.trace_top = addr;
}
//=============================================================================



//=============================================================================
// View Operand Address                         ZX/GS - ok
// jump to instruction operand in data window           // â ìåíþ WNDTRACE äåáàãåðà
void cdjump()                                           // è "cpu.datajump" õîòêåé
{                                                      
    char *ptr = nullptr;
    //-------------------------------------------------------------------------
    for (char *p = asmpc;    *p;    p++)
        if (ishex( p[0]) & ishex( p[1]) & ishex( p[2]) & ishex( p[3]))
            ptr = p;
    //-------------------------------------------------------------------------
    if (!ptr)
        return;
    //-------------------------------------------------------------------------
    unsigned addr;
    sscanf( ptr, "%04X", &addr);
    Z80 &cpu = CpuMgr.Cpu();
    cpu.mem_curs = addr;
    activedbg = WNDMEM;
    editor = ED_MEM;
}
//=============================================================================



               
               
//=============================================================================
// ïåðåõîä ê àäðåñó â îêíå ìåìîðè âèåâåðà       ZX/GS - ok              // [NS]
// èç îêíà äèçàñìà
void mon_view_mem_addr( unsigned addr)                                 
{
//  unsigned addr = cpu.af;
    addr &= 0xFFFF;     // îáðåçêà òê ìîæåò áûòü ôèãíÿ
    Z80 &cpu = CpuMgr.Cpu();
    cpu.mem_curs = addr;
    activedbg = WNDMEM;
    editor = ED_MEM;
}

void mon_view_mem_rAF()         { Z80 &cpu = CpuMgr.Cpu();      mon_view_mem_addr( cpu.af);             }
void mon_view_mem_rBC()         { Z80 &cpu = CpuMgr.Cpu();      mon_view_mem_addr( cpu.bc);             }
void mon_view_mem_rDE()         { Z80 &cpu = CpuMgr.Cpu();      mon_view_mem_addr( cpu.de);             }
void mon_view_mem_rHL()         { Z80 &cpu = CpuMgr.Cpu();      mon_view_mem_addr( cpu.hl);             }

void mon_view_mem_rAF1()        { Z80 &cpu = CpuMgr.Cpu();      mon_view_mem_addr( cpu.alt.af); }
void mon_view_mem_rBC1()        { Z80 &cpu = CpuMgr.Cpu();      mon_view_mem_addr( cpu.alt.bc); }
void mon_view_mem_rDE1()        { Z80 &cpu = CpuMgr.Cpu();      mon_view_mem_addr( cpu.alt.de); }
void mon_view_mem_rHL1()        { Z80 &cpu = CpuMgr.Cpu();      mon_view_mem_addr( cpu.alt.hl); }

void mon_view_mem_rIX()         { Z80 &cpu = CpuMgr.Cpu();      mon_view_mem_addr( cpu.ix);             }
void mon_view_mem_rIY()         { Z80 &cpu = CpuMgr.Cpu();      mon_view_mem_addr( cpu.iy);             }

void mon_view_mem_rSP()         { Z80 &cpu = CpuMgr.Cpu();      mon_view_mem_addr( cpu.sp);             }
void mon_view_mem_rPC()         { Z80 &cpu = CpuMgr.Cpu();      mon_view_mem_addr( cpu.pc);             }

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


//=============================================================================
// ïîêàçàòü/ñêðûòü labels
void cfliplabels()                              // â ìåíþ WNDTRACE äåáàãåðà
{                                               // "cpu.labels" õîòêåé
   trace_labels = !trace_labels; showtrace();
}
//=============================================================================
// save cursor position to slot n
static void csave(unsigned n)           //"cpu.save1"..."cpu.save8" õîòêåè
{
   Z80 &cpu = CpuMgr.Cpu();
   save_pos[n] = cpu.trace_top;
   save_cur[n] = cpu.trace_curs;
}
//=============================================================================
// save cursor position to jumpstack, load from slot 1
static void crest(unsigned n)           //"cpu.rest1"..."cpu.rest8" õîòêåè
{
   Z80 &cpu = CpuMgr.Cpu();
   if (save_pos[n] == -1U)
       return;
   push_pos();
   cpu.trace_top = save_pos[n];
   cpu.trace_curs = save_cur[n];
}
//=============================================================================
void csave1() { csave(0); }
void csave2() { csave(1); }
void csave3() { csave(2); }
void csave4() { csave(3); }
void csave5() { csave(4); }
void csave6() { csave(5); }
void csave7() { csave(6); }
void csave8() { csave(7); }
//=============================================================================
void crest1() { crest(0); }
void crest2() { crest(1); }
void crest3() { crest(2); }
void crest4() { crest(3); }
void crest5() { crest(4); }
void crest6() { crest(5); }
void crest7() { crest(6); }
void crest8() { crest(7); }
//=============================================================================



//=============================================================================
namespace z80dbg                                                //????
{
    void __cdecl SetLastT()
    {
        cpu.debug_last_t = comp.t_states + cpu.t;
    }
}
//=============================================================================



float zx_step_dither = 0.0;
float gs_step_dither = 0.0;

float zx_tact_dither = 0.0;
float gs_tact_dither = 0.0;


//=============================================================================
//áûâøèé void mon_step()
void mon_step_single_cpu()
{
    Z80 &cpu = CpuMgr.Cpu();
    TZ80State &prevcpu = CpuMgr.PrevCpu();
   
    cpu.SetLastT();
    prevcpu = cpu;
    // CpuMgr.CopyToPrev();
   
    //-------------------------------------------------------------------------
    if (cpu.t >= conf.intlen)
       cpu.int_pend = false;
    //-------------------------------------------------------------------------
    cpu.Step();
    //-------------------------------------------------------------------------
    if (  (cpu.int_pend)        &&
          (cpu.iff1)            &&
          (cpu.t != cpu.eipos)  &&      // int enabled in CPU not issued after EI
          (cpu.int_gate)                // int enabled by ATM hardware
     )
    {
        handle_int( &cpu, cpu.IntVec());
    }
    //-------------------------------------------------------------------------
    cpu.CheckNextFrame();
    //-------------------------------------------------------------------------
    if (conf.trace_follow_regs)                                         // [NS]
    {
        //---------------------------------------------------------------------
        switch (conf.trace_follow_regs)
        {
            case REG_AF:        cpu.trace_curs = cpu.af;        break;
            case REG_BC:        cpu.trace_curs = cpu.bc;        break;
            case REG_DE:        cpu.trace_curs = cpu.de;        break;
            case REG_HL:        cpu.trace_curs = cpu.hl;        break;
            case REG_AF1:       cpu.trace_curs = cpu.alt.af;    break;
            case REG_BC1:       cpu.trace_curs = cpu.alt.bc;    break;
            case REG_DE1:       cpu.trace_curs = cpu.alt.de;    break;
            case REG_HL1:       cpu.trace_curs = cpu.alt.hl;    break;
            case REG_IX:        cpu.trace_curs = cpu.ix;        break;
            case REG_IY:        cpu.trace_curs = cpu.iy;        break;
            case REG_SP:        cpu.trace_curs = cpu.sp;        break;
            case REG_PC:        cpu.trace_curs = cpu.pc;        break;
        }
        //---------------------------------------------------------------------
        conf.trace_follow_request = 1;  // ñëåäîâàòü çà ÷åì íèáóäü     
    }
    //-------------------------------------------------------------------------
    // òóò íóæíî íåñêîëüêî ðàç âûçûâàòü step äëÿ GS
    // èëè ìîæåò äàæå áðàòü òàêòû
    // è ùèòàòü ñêîëüêî êàæäîãî äîëæíî áûòü âûçâàíî
   
}
//=============================================================================
// ZX+GS Step                                                           // [NS]
void mon_step()                                                        
{
    //=========================================================================
    if ( (conf.gs_type == 1)    &&      // GS Z80
         (conf.ZXGS_Step == 1)          // âêëþ÷åííîñòü ñîâìåñòíîãî ñòåïà
     )
    {
        Z80 &cpu = CpuMgr.Cpu();

        // NO STATIC !!!!
        int current_cpu_back = CpuMgr.GetCurrentCpu();
   
        float zx_cpu_frq = frametime * conf.intfq;
        //printf("ZX CPU %f\n",zx_cpu_frq);
   
        //=====================================================================
        // ZX Step
        if (current_cpu_back == 0)
        {
            //printf("ZX_STEP\n");
            float gs_tacts_per_1_zx = (float) z80gs::GSCPUFQ / zx_cpu_frq;
           
            mon_step_single_cpu();      // 1 ZX Step
            //printf("cpu.Delta() %d\n",cpu.Delta());
            gs_tact_dither += gs_tacts_per_1_zx * (float) cpu.Delta();
            //printf("gs_tact_dither %f\n",gs_tact_dither);
            //-----------------------------------------------------------------
            // Âîçìîæíà ðàçäà÷à GS îøèáêè
            if (gs_tact_dither > 4.0)   // ïóøî ìåíüøå 4 òàêòîâ íåâîçìîæíî
            {
                //CpuMgr.SwitchCpu();
                CpuMgr.SetCurrentCpu( 1);       // GS CPU
                Z80 &cpu = CpuMgr.Cpu();
                //-------------------------------------------------------------
                // GS Step
                while (gs_tact_dither > 4.0)
                {
                    //printf("  gs_step\n");
                    mon_step_single_cpu();
                    //printf("  cpu.Delta() %d\n",cpu.Delta());
                    gs_tact_dither -= (float) cpu.Delta();
                    //printf("  gs_tact_dither %f\n",gs_tact_dither);
                }
                //-------------------------------------------------------------
                //CpuMgr.SwitchCpu();
            }
            //-----------------------------------------------------------------
        } // ZX Step
        //=====================================================================
        // GS Step
        else
        {
            //printf("GS_STEP\n");
            float zx_tacts_per_1_gs = zx_cpu_frq / (float) z80gs::GSCPUFQ;
           
            mon_step_single_cpu();      // 1 GS Step
            //printf("cpu.Delta() %d\n",cpu.Delta());
            zx_tact_dither += zx_tacts_per_1_gs * (float) cpu.Delta();
            //printf("zx_tact_dither %f\n",zx_tact_dither);
            //-----------------------------------------------------------------
            // Âîçìîæíà ðàçäà÷à ZX îøèáêè
            if (zx_tact_dither > 4.0)   // ïóøî ìåíüøå 4 òàêòîâ íåâîçìîæíî
            {
                //CpuMgr.SwitchCpu();
                CpuMgr.SetCurrentCpu( 0);       // ZX CPU
                Z80 &cpu = CpuMgr.Cpu();
                //-------------------------------------------------------------
                // ZX Step
                while (zx_tact_dither > 4.0)
                {
                    //printf("  zx_step\n");
                    mon_step_single_cpu();
                    //printf("  zx cpu.Delta() %d\n",cpu.Delta());
                    zx_tact_dither -= (float) cpu.Delta();
                    //printf("  zx_tact_dither %f\n",zx_tact_dither);
                }
                //-------------------------------------------------------------
                //CpuMgr.SwitchCpu();
            }
            //-----------------------------------------------------------------
        } // GS Step
        //=====================================================================
        // Âîñòàíîâëåíèå èñõîäíîãî CPU
        CpuMgr.SetCurrentCpu( current_cpu_back);
    }
    //=========================================================================
    // íå øàãàòü "îäíîâðåìåííî"
    else
    {
        mon_step_single_cpu();
    }
    //=========================================================================
   
/*



    // NO STATIC !!!!
    int current_cpu_back = CpuMgr.GetCurrentCpu();
    //printf("cpu %x\n",current_cpu_back);
   
   //     const int GSCPUFQ = 24000000;         // hz //12
   // extern const unsigned GSCPUINT;
    // GSINTFQ
   
        //conf.frame
        //cpu.tpi //zx?
        //printf("GSINTFQ %d\n",GSINTFQ);
        //printf("GSCPUINT %d\n",GSCPUINT);
        //printf("GSCPUFQ %d\n",z80gs::GSCPUFQ);
        //printf("frametime %d\n",frametime);
        //printf("conf.intfq %d\n",conf.intfq);
        float zx_cpu_frq = frametime * conf.intfq;
        //printf("ZX CPU %f\n",zx_cpu_frq);
        float gs_steps_per_1_zx = (float) z80gs::GSCPUFQ / zx_cpu_frq;
        float zx_steps_per_1_gs = zx_cpu_frq / (float) z80gs::GSCPUFQ;
        //printf("gs_steps_per_1_zx %f\n",gs_steps_per_1_zx);
        //printf("zx_steps_per_1_gs %f\n",zx_steps_per_1_gs);
       
    // STEP-û íå ó÷èòûâàþò òàêòû !!!
    // íóæíî äåëàòü ñ ó÷åòîì òàêòîâ çà ïîñëåäíèé ñòåï
    //=========================================================================
    // ZX Step
    if (current_cpu_back == 0)
    {
        printf("ZX_STEP\n");
        mon_step_single_cpu();  // 1 ZX Step

        gs_step_dither += gs_steps_per_1_zx;
        //printf("gs_step_dither %f\n",gs_step_dither);
        //---------------------------------------------------------------------
       
       
        if (gs_step_dither > 1.0)
        {
            CpuMgr.SwitchCpu();
            while (gs_step_dither > 1.0)
            {
                gs_step_dither -= 1.0;
                printf("gs_step\n");
                mon_step_single_cpu();
            }
            CpuMgr.SwitchCpu();
        }
        //---------------------------------------------------------------------
       
    }
    //=========================================================================
    // GS Step
    else
    {
        printf("GS_STEP\n");
        mon_step_single_cpu();  // 1 GS Step
       
        zx_step_dither += zx_steps_per_1_gs;
        //printf("zx_step_dither %f\n",zx_step_dither);
        //---------------------------------------------------------------------
        if (zx_step_dither > 1.0)
        {
            CpuMgr.SwitchCpu();
            while (zx_step_dither > 1.0)
            {
                zx_step_dither -= 1.0;
                printf("zx_step\n");
                mon_step_single_cpu();
            }
            CpuMgr.SwitchCpu();
        }
        //---------------------------------------------------------------------
       
    }
    //=========================================================================
   
   
   
    CpuMgr.SetCurrentCpu( current_cpu_back);
   
    */

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




//=============================================================================
void mon_step_x( int count)
{
    mon_step();
    //-------------------------------------------------------------------------
    for (int temp_cnt = 0;    temp_cnt < count;    temp_cnt++)
    {
        debugscr();             //à ïî÷åìó íå ïîñëå?
        debugflip();
       
        mon_step();
    }
    //-------------------------------------------------------------------------
}
//=============================================================================
void mon_step_x2() {    mon_step_x(   1); }
void mon_step_x4() {    mon_step_x(   3); }
void mon_step_x8() {    mon_step_x(   7); }
void mon_step_x16() {   mon_step_x(  15); }
void mon_step_x32() {   mon_step_x(  31); }
void mon_step_x64() {   mon_step_x(  63); }
void mon_step_x128() {  mon_step_x( 127); }
void mon_step_x256() {  mon_step_x( 255); }
//=============================================================================


//#define TWF_BRANCH  0x010000U
//#define TWF_BRADDR  0x020000U
//#define TWF_LOOPCMD 0x040000U
//#define TWF_CALLCMD 0x080000U
//#define TWF_BLKCMD  0x100000U
//#define TWF_HALTCMD 0x200000U

//=============================================================================
void mon_stepover_flags( int flags)
{
    Z80 &cpu = CpuMgr.Cpu();
    unsigned char trace = 1;
    //-------------------------------------------------------------------------
    // call,rst
    if (cpu.pc_trflags & TWF_CALLCMD)
    {
        cpu.dbg_stopsp = cpu.sp & 0xFFFF;       //??????
        cpu.dbg_stophere = cpu.nextpc;
        trace = 0;
    }
    //-------------------------------------------------------------------------
//  else if (cpu.pc_trflags & (TWF_BLKCMD | TWF_HALTCMD))
    else if (cpu.pc_trflags & (flags))                                  // [NS]      
    {
        trace = 0;
        cpu.dbg_stophere = cpu.nextpc;
    }
    //-------------------------------------------------------------------------  
/* [vv]
    // jr cc,$-xx, jp cc,$-xx
    else if ((cpu.pc_trflags & TWF_LOOPCMD) && (cpu.pc_trflags & 0xFFFF) < (cpu.pc & 0xFFFF))
    {
        cpu.dbg_stopsp = cpu.sp & 0xFFFF;
        cpu.dbg_stophere = cpu.nextpc,
        cpu.dbg_loop_r1 = cpu.pc_trflags & 0xFFFF;
        cpu.dbg_loop_r2 = cpu.pc & 0xFFFF;
        trace = 0;
    }
*/

    //-------------------------------------------------------------------------
/*  [vv]
    else if (cpu.pc_trflags & TWF_BRANCH)
        trace = 1;
    else
    {
        trace = 1;
        cpu.dbg_stophere = cpu.nextpc;
    }
*/

    //-------------------------------------------------------------------------
    //step over (step) ?
    if (trace)
    {
        mon_step();
    }
    //-------------------------------------------------------------------------
    //step over (call skip)
    else
    {
        cpu.dbgbreak = 0;
        dbgbreak = 0;
        cpu.dbgchk = 1;
    }
    //-------------------------------------------------------------------------
}
//=============================================================================
void mon_stepover()                                                     // [NS]
{
// ldir/lddr|cpir/cpdr|otir/otdr|inir/indr|halt

    mon_stepover_flags(         TWF_BLKCMD      |
                                TWF_HALTCMD
                        );
}
//=============================================================================
void mon_stepover_jump()                                                // [NS]
{
// òàê æå ïðîñêàêèâàåò jr cc jp cc djnz
// ÍÎ íåêîòîðûå óñëîâèÿ î÷åíü ðåäêèå
// è trace over ìîæåò ÂÍÅÇÀÏÍÎ ïðåâðàòèòñî â run
// ïîýòîìó îòäåëüíîé êíîïêîé

    mon_stepover_flags(         TWF_BLKCMD      |
                                TWF_HALTCMD     |
                                TWF_LOOPCMD
                        );
}
//=============================================================================