рдЕрдкрдЧреНрд░реЗрдбрд┐рдВрдЧ рдЖрдИрдбреАрдП рдкреНрд░реЛред рд╕реЗрдЧрд╛ рдореЗрдЧрд╛ рдбреНрд░рд╛рдЗрд╡ рдХреЗ рд▓рд┐рдП рдбрд┐рдмрдЧрд░ (рднрд╛рдЧ 1)


рдирдорд╕реНрддреЗ!


рдХреЙрдорд░реЗрдбреНрд╕ рд░рд┐рд╡рд░реНрд╕рд▓рд░реНрд╕, рд░реЛрдорд╣реИрдХрд░реНрд╕: рдореВрд▓ рд░реВрдк рд╕реЗ рдпрд╣ рд▓реЗрдЦ рдЖрдкрдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдкрд┐рдд рд╣реЛрдЧрд╛ред рдЗрд╕рдореЗрдВ, рдореИрдВ рдЖрдкрдХреЛ IDA Pro рд▓рд┐рдП рдЕрдкрдирд╛ рдЦреБрдж рдХрд╛ рдбрд┐рдмрдЧрд░ рдкреНрд▓рдЧрдЗрди рд▓рд┐рдЦрдиреЗ рдХрд╛ рддрд░реАрдХрд╛ рдмрддрд╛рдКрдВрдЧрд╛ред рд╣рд╛рдВ, рдХрд╣рд╛рдиреА рд╢реБрд░реВ рдХрд░рдиреЗ рдХрд╛ рдкрд╣рд▓рд╛ рдкреНрд░рдпрд╛рд╕ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдерд╛, рд▓реЗрдХрд┐рди рддрдм рд╕реЗ рдмрд╣реБрдд рдкрд╛рдиреА рдмрд╣ рдЪреБрдХрд╛ рд╣реИ, рдХрдИ рд╕рд┐рджреНрдзрд╛рдВрддреЛрдВ рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рд╡реЗ рдЪрд▓реЗ рдЧрдП!


рдЧреЗрдп рдкрд░рд┐рдЪрдп


рджрд░рдЕрд╕рд▓, рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦреЛрдВ ( рдПрдХ , рджреЛ , рддреАрди ) рд╕реЗ, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рд░рд╣рд╕реНрдп рдирд╣реАрдВ рд╣реЛрдЧрд╛ рдХрд┐ рдореЗрд░рд╛ рдкрд╕рдВрджреАрджрд╛ рдкреНрд░реЛрд╕реЗрд╕рд░ Motorola 68000 ред рд╡реИрд╕реЗ, рдореЗрд░реА рдкрд╕рдВрджреАрджрд╛ рдкреБрд░рд╛рдиреА рдорд╣рд┐рд▓рд╛ Sega Mega Drive / Genesis рдкрд░ рдХрд╛рдо рдХрд░ рд░рд╣реА рд╣реИред рдФрд░, рдЬрдм рд╕реЗ рдореБрдЭреЗ рд╣рдореЗрд╢рд╛ рдЗрд╕ рдмрд╛рдд рдореЗрдВ рджрд┐рд▓рдЪрд╕реНрдкреА рдереА рдХрд┐ рд╕реАрдЬреАрдУ рдХреЗ рдЦреЗрд▓ рдХреА рд╡реНрдпрд╡рд╕реНрдерд╛ рдХреИрд╕реЗ рдХреА рдЬрд╛рддреА рд╣реИ, рдЕрдкрдиреЗ рдХрдВрдкреНрдпреВрдЯрд░ рдЙрдкрдпреЛрдЧ рдХреЗ рдкрд╣рд▓реЗ рдорд╣реАрдиреЛрдВ рд╕реЗ рдореИрдВрдиреЗ рдбрд┐рд╕рд╕реИрдореНрдм рдХреЗ рдЬрдВрдЧрд▓ рдореЗрдВ рдЧрд╣рд░рд╛рдИ рддрдХ рдЬрд╛рдиреЗ рдФрд░ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рд░рд┐рд╡рд░реНрд╕ рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред


рдЗрд╕ рддрд░рд╣ рд╕реЗ Smd IDA Tools рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЖрдпрд╛ред
рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рд╡рд┐рднрд┐рдиреНрди рд╕рд╣рд╛рдпрдХ рдЪреАрдЬреЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ рдЬреЛ рд╕реЗрдЧрд╛ рдкрд░ рд░реЛрдорд╛рдВрд╕ рдХрд╛ рдЕрдзреНрдпрдпрди рдХрд░рдиреЗ рдХреЗ рдХрд╛рдо рдХреЛ рдмрд╣реБрдд рдЖрд╕рд╛рди рдмрдирд╛рддреА рд╣реИрдВ: рдПрдХ рд▓реЛрдбрд░, рдПрдХ рдбрд┐рдмрдЧрд░, VDP рдХрдорд╛рдВрдб рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд╣рд╛рдпрдХред рд╕рдм рдХреБрдЫ IDA 6.8 рд▓рд┐рдП рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рдерд╛, рдФрд░ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдХрд┐рдпрд╛ред рд▓реЗрдХрд┐рди, рдЬрдм рдореИрдВрдиреЗ рджреБрдирд┐рдпрд╛ рдХреЛ рдпрд╣ рдмрддрд╛рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ рдХрд┐ рдореИрдВрдиреЗ рдпрд╣ рд╕рдм рдХреИрд╕реЗ рдХрд┐рдпрд╛ рд╣реИ, рддреЛ рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд╣реЛ рдЧрдпрд╛ рдХрд┐ рд▓реЛрдЧреЛрдВ рдХреЛ рдЗрд╕ рддрд░рд╣ рдХреЗ рдХреЛрдб рдХреЛ рджрд┐рдЦрд╛рдирд╛ рдмрд╣реБрдд рдореБрд╢реНрдХрд┐рд▓ рд╣реЛрдЧрд╛, рдФрд░ рдЗрд╕рд╕реЗ рднреА рдЬреНрдпрд╛рджрд╛ рдЗрд╕рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдЗрд╕рд▓рд┐рдП, рдореИрдВ рдРрд╕рд╛ рдирд╣реАрдВ рдХрд░ рд╕рдХрд╛ред


рдФрд░ рдлрд┐рд░ IDA 7.0 рд╕рд╛рдордиреЗ рдЖрдпрд╛ред рдореЗрд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛ рдкреЛрд░реНрдЯ рдХрд░рдиреЗ рдХреА рдЗрдЪреНрдЫрд╛ рддреБрд░рдВрдд рджрд┐рдЦрд╛рдИ рджреА, рд▓реЗрдХрд┐рди Gens рдПрдореНрдпреВрд▓реЗрдЯрд░ рдХреА рд╡рд╛рд╕реНрддреБрдХрд▓рд╛, рдЬрд┐рд╕рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдореИрдВрдиреЗ рдбрд┐рдмрдЧрд░ рд▓рд┐рдЦрд╛, рдкреЛрд░реНрдЯрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдЕрдиреБрдкрдпреБрдХреНрдд рд╣реЛ рдЧрдпрд╛: x86 рдЕрд╕реЗрдВрдмрд▓реА рдЖрд╡реЗрд╖рдг, рдмреИрд╕рд╛рдЦреА, рдХреЛрдб рдЬреЛ рд╕рдордЭрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдерд╛, рдФрд░ рдмрд╣реБрдд рдХреБрдЫред рдФрд░ рдЦреЗрд▓ Pier Solar and the Great Architects , рдЬреЛ 2010 рдореЗрдВ рдХрд╛рд░рддреВрд╕ рдкрд░ рдЬрд╛рд░реА рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдФрд░ рдЬреЛ рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рддрд▓рд╛рд╢ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ (рдФрд░ рд╡рд╣рд╛рдВ рдмрд╣реБрдд рд╕рд╛рд░реЗ рд╡рд┐рд░реЛрдзреА рдЕрдиреБрдХрд░рдг рдЪрд╛рд▓реЗрдВ рд╣реИрдВ), Gens рдореЗрдВ рд╢реБрд░реВ рдирд╣реАрдВ рд╣реБрдЖред



рдПрдХ рдЙрдкрдпреБрдХреНрдд рдПрдореБрд▓реЗрдЯрд░ рд╕реНрд░реЛрдд рдХреА рддрд▓рд╛рд╢ рдореЗрдВ рдЬрд┐рд╕реЗ рдбрд┐рдмрдЧрд░ рдХреЗ рд▓рд┐рдП рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдореИрдВ рдЕрдВрддрддрдГ EkeEke рдЬреЗрдиреЗрд╕рд┐рд╕ рдкреНрд▓рд╕ рдЬреАрдПрдХреНрд╕ рдкрд░ рдареЛрдХрд░ рдЦрд╛рдИред рддреЛ рдпрд╣ рд▓реЗрдЦ рджрд┐рдЦрд╛рдИ рджрд┐рдпрд╛ред


рднрд╛рдЧ рдПрдХ: рдбреАрдмрдЧрд░ рдХреЛрд░


рдореБрд╢реАрд╢реА рдиреЗ Genesis Plus GX рдореЗрдВ рдореЛрдЯреЛрд░реЛрд▓рд╛ рдкреНрд░реЛрд╕реЗрд╕рд░ рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХрд╛ рдЕрдиреБрдХрд░рдг рдХрд┐рдпрд╛ред рдЗрд╕рдХреЗ рдореВрд▓ рд╕реНрд░реЛрдд рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдмреБрдирд┐рдпрд╛рджреА рдбрд┐рдмрдЧрд┐рдВрдЧ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ (рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╣реБрдХ) рд╣реИ, рд▓реЗрдХрд┐рди EkeEke рдиреЗ рдЗрд╕реЗ рдЕрдирд╛рд╡рд╢реНрдпрдХ рд░реВрдк рд╕реЗ рд╣рдЯрд╛рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред рд╣рдо рд▓реМрдЯрддреЗ рд╣реИрдВред




рдЕрдм рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд╛рдд: рдЖрдкрдХреЛ рдбрд┐рдмрдЧрд░ рдХреА рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЖрд╡рд╢реНрдпрдХрддрд╛рдПрдВ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИрдВ:


  • рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рд▓рд┐рдП рдмреНрд░реЗрдХ (рдмреНрд░реЗрдХрдкреЙрдЗрдВрдЯ), рдкрдврд╝рдиреЗ рдФрд░ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдореЗрдореЛрд░реА
  • рдХрд╛рд░реНрдпрд╢реАрд▓рддрд╛ Step Into , Step Over
  • рд░реЛрдХреЗрдВ, рдЕрдиреБрдХрд░рдг Resume
  • рд░рдЬрд┐рд╕реНрдЯрд░ рдкрдврд╝реЗрдВ / рд╕реЗрдЯ рдХрд░реЗрдВ, рдореЗрдореЛрд░реА рдкрдврд╝реЗрдВ / рд▓рд┐рдЦреЗрдВ

рдпрджрд┐ рдпреЗ рдЪрд╛рд░ рдмрд┐рдВрджреБ рдЕрдВрджрд░ рд╕реЗ рдбреАрдмрдЧрд░ рдХрд╛ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдЕрднреА рднреА рдмрд╛рд╣рд░ рд╕реЗ рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдХреЛрдИ рдЕрдиреНрдп рдЖрдЗрдЯрдо рдЬреЛрдбрд╝реЗрдВ:


  • рдбрд┐рдмрдЧрд░-рдХреНрд▓рд╛рдЗрдВрдЯ (GUI, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛) рдХреЗ рд╕рд╛рде рдбреАрдмрдЧрд░-рд╕рд░реНрд╡рд░ (рдХрд░реНрдиреЗрд▓) рдХрд╛ рд╕рдВрдЪрд╛рд░ рдкреНрд░реЛрдЯреЛрдХреЙрд▓

рдбрд┐рдмрдЧрд░ рдХреЛрд░: рдмреНрд░реЗрдХ рд▓рд┐рд╕реНрдЯ


рд╕реВрдЪреА рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рдВрд░рдЪрдирд╛ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ:


 typedef struct breakpoint_s { struct breakpoint_s *next, *prev; int enabled; int width; bpt_type_t type; unsigned int address; } breakpoint_t; 

next рдФрд░ prev рдлрд╝реАрд▓реНрдб рдХреНрд░рдорд╢рдГ рдЕрдЧрд▓реЗ рдФрд░ рдкрд┐рдЫрд▓реЗ рддрддреНрд╡ рдХреА рдУрд░ рд╕рдВрдХреЗрдд рдХрд░реЗрдВрдЧреЗред
рдпрджрд┐ рдЗрд╕ рдмреНрд░реЗрдХрдкреЙрдЗрдВрдЯ рдХреЛ рдСрдкрд░реЗрд╢рди рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рдЫреЛрдбрд╝ рджрд┐рдпрд╛ рдЬрд╛рдирд╛ рд╣реИ рддреЛ enabled рдлрд╝реАрд▓реНрдб 0 рд╕реНрдЯреЛрд░ рдХрд░реЗрдЧрд╛ред
width - address рдлрд╝реАрд▓реНрдб рдореЗрдВ рдкрддреЗ рд╕реЗ рд╢реБрд░реВ рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рдмрд╛рдЗрдЯреНрд╕ рдХреА рд╕рдВрдЦреНрдпрд╛ рдЬреЛ рдмреНрд░реЗрдХрд░ рдХреЛ рдХрд╡рд░ рдХрд░рддреА рд╣реИред
рдЦреИрд░, type рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рд╣рдо рдмреНрд░реЗрдХрдкреЙрдЗрдВрдЯ рдкреНрд░рдХрд╛рд░ (рдирд┐рд╖реНрдкрд╛рджрди, рдкрдврд╝рдирд╛, рд▓рд┐рдЦрдирд╛) рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░реЗрдВрдЧреЗред рдЕрдзрд┐рдХ рд╡рд┐рд╡рд░рдг рдиреАрдЪреЗред


рдмреНрд░реЗрдХрдкреНрд╡рд╛рдЗрдВрдЯ рдХреА рд╕реВрдЪреА рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд╛рд░реНрдп рдЬреЛрдбрд╝реЗ:


рд╡рд┐рд░рд╛рдо рдмрд┐рдВрджреБ рдХрд╛рд░реНрдп
 static breakpoint_t *first_bp = NULL; static breakpoint_t *add_bpt(bpt_type_t type, unsigned int address, int width) { breakpoint_t *bp = (breakpoint_t *)malloc(sizeof(breakpoint_t)); bp->type = type; bp->address = address; bp->width = width; bp->enabled = 1; if (first_bp) { bp->next = first_bp; bp->prev = first_bp->prev; first_bp->prev = bp; bp->prev->next = bp; } else { first_bp = bp; bp->next = bp; bp->prev = bp; } return bp; } static void delete_breakpoint(breakpoint_t * bp) { if (bp == first_bp) { if (bp->next == bp) { first_bp = NULL; } else { first_bp = bp->next; } } bp->next->prev = bp->prev; bp->prev->next = bp->next; free(bp); } static breakpoint_t *next_breakpoint(breakpoint_t *bp) { return bp->next != first_bp ? bp->next : 0; } static breakpoint_t *find_breakpoint(unsigned int address, bpt_type_t type) { breakpoint_t *p; for (p = first_bp; p; p = next_breakpoint(p)) { if ((p->address == address) && ((p->type == BPT_ANY) || (p->type & type))) return p; } return 0; } static void remove_bpt(unsigned int address, bpt_type_t type) { breakpoint_t *bpt; if ((bpt = find_breakpoint(address, type))) delete_breakpoint(bpt); } static int count_bpt_list() { breakpoint_t *p; int i = 0; for (p = first_bp; p; p = next_breakpoint(p)) { ++i; } return i; } static void get_bpt_data(int index, bpt_data_t *data) { breakpoint_t *p; int i = 0; for (p = first_bp; p; p = next_breakpoint(p)) { if (i == index) { data->address = p->address; data->width = p->width; data->type = p->type; data->enabled = p->enabled; break; } ++i; } } static void clear_bpt_list() { while (first_bp != NULL) delete_breakpoint(first_bp); } static void init_bpt_list() { if (first_bp) clear_bpt_list(); } void check_breakpoint(bpt_type_t type, int width, unsigned int address, unsigned int value) { if (!dbg_req || !dbg_req->dbg_active || dbg_dont_check_bp) return; breakpoint_t *bp; for (bp = first_bp; bp; bp = next_breakpoint(bp)) { if (!(bp->type & type) || !bp->enabled) continue; if ((address <= (bp->address + bp->width)) && ((address + width) >= bp->address)) { dbg_req->dbg_paused = 1; break; } } } 

рдбреАрдмрдЧрд░ рдХреЛрд░: рдореБрдЦреНрдп рдЪрд░


рджрд░рдЕрд╕рд▓, рдореИрдВрдиреЗ рдЗрд╕ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдПрдХ рдФрд░ PCSXR рдбрд┐рдмрдЧрд░ рдореЗрдВ рдЬрд╛рд╕реВрд╕реА рдХреАред


рдЙрди рд╡реЗрд░рд┐рдПрдмрд▓реНрд╕ рдХреЛ рдЬреЛрдбрд╝реЗрдВ рдЬреЛ рдЗрдореНрдпреВрд▓реЗрд╢рди рд╕реНрдЯреЗрдЯ рдХреЛ рд╕реНрдЯреЛрд░ рдХрд░реЗрдВрдЧреЗ:


 static int dbg_first_paused, dbg_trace, dbg_dont_check_bp; static int dbg_step_over; static int dbg_last_pc; static unsigned int dbg_step_over_addr; static int dbg_active, dbg_paused; 

dbg_first_paused рдЪрд░ рдбрд┐рдмрдЧрд┐рдВрдЧ рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рдЕрдиреБрдХрд░рдг рдХреЛ рд░реЛрдХрдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реЛрдЧрд╛ред рдпрджрд┐ 0 - рддреЛ рдЖрдкрдХреЛ рдПрдореБрд▓реЗрд╢рди рдХреЛ рд░реЛрдХрдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдПрдХ рд╕рдВрджреЗрд╢ рднреЗрдЬрдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдПрдореБрд▓реЗрд╢рди рд╢реБрд░реВ рд╣реЛ рдЧрдпрд╛ рд╣реИред рдкрд╣рд▓реЗ рдард╣рд░рд╛рд╡ рдХреЗ рдмрд╛рдж, 1 рд╕реЗрдЯ рдХрд░реЗрдВред


рд╣рдореЗрдВ рдПрдХ рдирд┐рд░реНрджреЗрд╢ ( Step Into рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛) рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рд▓рд┐рдП dbg_trace рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрджрд┐ 1 рдмрд░рд╛рдмрд░ рд╣реИ, рддреЛ рд╣рдо рдПрдХ рдирд┐рд░реНрджреЗрд╢ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рд░реЛрдХрддреЗ рд╣реИрдВ, рдФрд░ рдорд╛рди рдХреЛ 0 рд░реАрд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВред


рдореИрдВрдиреЗ dbg_dont_check_bp рд╡реИрд░рд┐рдПрдмрд▓ рд╕реЗрдЯ рдХрд┐рдпрд╛ рддрд╛рдХрд┐ dbg_dont_check_bp рдХрд░рдиреЗ рдкрд░ рд░реАрдб / рд░рд╛рдЗрдЯ рдореЗрдореЛрд░реА рдмреНрд░реЗрдХ рдХрд╛рдо рди рдХрд░реЗред


dbg_step_over рд╣рдорд╛рд░реЗ рд╕рд╛рде 1 рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдпрджрд┐ рд╣рдо рдореМрдЬреВрджрд╛ PC ( рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХрд╛рдЙрдВрдЯрд░ , рдЙрд░реНрдл рдЗрдВрд╕реНрдЯреНрд░рдХреНрд╢рди рдкреЙрдЗрдВрдЯрд░ ) dbg_step_over_addr рдореЗрдВ рдкрддреЗ рдХреЗ рдмрд░рд╛рдмрд░ рд╣реЛрдиреЗ рддрдХ Step Over рдореЛрдб рдореЗрдВ рд╣реИрдВред рдЙрд╕рдХреЗ рдмрд╛рдж, рджреЛрдиреЛрдВ рдЪрд░ рд░реАрд╕реЗрдЯ рдХрд░ рджрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред рдореИрдВ рдмрд╛рдж рдореЗрдВ dbg_step_over_addr рдХреЗ рдорд╛рди рдХреА рдЧрдгрдирд╛ dbg_step_over_addr ред


рдореИрдВрдиреЗ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдорд╛рдорд▓реЗ рдХреЗ рд▓рд┐рдП dbg_last_pc рд╡реИрд░рд┐рдПрдмрд▓ рд╕реЗрдЯ рдХрд┐рдпрд╛: рдЬрдм рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдмреНрд░реЗрдХ рдкрд░ рдЦрдбрд╝реЗ рд╣реИрдВ, рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ dbg_last_pc рдкреВрдЫрддрд╛ рд╣реИред рддрд╛рдХрд┐ рдмреНрд░реЗрдХрд░ рдлрд┐рд░ рд╕реЗ рдХрд╛рдо рди рдХрд░реЗрдВ, рдореИрдВ рдЗрд╕ рдЪрд░ рдореЗрдВ рдЕрдВрддрд┐рдо PC рдХреЗ рдкрддреЗ рдХреА рддреБрд▓рдирд╛ рдирдП рдХреЗ рд╕рд╛рде рдХрд░рддрд╛ рд╣реВрдВ, рдФрд░ рдпрджрд┐ рдорд╛рди рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╣реИрдВ, рддреЛ рдЖрдк рд╡рд░реНрддрдорд╛рди PC рдкрд░ рдмреНрд░реЗрдХрдкреЙрдЗрдВрдЯ рдХреА рдЬрд╛рдВрдЪ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


dbg_active - рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпрд╣ рдбреАрдмрдЧрд┐рдВрдЧ рд╕рдХреНрд░рд┐рдп рд╣реЛрдиреЗ рдкрд░ 1 рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЖрдкрдХреЛ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕реЗ рдмреНрд░реЗрдХ, рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред


dbg_paused рд╡реИрд░рд┐рдПрдмрд▓ рдХреЗ рд╕рд╛рде, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╕рдм рдХреБрдЫ рд╕реНрдкрд╖реНрдЯ рд╣реИ: 1 - рд╣рдореЗрдВ рд░реЛрдХ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдмреНрд░реЗрдХ рдХреЗ рдмрд╛рдж рдЯреНрд░рд┐рдЧрд░ рд╣реЛрддрд╛ рд╣реИ) рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕реЗ рдХрдорд╛рдВрдб рдХреА рдЕрдкреЗрдХреНрд╖рд╛ рдХрд░рддреЗ рд╣реИрдВ, 0 - рд╣рдо рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХрд╛ рдкрд╛рд▓рди рдХрд░рддреЗ рд╣реИрдВред


рд╣рдо рдЗрди рдЪрд░реЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдп рд▓рд┐рдЦрддреЗ рд╣реИрдВ:


 static void pause_debugger() { dbg_trace = 1; dbg_paused = 1; } static void resume_debugger() { dbg_trace = 0; dbg_paused = 0; } static void detach_debugger() { clear_bpt_list(); resume_debugger(); } static void activate_debugger() { dbg_active = 1; } static void deactivate_debugger() { dbg_active = 0; } 

рд╣рдо рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ detach_debugger() рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдореИрдВ рдмреНрд░реЗрдХ рдХреА рд╕реВрдЪреА рдХреЛ рд╕рд╛рдлрд╝ рдХрд░рддрд╛ рдерд╛ред рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рддрд╛рдХрд┐ рдЧреНрд░рд╛рд╣рдХ рдХреЛ рдбрд┐рд╕реНрдХрдиреЗрдХреНрдЯ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдкреБрд░рд╛рдиреЗ рдмреНрд░реЗрдХрдкреЙрдЗрдВрдЯ рдХрд╛рдо рдХрд░рдирд╛ рдЬрд╛рд░реА рди рд░рдЦреЗрдВред


рдбрд┐рдмрдЧрд░ рдХреЛрд░: рд╣рдо рдирд┐рд░реНрджреЗрд╢реЛрдВ рдкрд░ рдПрдХ рд╣реБрдХ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ


рдЕрд╕рд▓ рдореЗрдВ, рдпрд╣рд╛рдВ рдореБрдЦреНрдп рдХрд╛рдо рдПрдХ рдард╣рд░рд╛рд╡, рдирд┐рд░рдВрддрд░ рдЕрдиреБрдХрд░рдг, Step Into , Step Over ред


рдпрд╣рд╛рдБ process_breakpoints() рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдХреЛрдб рд╣реИ:


 void process_breakpoints() { int handled_event = 0; int is_step_over = 0; int is_step_in = 0; if (!dbg_active) return; unsigned int pc = m68k_get_reg(M68K_REG_PC); if (dbg_paused && dbg_first_paused && !dbg_trace) longjmp(jmp_env, 1); if (!dbg_first_paused) { dbg_first_paused = 1; dbg_paused = 1; // TODO: Send emulation started event } if (dbg_trace) { is_step_in = 1; dbg_trace = 0; dbg_paused = 1; // TODO: Send event that Step Into has been triggered handled_event = 1; } if (!dbg_paused) { if (dbg_step_over && pc == dbg_step_over_addr) { is_step_over = 1; dbg_step_over = 0; dbg_step_over_addr = 0; dbg_paused = 1; } if (dbg_last_pc != pc) check_breakpoint(BPT_M68K_E, 1, pc, pc); if (dbg_paused) { // TODO: Send event about Step Over or breakpoint has been triggered handled_event = 1; } } if (dbg_first_paused && (!handled_event) && dbg_paused) { // TODO: Send paused event } dbg_last_pc = pc; if (dbg_paused && (!is_step_in || is_step_over)) { longjmp(jmp_env, 1); } } 

рдЖрдЗрдП рд╕рдордЭрддреЗ рд╣реИрдВ:


  1. рдпрджрд┐ рдбрд┐рдмрдЧрд┐рдВрдЧ рд╕рдХреНрд╖рдо рдирд╣реАрдВ рд╣реИ, рддреЛ рдмрд╕ рд╣реБрдХ рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓реЗрдВ
  2. longjmp / longjmp рд╕рд╛рде рдЯреНрд░рд┐рдХ longjmp рдЖрд╡рд╢реНрдпрдХрддрд╛ рдереА рдХреНрдпреЛрдВрдХрд┐ RetroArch рд╢реЗрд▓ RetroArch , рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рд╣рдордиреЗ Genesis Plus GX рдХрд╛ рдЕрдкрдирд╛ рд╕рдВрд╕реНрдХрд░рдг рд▓рд┐рдЦрд╛ рдерд╛, рдЬрд┐рд╕рдХреЗ рд╕рд╛рде рд╣рдо рдПрдореБрд▓реЗрд╢рди рдЪрд▓рд╛рддреЗ рд╣реИрдВ, рдлреНрд░реЗрдо рд░реЗрдВрдбрд░рд┐рдВрдЧ рдлрдВрдХреНрд╢рди рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдореБрд▓реЗрдЯрд░ рдХрд╛ рдЗрдВрддрдЬрд╛рд░ рдХрд░рддреЗ рд╣реИрдВред рдореИрдВ рдмрд╛рдж рдореЗрдВ рдЯреНрд░рд┐рдХ рдХрд╛ рджреВрд╕рд░рд╛ рднрд╛рдЧ рджрд┐рдЦрд╛рдКрдВрдЧрд╛ред рдпрд╣ рдХреЛрд░ рдХреЗ рдмрдЬрд╛рдп рдПрдореБрд▓реЗрдЯрд░ рдкрд░ рд╢реЗрд▓ рдХреЛ рдЫреВрддрд╛ рд╣реИред
  3. рдпрджрд┐ рдпрд╣ рд╣реБрдХ рдХрд╛ рд╣рдорд╛рд░рд╛ рдкрд╣рд▓рд╛ рдСрдкрд░реЗрд╢рди рд╣реИ, рдФрд░, рддрджрдиреБрд╕рд╛рд░, рдЕрдиреБрдХрд░рдг рдХреА рд╢реБрд░реБрдЖрдд, рд╣рдо рдЧреНрд░рд╛рд╣рдХ рдХреЛ рдЕрдиреБрдХрд░рдг рдХреА рд╢реБрд░реБрдЖрдд рдХреА рдШрдЯрдирд╛ рдХреЛ рд╡рд┐рд░рд╛рдо рджреЗрддреЗ рд╣реИрдВ рдФрд░ рднреЗрдЬрддреЗ рд╣реИрдВред
  4. рдпрджрд┐ рдХреНрд▓рд╛рдЗрдВрдЯ рдиреЗ рдкрд╣рд▓реЗ Step Into dbg_trace рднреЗрдЬрд╛ рдерд╛, рддреЛ рд╣рдо dbg_trace рдЪрд░ рдХрд╛ рдорд╛рди dbg_trace рдФрд░ рдЕрдиреБрдХрд░рдг рдХреЛ рд╡рд┐рд░рд╛рдо рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВред рд╣рдо рдЧреНрд░рд╛рд╣рдХ рдХреЛ рд╕рдВрдмрдВрдзрд┐рдд рдШрдЯрдирд╛ рднреЗрдЬрддреЗ рд╣реИрдВред
  5. рдпрджрд┐ рд╣рдо рдард╣рд░рд╛рд╡ рдкрд░ рдирд╣реАрдВ рд╣реИрдВ, рддреЛ Step Over рдореЛрдб рдЪрд╛рд▓реВ рд╣реИ, рдФрд░ рд╡рд░реНрддрдорд╛рди PC рдЧрдВрддрд╡реНрдп рдкрддреЗ dbg_step_over_addr рдмрд░рд╛рдмрд░ рд╣реИ, рдЖрд╡рд╢реНрдпрдХ рдЪрд░ dbg_step_over_addr рдФрд░ рдард╣рд░рд╛рд╡ рдкрд░ рд░рдЦреЗрдВред
  6. рд╣рдо рдмреНрд░реЗрдХрдкреЙрдЗрдВрдЯ рдХреА рдЬрд╛рдВрдЪ рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдХреНрдпрд╛ рд╣рдо рдЕрднреА рдЙрд╕ рдкрд░ рдирд╣реАрдВ рд╣реИрдВ, рдФрд░ рдЕрдЧрд░ рдмреНрд░реЗрдХ рдиреЗ рдХрд╛рдо рдХрд┐рдпрд╛ рд╣реИ, рддреЛ рд╣рдо рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ Step Over рдпрд╛ рдмреНрд░реЗрдХ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рдШрдЯрдирд╛ рднреЗрдЬрддреЗ рд╣реИрдВред
  7. рдпрджрд┐ рдпрд╣ рдмреНрд░реЗрдХрдбрд╛рдЙрди рдирд╣реАрдВ рд╣реИ, рддреЛ Step Into рдирд╣реАрдВ, рдФрд░ Step Over рдирд╣реАрдВ рд╣реИ, рддреЛ рдХреНрд▓рд╛рдЗрдВрдЯ рдиреЗ рдмреНрд░реЗрдХ рдХреЗ рд▓рд┐рдП рдХрд╣рд╛ред рд╣рдо рдЯреНрд░рд┐рдЧрд░ рдард╣рд░рд╛рд╡ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рдШрдЯрдирд╛ рднреЗрдЬрддреЗ рд╣реИрдВред
  8. рд╣рдо рдПрдХ рдард╣рд░рд╛рд╡ рдХреЗ рджреМрд░рд╛рди рдХреНрд▓рд╛рдЗрдВрдЯ рд╕реЗ рдХрд╛рд░реНрдпреЛрдВ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдЕрдирдВрдд рд▓реВрдк рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд░реВрдк рдореЗрдВ longjump рд╕рд╛рде рдЪрд╛рд▓ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВред

Step Over рд▓рд┐рдП рдкрддреЗ рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХрд╛ рдХреЛрдб рдЗрддрдирд╛ рд╕рд░рд▓ рдирд╣реАрдВ рдерд╛ рдЬрд┐рддрдирд╛ рдХрд┐ рдЖрдк рдкрд╣рд▓реЗ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВред рдореЛрдЯреЛрд░реЛрд▓рд╛ рдкреНрд░реЛрд╕реЗрд╕рд░ рдХреА рдЕрд▓рдЧ-рдЕрд▓рдЧ рдЕрдиреБрджреЗрд╢ рд▓рдВрдмрд╛рдИ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ рдУрдкрдХреЛрдб рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдЕрдЧрд▓реЗ рдкрддреЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЖрдкрдХреЛ bra , jmp , рд╕рд╢рд░реНрдд рдЫрд▓рд╛рдВрдЧ рдХреЗ jmp рдЬреИрд╕реЗ рдирд┐рд░реНрджреЗрд╢реЛрдВ рд╕реЗ рдмрдЪрдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ, рдФрд░ рдЙрдиреНрд╣реЗрдВ Step Into jmp рд░реВрдк Step Into рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ:


Calc_step_over () рдлрд╝рдВрдХреНрд╢рди рдХреЛрдб
 static unsigned int calc_step_over() { unsigned int pc = m68k_get_reg(M68K_REG_PC); unsigned int sp = m68k_get_reg(M68K_REG_SP); unsigned int opc = m68ki_read_imm_16(); unsigned int dest_pc = (unsigned int)(-1); // jsr if ((opc & 0xFFF8) == 0x4E90) { m68k_op_jsr_32_ai(); m68k_op_rts_32(); dest_pc = m68k_get_reg(M68K_REG_PC); } else if ((opc & 0xFFF8) == 0x4EA8) { m68k_op_jsr_32_di(); m68k_op_rts_32(); dest_pc = m68k_get_reg(M68K_REG_PC); } else if ((opc & 0xFFF8) == 0x4EB0) { m68k_op_jsr_32_ix(); m68k_op_rts_32(); dest_pc = m68k_get_reg(M68K_REG_PC); } else if ((opc & 0xFFFF) == 0x4EB8) { m68k_op_jsr_32_aw(); m68k_op_rts_32(); dest_pc = m68k_get_reg(M68K_REG_PC); } else if ((opc & 0xFFFF) == 0x4EB9) { m68k_op_jsr_32_al(); m68k_op_rts_32(); dest_pc = m68k_get_reg(M68K_REG_PC); } else if ((opc & 0xFFFF) == 0x4EBA) { m68k_op_jsr_32_pcdi(); m68k_op_rts_32(); dest_pc = m68k_get_reg(M68K_REG_PC); } else if ((opc & 0xFFFF) == 0x4EBB) { m68k_op_jsr_32_pcix(); m68k_op_rts_32(); dest_pc = m68k_get_reg(M68K_REG_PC); } // bsr else if ((opc & 0xFFFF) == 0x6100) { m68k_op_bsr_16(); m68k_op_rts_32(); dest_pc = m68k_get_reg(M68K_REG_PC); } else if ((opc & 0xFFFF) == 0x61FF) { m68k_op_bsr_32(); m68k_op_rts_32(); dest_pc = m68k_get_reg(M68K_REG_PC); } else if ((opc & 0xFF00) == 0x6100) { m68k_op_bsr_8(); m68k_op_rts_32(); dest_pc = m68k_get_reg(M68K_REG_PC); } // dbf else if ((opc & 0xfff8) == 0x51C8) { dest_pc = m68k_get_reg(M68K_REG_PC) + 2; } m68k_set_reg(M68K_REG_PC, pc); m68k_set_reg(M68K_REG_SP, sp); return dest_pc; 

рдбреАрдмрдЧрд░ рдХрд░реНрдиреЗрд▓: рдЖрд░рдВрдн рдХрд░рдирд╛ рдФрд░ рдбреАрдмрдЧ рдХрд░рдирд╛ рд░реЛрдХрдирд╛


рдпрд╣рд╛рдБ рд╕рдм рдХреБрдЫ рд╕рд░рд▓ рд╣реИ:


 void stop_debugging() { // TODO: Send Stopped event to client detach_debugger(); deactivate_debugger(); dbg_first_paused = dbg_paused = dbg_trace = dbg_dont_check_bp = dbg_step_over = dbg_step_over_addr = dbg_last_pc = 0; } void start_debugging() { if (dbg_active) return; activate_debugger(); init_bpt_list(); dbg_first_paused = dbg_paused = dbg_trace = dbg_dont_check_bp = dbg_step_over = dbg_step_over_addr = dbg_last_pc = 0; } 

рдбреАрдмрдЧрд░ рдХрд░реНрдиреЗрд▓: рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди


рдбрд┐рдмрдЧ рд╕рд░реНрд╡рд░ рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рдмреАрдЪ рд╕рдВрдЪрд╛рд░ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЛ рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рдбреАрдмрдЧрд┐рдВрдЧ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╛ рджреВрд╕рд░рд╛ рджрд┐рд▓ рдХрд╣рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЧреНрд░рд╛рд╣рдХ рд╕реЗ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЙрди рдкрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд░рддрд╛ рд╣реИред
рдЗрд╕реЗ рд╕рд╛рдЭрд╛ рдореЗрдореЛрд░реА рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдХреНрдпреЛрдВрдХрд┐ рдореЗрдореЛрд░реА рдХреЗ рдмрдбрд╝реЗ рдмреНрд▓реЙрдХреЛрдВ рдХреЛ рднреЗрдЬрдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ: VRAM , RAM , ROM , рдФрд░ рдиреЗрдЯрд╡рд░реНрдХ рдкрд░ рдпрд╣ рдФрд░ рднреА рдордЬреЗрджрд╛рд░ рд╣реЛрдЧрд╛ред


рд╕рд╛рд░ рдпрд╣ рд╣реИ: рдХрд░реНрдиреЗрд▓ рдПрдХ рдкреВрд░реНрд╡рдирд┐рд░реНрдзрд╛рд░рд┐рдд рд╕рдВрд░рдЪрдирд╛ рдХреЗ рд╕рд╛рде рдПрдХ рд╕рд╛рдЭрд╛ рдореЗрдореЛрд░реА рдмрдирд╛рддрд╛ рд╣реИ, рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕реЗ рдЖрдиреЗ рд╡рд╛рд▓реЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рдЕрдкреЗрдХреНрд╖рд╛ рдХрд░рддрд╛ рд╣реИред рдЕрдиреБрд░реЛрдз рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЙрддреНрддрд░ рдХреЛ рдЙрд╕реА рдореЗрдореЛрд░реА рдореЗрдВ рд╕рд╣реЗрдЬрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рд╕рдВрдмрдВрдзрд┐рдд рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рдЙрд╕реА рдореЗрдореЛрд░реА рдореЗрдВ рдбреАрдмрдЧрд░ рдШрдЯрдирд╛рдУрдВ рдХреА рд╕реВрдЪреА рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИред


рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк рдХреЛ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдЪреБрдирд╛ рдЧрдпрд╛ рдерд╛:


рд╕реНрд░реЛрдд рдкреИрдХреЗрдЬ debug_wrap.h рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ
 #ifndef _DEBUG_WRAP_H_ #define _DEBUG_WRAP_H_ #ifdef __cplusplus extern "C" { #endif #include <Windows.h> #define SHARED_MEM_NAME "GX_PLUS_SHARED_MEM" #define MAX_BREAKPOINTS 1000 #define MAX_DBG_EVENTS 20 #ifndef MAXROMSIZE #define MAXROMSIZE ((unsigned int)0xA00000) #endif #pragma pack(push, 4) typedef enum { BPT_ANY = (0 << 0), // M68K BPT_M68K_E = (1 << 0), BPT_M68K_R = (1 << 1), BPT_M68K_W = (1 << 2), BPT_M68K_RW = BPT_M68K_R | BPT_M68K_W, // VDP BPT_VRAM_R = (1 << 3), BPT_VRAM_W = (1 << 4), BPT_VRAM_RW = BPT_VRAM_R | BPT_VRAM_W, BPT_CRAM_R = (1 << 5), BPT_CRAM_W = (1 << 6), BPT_CRAM_RW = BPT_CRAM_R | BPT_CRAM_W, BPT_VSRAM_R = (1 << 7), BPT_VSRAM_W = (1 << 8), BPT_VSRAM_RW = BPT_VSRAM_R | BPT_VSRAM_W, // Z80 BPT_Z80_E = (1 << 11), BPT_Z80_R = (1 << 12), BPT_Z80_W = (1 << 13), BPT_Z80_RW = BPT_Z80_R | BPT_Z80_W, // REGS BPT_VDP_REG = (1 << 9), BPT_M68K_REG = (1 << 10), } bpt_type_t; typedef enum { REQ_NO_REQUEST, REQ_GET_REGS, REQ_SET_REGS, REQ_GET_REG, REQ_SET_REG, REQ_READ_68K_ROM, REQ_READ_68K_RAM, REQ_WRITE_68K_ROM, REQ_WRITE_68K_RAM, REQ_READ_Z80, REQ_WRITE_Z80, REQ_ADD_BREAK, REQ_TOGGLE_BREAK, REQ_DEL_BREAK, REQ_CLEAR_BREAKS, REQ_LIST_BREAKS, REQ_ATTACH, REQ_PAUSE, REQ_RESUME, REQ_STOP, REQ_STEP_INTO, REQ_STEP_OVER, } request_type_t; typedef enum { REG_TYPE_M68K = (1 << 0), REG_TYPE_S80 = (1 << 1), REG_TYPE_Z80 = (1 << 2), REG_TYPE_VDP = (1 << 3), } register_type_t; typedef enum { DBG_EVT_NO_EVENT, DBG_EVT_STARTED, DBG_EVT_PAUSED, DBG_EVT_BREAK, DBG_EVT_STEP, DBG_EVT_STOPPED, } dbg_event_type_t; typedef struct { dbg_event_type_t type; unsigned int pc; char msg[256]; } debugger_event_t; typedef struct { int index; unsigned int val; } reg_val_t; typedef struct { unsigned int d0, d1, d2, d3, d4, d5, d6, d7; unsigned int a0, a1, a2, a3, a4, a5, a6, a7; unsigned int pc, sr, sp, usp, isp, ppc, ir; } regs_68k_data_t; typedef enum { REG_68K_D0, REG_68K_D1, REG_68K_D2, REG_68K_D3, REG_68K_D4, REG_68K_D5, REG_68K_D6, REG_68K_D7, REG_68K_A0, REG_68K_A1, REG_68K_A2, REG_68K_A3, REG_68K_A4, REG_68K_A5, REG_68K_A6, REG_68K_A7, REG_68K_PC, REG_68K_SR, REG_68K_SP, REG_68K_USP, REG_68K_ISP, REG_68K_PPC, REG_68K_IR, REG_VDP_00, REG_VDP_01, REG_VDP_02, REG_VDP_03, REG_VDP_04, REG_VDP_05, REG_VDP_06, REG_VDP_07, REG_VDP_08, REG_VDP_09, REG_VDP_0A, REG_VDP_0B, REG_VDP_0C, REG_VDP_0D, REG_VDP_0E, REG_VDP_0F, REG_VDP_10, REG_VDP_11, REG_VDP_12, REG_VDP_13, REG_VDP_14, REG_VDP_15, REG_VDP_16, REG_VDP_17, REG_VDP_18, REG_VDP_19, REG_VDP_1A, REG_VDP_1B, REG_VDP_1C, REG_VDP_1D, REG_VDP_1E, REG_VDP_1F, REG_VDP_DMA_LEN, REG_VDP_DMA_SRC, REG_VDP_DMA_DST, REG_Z80_PC, REG_Z80_SP, REG_Z80_AF, REG_Z80_BC, REG_Z80_DE, REG_Z80_HL, REG_Z80_IX, REG_Z80_IY, REG_Z80_WZ, REG_Z80_AF2, REG_Z80_BC2, REG_Z80_DE2, REG_Z80_HL2, REG_Z80_R, REG_Z80_R2, REG_Z80_IFFI1, REG_Z80_IFFI2, REG_Z80_HALT, REG_Z80_IM, REG_Z80_I, } regs_all_t; typedef struct { unsigned int pc, sp, af, bc, de, hl, ix, iy, wz; unsigned int af2,bc2,de2,hl2; unsigned char r, r2, iff1, iff2, halt, im, i; } regs_z80_data_t; typedef struct { unsigned char regs_vdp[0x20]; unsigned short dma_len; unsigned int dma_src, dma_dst; } vdp_regs_t; typedef struct { int type; // register_type_t regs_68k_data_t regs_68k; reg_val_t any_reg; vdp_regs_t vdp_regs; regs_z80_data_t regs_z80; } register_data_t; typedef struct { int size; unsigned int address; unsigned char m68k_rom[MAXROMSIZE]; unsigned char m68k_ram[0x10000]; unsigned char z80_ram[0x2000]; } memory_data_t; typedef struct { bpt_type_t type; unsigned int address; int width; int enabled; } bpt_data_t; typedef struct { int count; bpt_data_t breaks[MAX_BREAKPOINTS]; } bpt_list_t; typedef struct { request_type_t req_type; register_data_t regs_data; memory_data_t mem_data; bpt_data_t bpt_data; int dbg_events_count; debugger_event_t dbg_events[MAX_DBG_EVENTS]; bpt_list_t bpt_list; int dbg_active, dbg_paused; int is_ida; } dbg_request_t; #pragma pack(pop) dbg_request_t *open_shared_mem(); void close_shared_mem(dbg_request_t **request); int recv_dbg_event(dbg_request_t *request, int wait); void send_dbg_request(dbg_request_t *request, request_type_t type); #ifdef __cplusplus } #endif #endif 

рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдкрд╣рд▓рд╛ рдХреНрд╖реЗрддреНрд░ рдЕрдиреБрд░реЛрдз рдХрд╛ рдкреНрд░рдХрд╛рд░ рд╣реЛрдЧрд╛:


  • рд░реАрдб / рд╕реЗрдЯ рд░рдЬрд┐рд╕реНрдЯрд░
  • рдореЗрдореЛрд░реА рдкрдврд╝реЗрдВ / рд▓рд┐рдЦреЗрдВ
  • рдмреНрд░реЗрдХрдкреЙрдЗрдВрдЯ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░реЗрдВ
  • рдбрд┐рдмрдЧрд░ рдХреЛ рд░реЛрдХрдирд╛ / рдЬрд╛рд░реА рд░рдЦрдирд╛, рдбрд┐рд╕реНрдХрдиреЗрдХреНрдЯ / рдмрдВрдж рдХрд░рдирд╛
  • Step Into / Step Over

рдЗрд╕рдХреЗ рдмрд╛рдж рд░рдЬрд┐рд╕реНрдЯрд░ рд╣реИрдВ M68K , Z80 , VDP ред рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдореЗрдореЛрд░реА рдмреНрд▓реЙрдХ ROM , RAM , VRAM , Z80 ред


рдПрдХ рджрд░рд╛рд░ рдХреЛ рдЬреЛрдбрд╝рдиреЗ / рд╣рдЯрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рд╕рдВрдЧрдд рд╕рдВрд░рдЪрдирд╛ рднреА рдмрдирд╛рдИред рдЦреИрд░, рдЙрдирдХреА рд╕реВрдЪреА рднреА рдпрд╣рд╛рдВ рд╣реИ (рдЕрдзрд┐рдХрд╛рдВрд╢ рднрд╛рдЧ рдХреЗ рд▓рд┐рдП, рдпрд╣ рдХреЗрд╡рд▓ рдЬреАрдпреВрдЖрдИ рдореЗрдВ рдкреНрд░рджрд░реНрд╢рди рдХреЗ рд▓рд┐рдП рд╣реИ, рд╕рднреА рд╕реНрдерд╛рдкрд┐рдд рдмреНрд░реЗрдХ рдХреЛ рдпрд╛рдж рд░рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЗ рдмрд┐рдирд╛, рдЬреИрд╕рд╛ рдХрд┐ IDA рдХрд░рддрд╛ рд╣реИ)ред


рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдбрд┐рдмрдЧрд┐рдВрдЧ рдШрдЯрдирд╛рдУрдВ рдХреА рдПрдХ рд╕реВрдЪреА рд╣реИ:


  • рдбрд┐рдмрдЧрд┐рдВрдЧ рд╢реБрд░реВ ( IDA Pro рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ)
  • рдбрд┐рдмрдЧрд┐рдВрдЧ рдХреЛ рд░реЛрдХ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ (рдЬрд┐рд╕ рдкрд░ рдПрдореБрд▓реЗрд╢рди рд╡рд░реНрддрдорд╛рди рдореЗрдВ рд░реЛрдХрд╛ рдЧрдпрд╛ рд╣реИ рд╡рд╣ PC рдШрдЯрдирд╛ рдореЗрдВ рдмрдЪ рдЧрдпрд╛ рд╣реИ)
  • рдмреНрд░реЗрдХрдкреЙрдЗрдВрдЯ рдиреЗ рдХрд╛рдо рдХрд┐рдпрд╛ ( PC рдХрд╛ рдореВрд▓реНрдп рднреА, рдЬрд┐рд╕ рдкрд░ рдСрдкрд░реЗрд╢рди рд╣реБрдЖ)
  • Step Into рдпрд╛ Step Over рдкреНрд░рджрд░реНрд╢рди рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ (рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдХреЗрд╡рд▓ IDA рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЖрдк рдХреЗрд╡рд▓ рдПрдХ рдард╣рд░рд╛рд╡ рдШрдЯрдирд╛ рдХреЗ рд╕рд╛рде рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ)
  • рдЕрдиреБрдХрд░рдг рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рд░реЛрдХ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЗрд╕ рдШрдЯрдирд╛ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдП рдмрд┐рдирд╛ IDA рдореЗрдВ Stop рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдпрд╣ рдПрдХ рд╕реНрдЯреЙрдк рдХреЗ рд▓рд┐рдП рдЕрдВрддрд╣реАрди рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░реЗрдЧрд╛

рдПрдХ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЗ рд╡рд┐рдЪрд╛рд░ рдХреЗ рд╕рд╛рде рд╕рд╢рд╕реНрддреНрд░, рд╣рдо рдЧреНрд░рд╛рд╣рдХ рдЕрдиреБрд░реЛрдз рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдбреАрдмрдЧрд░ рдХрд░реНрдиреЗрд▓ рдХреЛрдб рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ:


рд╕реНрд░реЛрдд рдкреИрдХреЗрдЬ debug.c рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ
 #include "debug.h" #include "shared.h" #define m68ki_cpu m68k #define MUL (7) #ifndef BUILD_TABLES #include "m68ki_cycles.h" #endif #include "m68kconf.h" #include "m68kcpu.h" #include "m68kops.h" #include "vdp_ctrl.h" #include "Z80.h" static int dbg_first_paused, dbg_trace, dbg_dont_check_bp; static int dbg_step_over; static int dbg_last_pc; static unsigned int dbg_step_over_addr; static dbg_request_t *dbg_req = NULL; static HANDLE hMapFile = 0; typedef struct breakpoint_s { struct breakpoint_s *next, *prev; int enabled; int width; bpt_type_t type; unsigned int address; } breakpoint_t; static breakpoint_t *first_bp = NULL; static breakpoint_t *add_bpt(bpt_type_t type, unsigned int address, int width) { breakpoint_t *bp = (breakpoint_t *)malloc(sizeof(breakpoint_t)); bp->type = type; bp->address = address; bp->width = width; bp->enabled = 1; if (first_bp) { bp->next = first_bp; bp->prev = first_bp->prev; first_bp->prev = bp; bp->prev->next = bp; } else { first_bp = bp; bp->next = bp; bp->prev = bp; } return bp; } static void delete_breakpoint(breakpoint_t * bp) { if (bp == first_bp) { if (bp->next == bp) { first_bp = NULL; } else { first_bp = bp->next; } } bp->next->prev = bp->prev; bp->prev->next = bp->next; free(bp); } static breakpoint_t *next_breakpoint(breakpoint_t *bp) { return bp->next != first_bp ? bp->next : 0; } static breakpoint_t *find_breakpoint(unsigned int address, bpt_type_t type) { breakpoint_t *p; for (p = first_bp; p; p = next_breakpoint(p)) { if ((p->address == address) && ((p->type == BPT_ANY) || (p->type & type))) return p; } return 0; } static void remove_bpt(unsigned int address, bpt_type_t type) { breakpoint_t *bpt; if ((bpt = find_breakpoint(address, type))) delete_breakpoint(bpt); } static int count_bpt_list() { breakpoint_t *p; int i = 0; for (p = first_bp; p; p = next_breakpoint(p)) { ++i; } return i; } static void get_bpt_data(int index, bpt_data_t *data) { breakpoint_t *p; int i = 0; for (p = first_bp; p; p = next_breakpoint(p)) { if (i == index) { data->address = p->address; data->width = p->width; data->type = p->type; data->enabled = p->enabled; break; } ++i; } } static void clear_bpt_list() { while (first_bp != NULL) delete_breakpoint(first_bp); } static void init_bpt_list() { if (first_bp) clear_bpt_list(); } void check_breakpoint(bpt_type_t type, int width, unsigned int address, unsigned int value) { if (!dbg_req || !dbg_req->dbg_active || dbg_dont_check_bp) return; breakpoint_t *bp; for (bp = first_bp; bp; bp = next_breakpoint(bp)) { if (!(bp->type & type) || !bp->enabled) continue; if ((address <= (bp->address + bp->width)) && ((address + width) >= bp->address)) { dbg_req->dbg_paused = 1; break; } } } static void pause_debugger() { dbg_trace = 1; dbg_req->dbg_paused = 1; } static void resume_debugger() { dbg_trace = 0; dbg_req->dbg_paused = 0; } static void detach_debugger() { clear_bpt_list(); resume_debugger(); } static void activate_debugger() { dbg_req->dbg_active = 1; } static void deactivate_debugger() { dbg_req->dbg_active = 0; } int activate_shared_mem() { hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(dbg_request_t), SHARED_MEM_NAME); if (hMapFile == 0) { return -1; } dbg_req = (dbg_request_t*)MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(dbg_request_t)); if (dbg_req == 0) { CloseHandle(hMapFile); return -1; } memset(dbg_req, 0, sizeof(dbg_request_t)); return 0; } void deactivate_shared_mem() { UnmapViewOfFile(dbg_req); CloseHandle(hMapFile); hMapFile = NULL; dbg_req = NULL; } static unsigned int calc_step_over() { unsigned int pc = m68k_get_reg(M68K_REG_PC); unsigned int sp = m68k_get_reg(M68K_REG_SP); unsigned int opc = m68ki_read_imm_16(); unsigned int dest_pc = (unsigned int)(-1); // jsr if ((opc & 0xFFF8) == 0x4E90) { m68k_op_jsr_32_ai(); m68k_op_rts_32(); dest_pc = m68k_get_reg(M68K_REG_PC); } else if ((opc & 0xFFF8) == 0x4EA8) { m68k_op_jsr_32_di(); m68k_op_rts_32(); dest_pc = m68k_get_reg(M68K_REG_PC); } else if ((opc & 0xFFF8) == 0x4EB0) { m68k_op_jsr_32_ix(); m68k_op_rts_32(); dest_pc = m68k_get_reg(M68K_REG_PC); } else if ((opc & 0xFFFF) == 0x4EB8) { m68k_op_jsr_32_aw(); m68k_op_rts_32(); dest_pc = m68k_get_reg(M68K_REG_PC); } else if ((opc & 0xFFFF) == 0x4EB9) { m68k_op_jsr_32_al(); m68k_op_rts_32(); dest_pc = m68k_get_reg(M68K_REG_PC); } else if ((opc & 0xFFFF) == 0x4EBA) { m68k_op_jsr_32_pcdi(); m68k_op_rts_32(); dest_pc = m68k_get_reg(M68K_REG_PC); } else if ((opc & 0xFFFF) == 0x4EBB) { m68k_op_jsr_32_pcix(); m68k_op_rts_32(); dest_pc = m68k_get_reg(M68K_REG_PC); } // bsr else if ((opc & 0xFFFF) == 0x6100) { m68k_op_bsr_16(); m68k_op_rts_32(); dest_pc = m68k_get_reg(M68K_REG_PC); } else if ((opc & 0xFFFF) == 0x61FF) { m68k_op_bsr_32(); m68k_op_rts_32(); dest_pc = m68k_get_reg(M68K_REG_PC); } else if ((opc & 0xFF00) == 0x6100) { m68k_op_bsr_8(); m68k_op_rts_32(); dest_pc = m68k_get_reg(M68K_REG_PC); } // dbf else if ((opc & 0xfff8) == 0x51C8) { dest_pc = m68k_get_reg(M68K_REG_PC) + 2; } m68k_set_reg(M68K_REG_PC, pc); m68k_set_reg(M68K_REG_SP, sp); return dest_pc; } void process_request() { if (!dbg_req || !dbg_req->dbg_active) return; if (dbg_req->req_type == REQ_NO_REQUEST) return; switch (dbg_req->req_type) { case REQ_GET_REG: { register_data_t *regs_data = &dbg_req->regs_data; if (regs_data->type & REG_TYPE_M68K) regs_data->any_reg.val = m68k_get_reg(regs_data->any_reg.index); if (regs_data->type & REG_TYPE_VDP) regs_data->any_reg.val = reg[regs_data->any_reg.index]; if (regs_data->type & REG_TYPE_Z80) { if (regs_data->any_reg.index >= 0 && regs_data->any_reg.index <= 12) // PC <-> HL2 { regs_data->any_reg.val = ((unsigned int *)&Z80.pc)[regs_data->any_reg.index]; } else if (regs_data->any_reg.index >= 13 && regs_data->any_reg.index <= 19) // R <-> I { regs_data->any_reg.val = ((unsigned char *)&Z80.r)[regs_data->any_reg.index - 13]; } } } break; case REQ_SET_REG: { register_data_t *regs_data = &dbg_req->regs_data; if (regs_data->type & REG_TYPE_M68K) m68k_set_reg(regs_data->any_reg.index, regs_data->any_reg.val); if (regs_data->type & REG_TYPE_VDP) reg[regs_data->any_reg.index] = regs_data->any_reg.val; if (regs_data->type & REG_TYPE_Z80) { if (regs_data->any_reg.index >= 0 && regs_data->any_reg.index <= 12) // PC <-> HL2 { ((unsigned int *)&Z80.pc)[regs_data->any_reg.index] = regs_data->any_reg.val; } else if (regs_data->any_reg.index >= 13 && regs_data->any_reg.index <= 19) // R <-> I { ((unsigned char *)&Z80.r)[regs_data->any_reg.index - 13] = regs_data->any_reg.val & 0xFF; } } } break; case REQ_GET_REGS: case REQ_SET_REGS: { register_data_t *regs_data = &dbg_req->regs_data; if (regs_data->type & REG_TYPE_M68K) { regs_68k_data_t *m68kr = &regs_data->regs_68k; if (dbg_req->req_type == REQ_GET_REGS) { m68kr->d0 = m68k_get_reg(M68K_REG_D0); m68kr->d1 = m68k_get_reg(M68K_REG_D1); m68kr->d2 = m68k_get_reg(M68K_REG_D2); m68kr->d3 = m68k_get_reg(M68K_REG_D3); m68kr->d4 = m68k_get_reg(M68K_REG_D4); m68kr->d5 = m68k_get_reg(M68K_REG_D5); m68kr->d6 = m68k_get_reg(M68K_REG_D6); m68kr->d7 = m68k_get_reg(M68K_REG_D7); m68kr->a0 = m68k_get_reg(M68K_REG_A0); m68kr->a1 = m68k_get_reg(M68K_REG_A1); m68kr->a2 = m68k_get_reg(M68K_REG_A2); m68kr->a3 = m68k_get_reg(M68K_REG_A3); m68kr->a4 = m68k_get_reg(M68K_REG_A4); m68kr->a5 = m68k_get_reg(M68K_REG_A5); m68kr->a6 = m68k_get_reg(M68K_REG_A6); m68kr->a7 = m68k_get_reg(M68K_REG_A7); m68kr->pc = m68k_get_reg(M68K_REG_PC); m68kr->sr = m68k_get_reg(M68K_REG_SR); m68kr->sp = m68k_get_reg(M68K_REG_SP); m68kr->usp = m68k_get_reg(M68K_REG_USP); m68kr->isp = m68k_get_reg(M68K_REG_ISP); m68kr->ppc = m68k_get_reg(M68K_REG_PPC); m68kr->ir = m68k_get_reg(M68K_REG_IR); } else { m68k_set_reg(M68K_REG_D0, m68kr->d0); m68k_set_reg(M68K_REG_D1, m68kr->d1); m68k_set_reg(M68K_REG_D2, m68kr->d2); m68k_set_reg(M68K_REG_D3, m68kr->d3); m68k_set_reg(M68K_REG_D4, m68kr->d4); m68k_set_reg(M68K_REG_D5, m68kr->d5); m68k_set_reg(M68K_REG_D6, m68kr->d6); m68k_set_reg(M68K_REG_D7, m68kr->d7); m68k_set_reg(M68K_REG_A0, m68kr->a0); m68k_set_reg(M68K_REG_A1, m68kr->a1); m68k_set_reg(M68K_REG_A2, m68kr->a2); m68k_set_reg(M68K_REG_A3, m68kr->a3); m68k_set_reg(M68K_REG_A4, m68kr->a4); m68k_set_reg(M68K_REG_A5, m68kr->a5); m68k_set_reg(M68K_REG_A6, m68kr->a6); m68k_set_reg(M68K_REG_A7, m68kr->a7); m68k_set_reg(M68K_REG_PC, m68kr->pc); m68k_set_reg(M68K_REG_SR, m68kr->sr); m68k_set_reg(M68K_REG_SP, m68kr->sp); m68k_set_reg(M68K_REG_USP, m68kr->usp); m68k_set_reg(M68K_REG_ISP, m68kr->isp); } } if (regs_data->type & REG_TYPE_VDP) { vdp_regs_t *vdp_regs = &regs_data->vdp_regs; for (int i = 0; i < (sizeof(vdp_regs) / sizeof(vdp_regs->regs_vdp[0])); ++i) { if (dbg_req->req_type == REQ_GET_REGS) vdp_regs->regs_vdp[i] = reg[i]; else reg[i] = vdp_regs->regs_vdp[i]; } if (dbg_req->req_type == REQ_GET_REGS) { vdp_regs->dma_len = (reg[20] << 8) | reg[19]; if (!vdp_regs->dma_len) vdp_regs->dma_len = 0x10000; vdp_regs->dma_src = vdp_dma_calc_src(); vdp_regs->dma_dst = vdp_dma_get_dst(); } } if (regs_data->type & REG_TYPE_Z80) { regs_z80_data_t *z80r = &regs_data->regs_z80; if (dbg_req->req_type == REQ_GET_REGS) { z80r->pc = Z80.pc.d; z80r->sp = Z80.sp.d; z80r->af = Z80.af.d; z80r->bc = Z80.bc.d; z80r->de = Z80.de.d; z80r->hl = Z80.hl.d; z80r->ix = Z80.ix.d; z80r->iy = Z80.iy.d; z80r->wz = Z80.wz.d; z80r->af2 = Z80.af2.d; z80r->bc2 = Z80.bc2.d; z80r->de2 = Z80.de2.d; z80r->hl2 = Z80.hl2.d; z80r->r = Z80.r; z80r->r2 = Z80.r2; z80r->iff1 = Z80.iff1; z80r->iff2 = Z80.iff2; z80r->halt = Z80.halt; z80r->im = Z80.im; z80r->i = Z80.i; } else { Z80.pc.d = z80r->pc; Z80.sp.d = z80r->sp; Z80.af.d = z80r->af; Z80.bc.d = z80r->bc; Z80.de.d = z80r->de; Z80.hl.d = z80r->hl; Z80.ix.d = z80r->ix; Z80.iy.d = z80r->iy; Z80.wz.d = z80r->wz; Z80.af2.d = z80r->af2; Z80.bc2.d = z80r->bc2; Z80.de2.d = z80r->de2; Z80.hl2.d = z80r->hl2; Z80.r = z80r->r; Z80.r2 = z80r->r2; Z80.iff1 = z80r->iff1; Z80.iff2 = z80r->iff2; Z80.halt = z80r->halt; Z80.im = z80r->im; Z80.i = z80r->i; } } } break; case REQ_READ_68K_ROM: case REQ_READ_68K_RAM: case REQ_READ_Z80: { dbg_dont_check_bp = 1; memory_data_t *mem_data = &dbg_req->mem_data; for (int i = 0; i < mem_data->size; ++i) { switch (dbg_req->req_type) { case REQ_READ_68K_ROM: mem_data->m68k_rom[mem_data->address + i] = m68ki_read_8(mem_data->address + i); break; case REQ_READ_68K_RAM: mem_data->m68k_ram[(mem_data->address + i) & 0xFFFF] = m68ki_read_8(mem_data->address + i); break; case REQ_READ_Z80: mem_data->z80_ram[(mem_data->address + i) & 0x1FFF] = z80_readmem(mem_data->address + i); break; default: break; } } dbg_dont_check_bp = 0; } break; case REQ_WRITE_68K_ROM: case REQ_WRITE_68K_RAM: case REQ_WRITE_Z80: { dbg_dont_check_bp = 1; memory_data_t *mem_data = &dbg_req->mem_data; for (int i = 0; i < mem_data->size; ++i) { switch (dbg_req->req_type) { case REQ_WRITE_68K_ROM: m68ki_write_8(mem_data->address + i, mem_data->m68k_rom[mem_data->address + i]); break; case REQ_WRITE_68K_RAM: m68ki_write_8(0xFF0000 | ((mem_data->address + i) & 0xFFFF), mem_data->m68k_ram[(mem_data->address + i) & 0xFFFF]); break; case REQ_WRITE_Z80: z80_writemem(mem_data->address + i, mem_data->z80_ram[(mem_data->address + i) & 0x1FFF]); break; default: break; } } dbg_dont_check_bp = 0; } break; case REQ_ADD_BREAK: { bpt_data_t *bpt_data = &dbg_req->bpt_data; if (!find_breakpoint(bpt_data->address, bpt_data->type)) add_bpt(bpt_data->type, bpt_data->address, bpt_data->width); } break; case REQ_TOGGLE_BREAK: { bpt_data_t *bpt_data = &dbg_req->bpt_data; breakpoint_t *bp = find_breakpoint(bpt_data->address, bpt_data->type); if (bp != NULL) bp->enabled = !bp->enabled; } break; case REQ_DEL_BREAK: { bpt_data_t *bpt_data = &dbg_req->bpt_data; remove_bpt(bpt_data->address, bpt_data->type); } break; case REQ_CLEAR_BREAKS: clear_bpt_list(); case REQ_LIST_BREAKS: { bpt_list_t *bpt_list = &dbg_req->bpt_list; bpt_list->count = count_bpt_list(); for (int i = 0; i < bpt_list->count; ++i) get_bpt_data(i, &bpt_list->breaks[i]); } break; case REQ_ATTACH: activate_debugger(); dbg_first_paused = 0; break; case REQ_PAUSE: pause_debugger(); break; case REQ_RESUME: resume_debugger(); break; case REQ_STOP: stop_debugging(); break; case REQ_STEP_INTO: { if (dbg_req->dbg_paused) { dbg_trace = 1; dbg_req->dbg_paused = 0; } } break; case REQ_STEP_OVER: { if (dbg_req->dbg_paused) { unsigned int dest_pc = calc_step_over(); if (dest_pc != (unsigned int)(-1)) { dbg_step_over = 1; dbg_step_over_addr = dest_pc; } else { dbg_step_over = 0; dbg_step_over_addr = 0; dbg_trace = 1; } dbg_req->dbg_paused = 0; } } break; default: break; } dbg_req->req_type = REQ_NO_REQUEST; } void send_dbg_event(dbg_event_type_t type) { dbg_req->dbg_events[dbg_req->dbg_events_count].type = type; dbg_req->dbg_events_count += 1; } void stop_debugging() { send_dbg_event(DBG_EVT_STOPPED); detach_debugger(); deactivate_debugger(); dbg_first_paused = dbg_req->dbg_paused = dbg_trace = dbg_dont_check_bp = dbg_step_over = dbg_step_over_addr = dbg_last_pc = 0; } void start_debugging() { if (dbg_req != NULL && dbg_req->dbg_active) return; activate_debugger(); init_bpt_list(); dbg_first_paused = dbg_req->dbg_paused = dbg_trace = dbg_dont_check_bp = dbg_step_over = dbg_step_over_addr = dbg_last_pc = 0; } int is_debugger_accessible() { return (dbg_req != NULL); } void process_breakpoints() { int handled_event = 0; int is_step_over = 0; int is_step_in = 0; unsigned int pc = m68k_get_reg(M68K_REG_PC); if (!dbg_req || !dbg_req->dbg_active) return; if (dbg_req->dbg_paused && dbg_first_paused && !dbg_trace) longjmp(jmp_env, 1); if (!dbg_first_paused) { dbg_first_paused = 1; dbg_req->dbg_paused = 1; dbg_req->dbg_events[dbg_req->dbg_events_count].pc = pc; strncpy(dbg_req->dbg_events[dbg_req->dbg_events_count].msg, "gpgx", sizeof(dbg_req->dbg_events[dbg_req->dbg_events_count].msg)); send_dbg_event(DBG_EVT_STARTED); } if (dbg_trace) { is_step_in = 1; dbg_trace = 0; dbg_req->dbg_paused = 1; dbg_req->dbg_events[dbg_req->dbg_events_count].pc = pc; send_dbg_event(DBG_EVT_STEP); handled_event = 1; } if (!dbg_req->dbg_paused) { if (dbg_step_over && pc == dbg_step_over_addr) { is_step_over = 1; dbg_step_over = 0; dbg_step_over_addr = 0; dbg_req->dbg_paused = 1; } if (dbg_last_pc != pc) check_breakpoint(BPT_M68K_E, 1, pc, pc); if (dbg_req->dbg_paused) { dbg_req->dbg_events[dbg_req->dbg_events_count].pc = pc; send_dbg_event(is_step_over ? DBG_EVT_STEP : DBG_EVT_BREAK); handled_event = 1; } } if (dbg_first_paused && (!handled_event) && dbg_req->dbg_paused) { dbg_req->dbg_events[dbg_req->dbg_events_count].pc = pc; send_dbg_event(DBG_EVT_PAUSED); } dbg_last_pc = pc; if (dbg_req->dbg_paused && (!is_step_in || is_step_over)) { longjmp(jmp_env, 1); } } int is_debugger_paused() { return is_debugger_accessible() && dbg_req->dbg_paused && dbg_first_paused && !dbg_trace; } 

debug.h
 #ifndef _DEBUG_H_ #define _DEBUG_H_ #ifdef __cplusplus extern "C" { #endif #include <setjmp.h> #include "debug_wrap.h" extern void start_debugging(); extern void stop_debugging(); extern int is_debugger_accessible(); extern void process_request(); extern int is_debugger_paused(); extern int activate_shared_mem(); extern void deactivate_shared_mem(); void check_breakpoint(bpt_type_t type, int width, unsigned int address, unsigned int value); extern jmp_buf jmp_env; #ifdef __cplusplus } #endif #endif 

.
, check_breakpoint VDP #ifdef LOGVDP . vdp_ctrl.c :


 check_breakpoint(BPT_VRAM_W, 2, addr, data); ... check_breakpoint(BPT_CRAM_W, 2, addr, data); ... check_breakpoint(BPT_VSRAM_W, 2, addr, data); ... check_breakpoint(BPT_VRAM_R, 2, addr, data); ... check_breakpoint(BPT_CRAM_R, 2, addr, data); ... check_breakpoint(BPT_VSRAM_R, 2, addr, data); 

RAM ( m68kcpu.h ):


 // m68ki_read_8 check_breakpoint(BPT_M68K_R, 1, address, val); // m68ki_read_16 check_breakpoint(BPT_M68K_R, 2, address, val); // m68ki_read_32 check_breakpoint(BPT_M68K_R, 4, address, val); // m68ki_write_8 check_breakpoint(BPT_M68K_W, 1, address, val); // m68ki_write_16 check_breakpoint(BPT_M68K_W, 2, address, val); // m68ki_write_32 check_breakpoint(BPT_M68K_W, 4, address, val); 

, , .


debug_wrap.c
 #include <Windows.h> #include <process.h> #include "debug_wrap.h" static HANDLE hMapFile = NULL, hStartFunc = NULL; dbg_request_t *open_shared_mem() { hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, SHARED_MEM_NAME); if (hMapFile == NULL) { return NULL; } dbg_request_t *request = (dbg_request_t *)MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(dbg_request_t)); if (request == NULL) { CloseHandle(hMapFile); return NULL; } return request; } void close_shared_mem(dbg_request_t **request) { UnmapViewOfFile(*request); CloseHandle(hMapFile); hMapFile = NULL; *request = NULL; } int recv_dbg_event(dbg_request_t *request, int wait) { while (request->dbg_active || request->dbg_events_count) { for (int i = 0; i < MAX_DBG_EVENTS; ++i) { if (request->dbg_events[i].type != DBG_EVT_NO_EVENT) { request->dbg_events_count -= 1; return i; } } if (!wait) return -1; Sleep(10); } return -1; } void send_dbg_request(dbg_request_t *request, request_type_t type) { if (!request) return; request->req_type = type; while (request->dbg_active && request->req_type != REQ_NO_REQUEST) { Sleep(10); } } 

. , . , , , .


:


Genesis Plus GX :


  var.key = "genesis_plus_gx_debugger"; environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); { if (!var.value || !strcmp(var.value, "disabled")) { if (is_debugger_accessible()) { stop_debugging(); stop_gui(); deactivate_shared_mem(); } } else { activate_shared_mem(); start_debugging(); run_gui(); } } ... { "genesis_plus_gx_debugger", "Debugger; disabled|enabled" }, 

RetroArch :
, retro_run() . ( ), . , retro_run() , RetroArch . setjmp() / longjmp() . , retro_run() :


  if (is_debugger_paused()) { longjmp(jmp_env, 1); } int is_paused = setjmp(jmp_env); if (is_paused) { process_request(); return; } 

retro_run() process_request() , , .


PS



Update :
- IDA Pro , .

Source: https://habr.com/ru/post/hi434992/


All Articles