/************************************************************************
* disio.cpp *
* This is a fairly big class, and yet it was originally part of the *
* larger disasm class. I finally got around to splitting off some of *
* 3500 lines of code from that class into here. This represents the *
* disasm I/O functions for window I/O and file I/O. Version 2.11 was *
* when this was split. There are still a huge number of confusing *
* functions and code in here which probably needs more work to clean it *
* up, and better split/define the classes. Some of the functions are *
* friends of disasm because it has been difficult to split the classes *
* effectively and both access the complex main disassembly structures *
************************************************************************/
#include <windows.h>
#include <stdio.h> // for sprintf, for float printing
#include "disio.h"
#include "disasm.h"
#include "data.h"
#include "dasm.h"
#include "schedule.h"
#include "gname.h"
#include "xref.h"
#include "range.h"
#include "debug.h"
/************************************************************************
* globals *
* - actually some constants used in file i/o as a header *
************************************************************************/
char hdr[] =";\t Created by Borg Disassembler\r\n";
char hdr2[]=";\t written by Cronos + h#s\r\n";
disio *cvd; // pointer to data of focused view
/************************************************************************
* constructor function *
* - this just enables window updates and sets the subline to null *
* - the subline (subitem) is basically the line in the disassembly that *
* you see for any given loc. As a loc may refer to many lines (like *
* segheader, comments, xref, actual instruction are all separate *
* line, and subline says which of these it is) *
************************************************************************/
disio::disio(HWND w) {
wnd=w;
subitem=dsmnull;
// bufferbusy=false;
}
/************************************************************************
* destructor function *
* - currently null *
* - note that disio has no particular structs the same way most of the *
* other classes in Borg do *
************************************************************************/
disio::~disio()
{
}
/************************************************************************
* argoverdec *
* - disio also acts as a go between for the user and the disasm engine *
* - here we translate the users current line of the disassembly and *
* their request for a decimal override into a call to the disasm *
* engine to add the override to the instruction that is there *
* - note that these kind of calls come from the scheduler and are part *
* of the secondary thread *
************************************************************************/
void disio::argoverdec(void)
{ lptr outhere;
findcurrentaddr(&outhere);
dsm->disargoverdec(outhere);
}
/************************************************************************
* argoversingle *
* - very similar to argoverdec, for a single (float) override *
************************************************************************/
void disio::argoversingle(void)
{ lptr outhere;
findcurrentaddr(&outhere);
dsm->disargoversingle(outhere);
}
/************************************************************************
* argovernegate *
* - very similar to argoverdec, for an argument negation override *
************************************************************************/
void disio::arg_negate(void)
{ lptr outhere;
findcurrentaddr(&outhere);
dsm->disargnegate(outhere);
}
/************************************************************************
* argoverhex *
* - very similar to argoverdec, for a hex override *
************************************************************************/
void disio::argoverhex(void)
{ lptr outhere;
findcurrentaddr(&outhere);
dsm->disargoverhex(outhere);
}
/************************************************************************
* argoveroffsetdseg *
* - very similar to argoverdec, for a dseg override *
************************************************************************/
void disio::argoveroffsetdseg(void)
{ lptr outhere;
findcurrentaddr(&outhere);
dsm->disargoveroffsetdseg(outhere);
}
/************************************************************************
* argoverchar *
* - very similar to argoverdec, for a char override *
************************************************************************/
void disio::argoverchar(void)
{ lptr outhere;
findcurrentaddr(&outhere);
dsm->disargoverchar(outhere);
}
/************************************************************************
* makedword *
* - disio acts as a go between for the user and the disasm engine *
* - here we translate the users current line of the disassembly and *
* their request for a dword into a call to the disasm engine to *
* disassemble a dword at the current point *
* - note that these kind of calls come from the scheduler and are part *
* of the secondary thread *
************************************************************************/
void disio::makedword(void)
{ lptr outhere;
findcurrentaddr(&outhere);
if(outhere==curraddr)
subitem=dsmnull;
dsm->disdatadword(outhere);
}
/************************************************************************
* makesingle *
* - very similar to makedword, this time to disassemble a single *
* (float) *
************************************************************************/
void disio::makesingle(void) {
lptr outhere;
findcurrentaddr(&outhere);
if (outhere==curraddr) subitem=dsmnull;
dsm->disdatasingle(outhere);
}
/************************************************************************
* makedouble *
* - very similar to makedword, this time to disassemble a double *
* (double float) *
************************************************************************/
void disio::makedouble(void)
{ lptr outhere;
findcurrentaddr(&outhere);
if(outhere==curraddr)
subitem=dsmnull;
dsm->disdatadouble(outhere);
}
/************************************************************************
* makelongdouble *
* - very similar to makedword, this time to disassemble a long double *
* (long double) *
************************************************************************/
void disio::makelongdouble(void)
{ lptr outhere;
findcurrentaddr(&outhere);
if(outhere==curraddr)
subitem=dsmnull;
dsm->disdatalongdouble(outhere);
}
/************************************************************************
* makeword *
* - very similar to makedword, this time to disassemble a word *
************************************************************************/
void disio::makeword(void)
{ lptr outhere;
findcurrentaddr(&outhere);
if(outhere==curraddr)
subitem=dsmnull;
dsm->disdataword(outhere);
}
/************************************************************************
* makestring *
* - very similar to makedword, this time to disassemble a string *
* (standard C string) *
************************************************************************/
void disio::makestring(void)
{ lptr outhere;
findcurrentaddr(&outhere);
if(outhere==curraddr)
subitem=dsmnull;
dsm->disdatastring(outhere);
}
/************************************************************************
* pascalstring *
* - very similar to makedword, this time to disassemble a string *
* (standard pascal string) *
************************************************************************/
void disio::pascalstring(void)
{ lptr outhere;
findcurrentaddr(&outhere);
if(outhere==curraddr)
subitem=dsmnull;
dsm->disdatapstring(outhere);
}
/************************************************************************
* ucstring *
* - very similar to makedword, this time to disassemble a string *
* (unicode C string) *
************************************************************************/
void disio::ucstring(void)
{ lptr outhere;
findcurrentaddr(&outhere);
if(outhere==curraddr)
subitem=dsmnull;
dsm->disdataucstring(outhere);
}
/************************************************************************
* upstring *
* - very similar to makedword, this time to disassemble a string *
* (unicode pascal string) *
************************************************************************/
void disio::upstring(void)
{ lptr outhere;
findcurrentaddr(&outhere);
if(outhere==curraddr)
subitem=dsmnull;
dsm->disdataupstring(outhere);
}
/************************************************************************
* dosstring *
* - very similar to makedword, this time to disassemble a string *
* (dos style string) *
************************************************************************/
void disio::dosstring(void)
{ lptr outhere;
findcurrentaddr(&outhere);
if(outhere==curraddr)
subitem=dsmnull;
dsm->disdatadosstring(outhere);
}
/************************************************************************
* generalstring *
* - very similar to makedword, this time to disassemble a string *
* (general string) *
************************************************************************/
void disio::generalstring(void)
{ lptr outhere;
findcurrentaddr(&outhere);
if(outhere==curraddr)
subitem=dsmnull;
dsm->disdatageneralstring(outhere);
}
/************************************************************************
* makecode *
* - very similar to makedword, but this time to disassemble as code *
* from the current location, and continue disassembling *
************************************************************************/
void disio::makecode(void)
{ lptr outhere;
findcurrentaddr(&outhere);
if(outhere==curraddr)
subitem=dsmnull;
dsm->disblock(outhere);
}
/************************************************************************
* vertsetpos *
* - this function takes a position of the vertical scroll bar, from 0 *
* to the VERTSCROLLRANGE and it sets the current address to that *
* point *
************************************************************************/
void disio::vertsetpos(int pos) {
unsigned long location;
#ifdef WIN32
location=(unsigned)MulDiv(pos,(int)total_data_size,VERTSCROLLRANGE);
#else
location=(unsigned long)((float)pos/VERTSCROLLRANGE*total_data_size);
#endif
setcuraddr(dta->getlocpos(location)); // linear to seg:ofs
}
// reverse function, sets scroll bar to seg:ofs given
// Vertical scroll bar has no PAGESIZE feedback yet
void disio::setscrollpos(lptr loc) {
DWORD current_data_pos=dta->datagetpos(loc); // seg:ofs to linear
#ifdef WIN32
int sbarpos=MulDiv((int)current_data_pos,VERTSCROLLRANGE,(int)total_data_size+1);
#else
int sbarpos=(int)((float)current_data_pos/(total_data_size+1)*VERTSCROLLRANGE;
#endif
SetScrollPos(wnd,SB_VERT,sbarpos,true);
}
/************************************************************************
* setcuraddr *
* - sets the address as a location for the screen output to start at *
* - also sets the scroll bar position for the vertical scroll bar *
* - also ensures that its not set to a mid-instruction address and *
* sets the subline *
* - called from many places in the source code *
************************************************************************/
void disio::setcuraddr(lptr loc) {
dsmitem titem,*tblock;
dsegitem *l_ds;
// check for non-existant address added v2.20
l_ds=dta->findseg(loc);
if (!l_ds) return;
curraddr=loc; // set top line address
titem.addr=curraddr;
titem.type=dsmnull;
dsm->findnext(&titem);
tblock=dsm->nextiterator();
if (tblock) subitem=tblock->type;
else subitem=dsmnull;
tblock=dsm->nextiter_code(tblock);
if (tblock && loc.between(tblock->addr,tblock->addr+tblock->length-1))
curraddr=tblock->addr;
outend=loc+50;
sel=0;
updatewindow();
setscrollpos(loc);
}
// calculates the rectangle for item at line <item> using CharBox.y
void disio::GetItemRect(int item, PRECT R) {
GetClientRect(wnd,R);
R->top=item*CharBox.y;
R->bottom=R->top+CharBox.y;
}
/************************************************************************
* setpos *
* - when the left mouse button is pressed the line is changed to the *
* line the mouse points at. This routine sets the line, and asks for *
* a screen update if needed (the screen update method here is a *
* primary thread request that simply invalidates the window rather *
* than requesting through the scheduler... *
************************************************************************/
void disio::setpos(int ypos) {
if (ypos!=sel) {
RECT R;
GetItemRect(sel,&R);
sel=ypos;
InvalidateRect(wnd,&R,TRUE); // let remove marker
GetItemRect(sel,&R);
InvalidateRect(wnd,&R,TRUE); // let set marker
}
}
/************************************************************************
* printlineheader *
* - prints an appropriate line header with the address if needed and *
* sets the cursor position for the next LastPrintBuff call *
************************************************************************/
void disio::printlineheader(lptr loc,bool printaddrs) {
if (options.mode32) {
if (printaddrs) PrintBuff(/*"%04lx:"*/"%08lx",/*loc.segm,*/loc.offs);
else PrintBuff("");
LastPrintBuffEpos(BYTEPOS-5);
}else{
if (printaddrs) PrintBuff("%04lx:%04lx",loc.segm,loc.offs);
else PrintBuff("");
LastPrintBuffEpos(BYTEPOS-4);
}
}
/************************************************************************
* outinst *
* - this is the routine which results in the output of an address, hex *
* bytes, instruction and arguments *
************************************************************************/
void disio::outinst(dsmitem *inst,bool printaddrs) {
dsegitem *dblock;
int i;
int prefixptr;
byte pbyte;
printlineheader(inst->addr,printaddrs);
dblock=dta->findseg(inst->addr); // find segment item.
switch (inst->type) {
case dsmcode: {
i=inst->length;
if (printaddrs) {
while (i) {
if (dblock) {
if (dblock->typ==uninitdata) LastPrintBuff("??");
else LastPrintBuff("%02x",inst->data[inst->length-i]);
}else LastPrintBuff("%02x",inst->data[inst->length-i]);
i--;
if (i+8<inst->length && inst->length>10) {
LastPrintBuff("..");
break;
}
}
}
if (options.mode32) LastPrintBuffEpos(ASMPOS+4);
else LastPrintBuffEpos(ASMPOS);
if (inst->flags&FLAGS_PREFIX) {
prefixptr=0;
while (!isprefix(inst->data[prefixptr]) && prefixptr<15) prefixptr++;
pbyte=inst->data[prefixptr];
outprefix(pbyte);
}
LastPrintBuff(DSMITEM_NAME(inst));
LastPrintBuff(" ");
if (options.mode32) LastPrintBuffEpos(ARGPOS+4);
else LastPrintBuffEpos(ARGPOS);
if (dblock) {
if (dblock->typ==uninitdata) LastPrintBuff("?");
else{
outargs(inst,DSMITEM_ARG1(inst));
if (DSMITEM_ARG2(inst)!=ARG_NONE) {
LastPrintBuff(", ");
outargs(inst,DSMITEM_ARG2(inst));
}
if (DSMITEM_ARG3(inst)!=ARG_NONE) {
LastPrintBuff(", ");
outargs(inst,DSMITEM_ARG3(inst));
}
}
}else{
outargs(inst,DSMITEM_ARG1(inst));
if (DSMITEM_ARG2(inst)!=ARG_NONE) {
LastPrintBuff(", ");
outargs(inst,DSMITEM_ARG2(inst));
}
if (DSMITEM_ARG3(inst)!=ARG_NONE) {
LastPrintBuff(", ");
outargs(inst,DSMITEM_ARG3(inst));
}
}
}break;
}
}
/************************************************************************
* outdb *
* - this is similar to outinst, but when there is no disassembly for a *
* loc we call this to output a db xxh or a db ? if its uninitdata *
************************************************************************/
void disio::outdb(lptr *lp,bool printaddrs) {
dsegitem *dblock;
dword aaddr;
byte *mcode;
printlineheader(*lp,printaddrs);
dblock=dta->findseg(*lp); // find segment item.
if (!dblock) {
if (printaddrs) LastPrintBuff("??");
}else if (dblock->typ==uninitdata) {
if (printaddrs) LastPrintBuff("??");
}else{
aaddr=(*lp-dblock->addr);
mcode=dblock->data+aaddr;
if (printaddrs) LastPrintBuff("%02x",mcode[0]);
}
if (options.mode32) LastPrintBuffEpos(ASMPOS+4);
else LastPrintBuffEpos(ASMPOS);
LastPrintBuff("db");
if (options.mode32) LastPrintBuffEpos(ARGPOS+4);
else LastPrintBuffEpos(ARGPOS);
// changed to single ? - 2.25
if (!dblock) LastPrintBuff("?");
else if (dblock->typ==uninitdata) {
LastPrintBuff("?");
}else{
LastPrintBuffHexValue(mcode[0]);
if (isprint(mcode[0])) {
LastPrintBuffEpos(COMMENTPOS);
LastPrintBuff(";'%c'",mcode[0]);
}
}
}
/************************************************************************
* issegprefix *
* - returns true if byte is a segment prefix valid value *
************************************************************************/
bool disio::issegprefix(byte byt) {
switch (byt) {
case 0x2e:
case 0x36:
case 0x3e:
case 0x26:
case 0x64:
case 0x65: return true;
}
return false;
}
/************************************************************************
* isprefix *
* - returns true if byte is a prefix valid value (rep/repne/lock) *
************************************************************************/
bool disio::isprefix(byte byt) {
switch (byt) {
case 0xf0:
case 0xf2:
case 0xf3: return true;
}
return false;
}
/************************************************************************
* outprefix *
* - here we output a prefix segment override *
************************************************************************/
void disio::outprefix(byte prefixbyte) {
char *s;
switch (prefixbyte) {
case 0x2e: s="cs:"; break;
case 0x36: s="ss:"; break;
case 0x3e: s="ds:"; break;
case 0x26: s="es:"; break;
case 0x64: s="fs:"; break;
case 0x65: s="gs:"; break;
case 0xf0: s="lock "; break;
case 0xf2: s="repne ";break;
case 0xf3: s="repe "; break;
default: s="err:";
}
LastPrintBuff(s);
}
/************************************************************************
* jumpback *
* - when the user presses ESC, or selects jump back we get the last *
* address from the top of the address stack and call setcuraddr and *
* update the window and so the disassembly listing flicks back *
************************************************************************/
void disio::jumpback(void) {
if (!retstack.stacktop) return;
setcuraddr(retstack.pop());
sel=selstack[retstack.stacktop];
if ((unsigned)sel>=(unsigned)size.y) sel=0; // for invalid values
updatewindow();
}
/************************************************************************
* jumpto *
* - more complex than the jumpback is the jumpto. The complexity lies *
* in deciding where we are jumping to and what the arguments value is *
* and if the location exists. Actually making the jump consists of *
* saving the current location to the address stack and then changing *
* the curraddr for output, and updating the window *
* - most of this routine is a complex decipherment of a modrm address *
* to jump to *
* NB I need to stick this in a function of its own at some point, as it *
* would be quite useful to just get an argument address in several *
* places in the code *
************************************************************************/
void disio::jumpto(bool arg1) {
dsmitem *tblock;
lptr outhere;
byte *data;
bool madejump;
byte modrm,sib;
word rm;
tblock=findcurrentline();
outhere.assign(0,0);
if (tblock && tblock->type!=dsmcode) return;
madejump=false;
if (tblock) {
if (arg1) {
switch (DSMITEM_ARG1(tblock)) {
case ARG_FADDR: {
data=tblock->data+tblock->length;
if (tblock->mode32) {
data-=6;
outhere.assign(((word *)(&data[4]))[0],((dword *)(&data[0]))[0]);
}else{
data-=4;
outhere.assign(((word *)(&data[2]))[0],((word *)(&data[0]))[0]);
}
if (follow(outhere)) madejump=true;
}break;
case ARG_IMM32: {
if (tblock->override!=over_dsoffset) break;
data=tblock->data+tblock->length;
data-=4;
outhere.assign(options.dseg,((dword *)(&data[0]))[0]);
if (follow(outhere)) madejump=true;
}break;
case ARG_MEMLOC: {
data=tblock->data+tblock->length;
if (options.mode32) {
data-=4;
outhere.assign(tblock->addr.segm,((dword *)data)[0]);
}else{
data-=2;
outhere.assign(tblock->addr.segm,((word *)data)[0]);
}
if (follow(outhere)) madejump=true;
}break;
case ARG_IMM: {
if (tblock->override!=over_dsoffset) break;
if (options.mode32) {
data=tblock->data+tblock->length;
data-=4;
outhere.assign(options.dseg,((dword *)(&data[0]))[0]);
if (follow(outhere)) madejump=true;
}
}break;
case ARG_RELIMM: {
data=tblock->data+tblock->length;
outhere=tblock->addr;
if (tblock->mode32) {
data-=4;
outhere+=((dword *)data)[0]+tblock->length;
}else{
data-=2;
outhere+=(word)(((word *)data)[0]+tblock->length);
}
if (follow(outhere)) madejump=true;
}break;
case ARG_RELIMM8: {
data=tblock->data+tblock->length-1;
outhere=tblock->addr;
if (tblock->mode32) {
if (data[0]&0x80) outhere+=(dword)(data[0]+0xffffff00+tblock->length);
else outhere+=(dword)(data[0]+tblock->length);
}else{
if (data[0]&0x80) outhere+=(word)(data[0]+0xff00+tblock->length);
else outhere+=(word)(data[0]+tblock->length);
}
if (follow(outhere)) madejump=true;
}break;
case ARG_MMXMODRM:
case ARG_XMMMODRM:
case ARG_MODRM_S:
case ARG_MODRMM512:
case ARG_MODRMQ:
case ARG_MODRM_SREAL:
case ARG_MODRM_PTR:
case ARG_MODRM_WORD:
case ARG_MODRM_SINT:
case ARG_MODRM_EREAL:
case ARG_MODRM_DREAL:
case ARG_MODRM_WINT:
case ARG_MODRM_LINT:
case ARG_MODRM_BCD:
case ARG_MODRM_FPTR:
case ARG_MODRM: {
data=tblock->data+tblock->modrm;
rm=(byte)((data[0]&0xc0)>>6);
modrm=(byte)(data[0]&0x07);
switch (rm) {
case 0: {
if (options.mode32) {
if (modrm==5) {
outhere.assign(tblock->addr.segm,((dword *)(&data[1]))[0]);
}else if (modrm==4) { // case 4=sib
sib=data[1];
if ((sib&0x07)==5) { // disp32
outhere.assign(tblock->addr.segm,((dword *)(&data[2]))[0]);
}
}
}else{
if (modrm==6) {
outhere.assign(tblock->addr.segm,((word *)(&data[1]))[0]);
}
}
}break;
case 1: break;
case 2: {
if (options.mode32) {
outhere.assign(tblock->addr.segm,((dword *)(&data[1]))[0]);
if (modrm==4) { // case 4=sib
outhere.assign(tblock->addr.segm,((dword *)(&data[2]))[0]);
}
}else{
outhere.assign(tblock->addr.segm,((word *)(&data[1]))[0]);
}
}break;
case 3: break;
}/*switch(rm)*/
if (follow(outhere)) madejump=true;
}break;
}/*switch(DSM_ITEM...)*/
}/*if(arg1)*/
if (!madejump) {
switch (DSMITEM_ARG2(tblock)) {
case ARG_IMM32: {
if (tblock->override!=over_dsoffset) break;
data=tblock->data+tblock->length;
data-=4;
outhere.assign(options.dseg,((dword *)(&data[0]))[0]);
follow(outhere);
}break;
case ARG_IMM: {
if (tblock->override!=over_dsoffset) break;
if (options.mode32) {
data=tblock->data+tblock->length;
data-=4;
outhere.assign(options.dseg,((dword *)(&data[0]))[0]);
follow(outhere);
}
}break;
case ARG_MEMLOC: {
data=tblock->data+tblock->length;
if (options.mode32) {
data-=4;
outhere.assign(tblock->addr.segm,((dword *)data)[0]);
}else{
data-=2;
outhere.assign(tblock->addr.segm,((word *)data)[0]);
}
follow(outhere);
}break;
case ARG_MMXMODRM:
case ARG_XMMMODRM:
case ARG_MODRM_S:
case ARG_MODRMM512:
case ARG_MODRMQ:
case ARG_MODRM_SREAL:
case ARG_MODRM_PTR:
case ARG_MODRM_WORD:
case ARG_MODRM_SINT:
case ARG_MODRM_EREAL:
case ARG_MODRM_DREAL:
case ARG_MODRM_WINT:
case ARG_MODRM_LINT:
case ARG_MODRM_BCD:
case ARG_MODRM_FPTR:
case ARG_MODRM: {
data=tblock->data+tblock->modrm;
rm=(byte)((data[0]&0xc0)>>6);
modrm=(byte)(data[0]&0x07);
switch (rm) {
case 0:
if(options.mode32)
{ if(modrm==5)
{ outhere.assign(tblock->addr.segm,((dword *)(&data[1]))[0]);
}
else if(modrm==4) // case 4=sib
{ sib=data[1];
if((sib&0x07)==5) // disp32
{ outhere.assign(tblock->addr.segm,((dword *)(&data[2]))[0]);
}
}
}
else
{ if(modrm==6)
{ outhere.assign(tblock->addr.segm,((word *)(&data[1]))[0]);
}
}
break;
case 1:
break;
case 2:
if(options.mode32)
{ outhere.assign(tblock->addr.segm,((dword *)(&data[1]))[0]);
if(modrm==4) // case 4=sib
{ outhere.assign(tblock->addr.segm,((dword *)(&data[2]))[0]);
}
}
else
{ outhere.assign(tblock->addr.segm,((word *)(&data[1]))[0]);
}
break;
case 3:
break;
}/*switch(rm)*/
follow(outhere);
}break;
}/*switch(DSMITEM...)*/
}
}
}
/************************************************************************
* findcurrentline *
* - this routine finds the current screen address and output line in *
* the disassembly database and from there works out the disassembly *
* item on the currently selected line. *
* - it is used by jumpto, when the user presses return to follow a jump *
* - comments added to the procedure, it is a useful one to follow and *
* see the strategy employed, which is a fairly common Borg strategy *
************************************************************************/
dsmitem *disio::findcurrentline(void) {
dsmitem titem,*tblock;
lptr outhere;
int i;
// strategy
// - use pointer to first item if available (so comments,etc included in list
// - otherwise use address.
titem.addr=curraddr;
titem.type=subitem;
// hunt for current addr and subitem
tblock=dsm->find(&titem);
if (tblock) tblock=dsm->nextiterator();
// on overlap - reset the curraddr.
// [on the spot error correction]
if (tblock) {
if(curraddr.between(tblock->addr,tblock->addr+tblock->length-1))
curraddr.offs=tblock->addr.offs;
}
// ensure we point to the right item, or the next one
if (tblock) {
if((tblock->addr<curraddr)||((tblock->addr==curraddr)&&(tblock->type<subitem)))
tblock=dsm->nextiterator();
}
// now at the top of the screen, the next loop moves down to the user selection line
outhere=curraddr;
for (i=0;i<sel;i++) {
if (tblock) {
if (outhere==tblock->addr) {
outhere+=tblock->length;
tblock=dsm->nextiterator();
}else outhere++;
}else outhere++;
// check if gone beyond seg, get next seg.
if (dta->beyondseg(outhere)) {
outhere.offs--;
dta->nextseg(&outhere);
}
if (!outhere.segm) break;
}
// now we either have the line we are pointing to, in the database
// or we have moved beyond the database and have a null
// or we have an address which would be a db
if (tblock && outhere!=tblock->addr) return NULL;
return tblock;
}
/************************************************************************
* findcurrentaddr *
* - this is very similar to findcurrentline, but it instead finds just *
* the location. the search strategy is the same *
************************************************************************/
void disio::findcurrentaddr(lptr *loc) {
dsmitem titem,*tblock;
lptr outhere;
int i;
// strategy
// - use pointer to first item if available (so comments,etc included in list
// - otherwise use address.
titem.addr=curraddr;
titem.type=subitem;
tblock=dsm->find(&titem);
if (tblock) tblock=dsm->nextiterator();
if (tblock && curraddr.between(tblock->addr,tblock->addr+tblock->length-1))
curraddr.offs=tblock->addr.offs;
if (tblock && tblock->addr<curraddr) tblock=dsm->nextiterator();
// added 2.25 - bugfix
// - wasnt finding correct lines when in mid-line......
if (tblock) {
while (tblock->addr==curraddr && tblock->type<subitem) {
tblock=dsm->nextiterator();
if (!tblock) break;
}
}
outhere=curraddr;
for (i=0;i<sel;i++) {
if (tblock && outhere==tblock->addr) {
outhere+=tblock->length;
tblock=dsm->nextiterator();
}else outhere++;
// check if gone beyond seg, get next seg.
if (dta->beyondseg(outhere)) {
outhere.offs--;
dta->nextseg(&outhere);
}
if (!outhere.segm) break;
}
if (outhere.segm) *loc=outhere;
else *loc=curraddr;
}
/************************************************************************
* findaddr *
* Ich verstehe diesen Quelltext nicht, aber hier versuche ich eine
* Zeile im Bildschirm zu finden, die die angegebene Adresse enthält *
************************************************************************/
int disio::findaddr(const lptr &loc) {
dsmitem titem,*tblock;
lptr outhere;
int i;
// strategy
// - use pointer to first item if available (so comments,etc included in list
// - otherwise use address.
titem.addr=curraddr;
titem.type=subitem;
tblock=dsm->find(&titem);
if (tblock) tblock=dsm->nextiterator();
if (tblock && curraddr.between(tblock->addr,tblock->addr+tblock->length-1))
curraddr.offs=tblock->addr.offs;
if (tblock && tblock->addr<curraddr) tblock=dsm->nextiterator();
// added 2.25 - bugfix
// - wasnt finding correct lines when in mid-line......
if (tblock) {
while (tblock->addr==curraddr && tblock->type<subitem) {
tblock=dsm->nextiterator();
if (!tblock) break;
}
}
outhere=curraddr;
for (i=0;i<size.y;i++) {
if (tblock && outhere==tblock->addr) {
outhere+=tblock->length;
tblock=dsm->nextiterator();
}else outhere++;
// check if gone beyond seg, get next seg.
if (dta->beyondseg(outhere)) {
outhere.offs--;
dta->nextseg(&outhere);
}
if (outhere==loc) return i+1; // weiß nicht warum das +1 ...
if (!outhere.segm) break;
}
return -1;
}
/************************************************************************
* savecuraddr *
* - this simply saves the window top line location to the return stack *
* - this is called when the user selects to jump somewhere (like to a *
* named location) rather than the 'jumpto' routine used to jump to a *
* location specified by a disassembly argument *
************************************************************************/
void disio::savecuraddr(void) {
if (retstack.stacktop==CALLSTACKSIZE) {
// if stack is full, move down its content (damn, no STL)
memmove(selstack,selstack+1,sizeof(selstack)-sizeof(selstack[0]));
}
retstack.push(curraddr);
selstack[retstack.stacktop-1]=sel;
}
// same as ^F in Turbo Debugger
bool disio::follow(const lptr &loc) {
if (!dta->findseg(loc)) return false;
savecuraddr();
int i=findaddr(loc);
if (i>=0) sel=i; // NICHT ROLLEN wenn im Bildschirm!!!
else setcuraddr(loc);
updatewindow();
return true;
}
/************************************************************************
* updatewindowifwithinrange *
* - adds a scheduler task for a window update if the current window *
* overlaps with the specified range *
************************************************************************/
void disio::updatewindowifwithinrange(lptr loc_start,lptr loc_end) {
if (loc_end>=curraddr && loc_start<=outend)
scheduler.addtask(windowupdate,priority_window,nlptr,NULL);
}
/************************************************************************
* updatewindowifinrange *
* - adds a scheduler task for a window update if the current window *
* contains the loc specified *
************************************************************************/
void disio::updatewindowifinrange(lptr loc) {
if (loc.between(curraddr,outend))
scheduler.addtask(windowupdate,priority_window,nlptr,NULL);
}
/************************************************************************
* updatewindow *
* - this function rewrites the buffers for the disassembly output to *
* the window, and then requests a screen refresh which will paint the *
* buffers into the window. The ClearBuff and DoneBuff functions *
* when the buffers are full and it is safe to refresh the screen with *
* a repaint *
************************************************************************/
// this functions job to output a window
// of disassembly to the buffer.
void disio::updatewindow(void) {
dsmitem titem,*tblock;
lptr outhere;
int i;
// find current position.
titem.addr=curraddr;
titem.type=subitem;
tblock=dsm->find(&titem);
if (tblock) tblock=dsm->nextiterator();
// now tblock= current position, or previous one.
// check if in middle of instruction
if (tblock) {
// bugfix 2.27
if (tblock->length>1
&& curraddr.between(tblock->addr,tblock->addr+tblock->length-1)) {
curraddr.offs=tblock->addr.offs;
subitem=tblock->type;
}
}
// check if previous one. get next
if (tblock) {
if (tblock->addr<curraddr
|| tblock->addr==curraddr && tblock->type<subitem)
tblock=dsm->nextiterator();
}
// tblock is now top of the page.
outhere=curraddr;
ClearBuff(); // start again
for (i=0; i<size.y;i++) {
if (tblock) {
if (outhere==tblock->addr) {
switch (tblock->type) {
case dsmcode: {
outinst(tblock,true);
}break;
case dsmnameloc: {
printlineheader(tblock->addr,true);
LastPrintBuff("%s:",tblock->data);
}break;
case dsmxref: {
printlineheader(tblock->addr,true);
LastPrintBuff(";");
LastPrintBuffEpos(COMMENTPOS);
LastPrintBuff("XREFS First: ");
xrefs->printfirst(tblock->addr);
}break;
default: {
printlineheader(tblock->addr,true);
outcomment(tblock);
}
}
outhere+=tblock->length;
tblock=dsm->nextiterator();
}else{
outdb(&outhere,true);
outhere++;
}
}else{
outdb(&outhere,true);
outhere++;
}
// check if gone beyond seg, get next seg.
if (dta->beyondseg(outhere)) {
outhere.offs--;
dta->nextseg(&outhere);
}
if (!outhere.segm) break;
else outend=outhere;
}
DoneBuff(); // mark as done
InvalidateRect(wnd,NULL,true);
}
/************************************************************************
* scroller *
* - this routine controls simple vertical scrolls. A vertical scroll is *
* a movement of the currently selected line. Only if this line moves *
* beyond the boundaries of the window do we need to move the windowed *
* disassembly output itself. Simple moves are handled quickly, and if *
* we need to regenerate the buffers then we first recalculate the top *
* position and then we call windowupdate to handle the rest. *
************************************************************************/
void disio::scroller(int amount) {
dsmitem titem,*tblock;
int newpos=sel+amount;
// simple move bar on screen
if ((unsigned)newpos<(unsigned)(size.y-1)) {
setpos(newpos);
return;
}
// find top of page
titem.addr=curraddr;
titem.type=subitem;
tblock=dsm->find(&titem);
// tblock is now top of page or previous item.
// if moving up find previous inst
if ((unsigned)amount<100 && tblock) tblock=dsm->nextiterator();
if ((unsigned)amount>100 && tblock
&& tblock->addr==titem.addr && tblock->type==subitem)
tblock=dsm->lastiterator();
// move up - tblock=previous inst.
// if moving down, check if tblock=previous item.
if (tblock && (unsigned)amount<100) {
if (tblock->addr<curraddr
|| tblock->addr==curraddr && tblock->type<subitem)
tblock=dsm->nextiterator();
}
// moving down - tblock=current top.
if ((unsigned)amount<100) while (amount) {
if (sel<=size.y-3) sel++;
else{
if (tblock) {
if (curraddr==tblock->addr) {
curraddr+=tblock->length;
tblock=dsm->nextiterator();
if (tblock && curraddr==tblock->addr) subitem=tblock->type;
else subitem=dsmcode;
}else{
subitem=dsmnull;
curraddr++;
}
}else{
subitem=dsmnull;
curraddr++;
}
// check if gone beyond seg, get next seg.
if (dta->beyondseg(curraddr)) {
curraddr.offs--;
dta->nextseg(&curraddr);
subitem=dsmnull;
}
if (!curraddr.segm) break;
titem.addr=curraddr;
}
amount--;
}else{
while (amount) {
if (sel) sel--;
else{
if (tblock) {
if (curraddr==tblock->addr+tblock->length) {
curraddr.offs-=tblock->length;
subitem=tblock->type;
tblock=dsm->lastiterator();
}else{
subitem=dsmcode;
curraddr.offs--;
}
}else{
subitem=dsmnull;
curraddr.offs--;
}
// check if gone beyond seg, get previous seg.
if (dta->beyondseg(curraddr)) {
curraddr++;
dta->lastseg(&curraddr);
}
if (!curraddr.segm) break;
titem.addr=curraddr;
}
amount++;
}
}
if (!curraddr.segm) curraddr=titem.addr;
updatewindow();
setscrollpos(curraddr);
// current_data_pos=dta->datagetpos();
// sbarpos=((float)current_data_pos)/((float)total_data_size+(float)1.0)*(float)VERTSCROLLRANGE;
// SetScrollPos(MainWnd,SB_VERT,(int)sbarpos,true);
}
BOOL PrintFoundName(lptr loc) {
if (name->isname(loc)) name->printname(loc);
else if (import->isname(loc)) import->printname(loc);
else if(expt->isname(loc)) expt->printname(loc);
else return FALSE;
return TRUE;
}
void PrintLongHex(lptr loc) {
if (!PrintFoundName(loc)) cvd->LastPrintBuffLongHexValue(loc.offs);
}
void PrintOffset(lptr loc) {
cvd->LastPrintBuff("offset ");
PrintLongHex(loc);
}
void PrintMemVar(lptr loc) {
cvd->LastPrintBuff("[");
PrintLongHex(loc);
cvd->LastPrintBuff("]");
}
/************************************************************************
* outargs *
* - this is a very long routine which handles every kind of argument *
* that we have set up in the processor tables. It outputs the ascii *
* form of the instructions arguments to the buffer. It handles *
* complex modrm and sib encodings, the display of names and locations *
* which must be decoded, etc. *
************************************************************************/
void disio::outargs(dsmitem *inst,argtype a) {
byte *dta,modrm,sib;
// rm extended to word. build 15. re M Ogden and VC++ warnings.
word rm;
argtype a1,a2;
dword targetd;
dword targetw;
lptr loc;
char fbuff[40];
int i,sp; // sp= string printed
byte pbyte; // prefix byte.
int prefixptr;
if(inst->flags&FLAGS_SEGPREFIX) {
prefixptr=0;
while (!issegprefix(inst->data[prefixptr]) && prefixptr<15)
prefixptr++;
pbyte=inst->data[prefixptr];
}
if (inst->flags&FLAGS_ADDRPREFIX) options.mode32=!options.mode32;
switch (a) {
case ARG_REG_AX: {
if (inst->mode32) LastPrintBuff("eax");
else LastPrintBuff("ax");
}break;
case ARG_REG_BX: {
if (inst->mode32) LastPrintBuff("ebx");
else LastPrintBuff("bx");
}break;
case ARG_REG_CX: {
if (inst->mode32) LastPrintBuff("ecx");
else LastPrintBuff("cx");
}break;
case ARG_REG_DX: {
if(inst->mode32) LastPrintBuff("edx");
else LastPrintBuff("dx");
}break;
case ARG_16REG_DX: LastPrintBuff("dx"); break;
case ARG_REG_SP: {
if (inst->mode32) LastPrintBuff("esp");
else LastPrintBuff("sp");
}break;
case ARG_REG_BP: {
if (inst->mode32) LastPrintBuff("ebp");
else LastPrintBuff("bp");
}break;
case ARG_REG_SI: {
if (inst->mode32) LastPrintBuff("esi");
else LastPrintBuff("si");
}break;
case ARG_REG_DI: {
if (inst->mode32) LastPrintBuff("edi");
else LastPrintBuff("di");
}break;
case ARG_REG_AL: LastPrintBuff("al"); break;
case ARG_REG_AH: LastPrintBuff("ah"); break;
case ARG_REG_BL: LastPrintBuff("bl"); break;
case ARG_REG_BH: LastPrintBuff("bh"); break;
case ARG_REG_CL: LastPrintBuff("cl"); break;
case ARG_REG_CH: LastPrintBuff("ch"); break;
case ARG_REG_DL: LastPrintBuff("dl"); break;
case ARG_REG_DH: LastPrintBuff("dh"); break;
case ARG_REG_ST0: LastPrintBuff("st(0)"); break;
case ARG_REG_ES: LastPrintBuff("es"); break;
case ARG_REG_CS: LastPrintBuff("cs"); break;
case ARG_REG_DS: LastPrintBuff("ds"); break;
case ARG_REG_SS: LastPrintBuff("ss"); break;
case ARG_REG_FS: LastPrintBuff("fs"); break;
case ARG_REG_GS: LastPrintBuff("gs"); break;
case ARG_REG_A: LastPrintBuff("a"); break;
case ARG_REG_B: LastPrintBuff("b"); break;
case ARG_REG_C: LastPrintBuff("c"); break;
case ARG_REG_D: LastPrintBuff("d"); break;
case ARG_REG_E: LastPrintBuff("e"); break;
case ARG_REG_H: LastPrintBuff("h"); break;
case ARG_REG_L: LastPrintBuff("l"); break;
case ARG_REG_I: LastPrintBuff("i"); break;
case ARG_REG_R: LastPrintBuff("r"); break;
case ARG_REG_HL_IND: LastPrintBuff("(hl)"); break;
case ARG_REG_BC: LastPrintBuff("bc"); break;
case ARG_REG_DE: LastPrintBuff("de"); break;
case ARG_REG_HL: LastPrintBuff("hl"); break;
case ARG_REG_BC_IND: LastPrintBuff("(bc)"); break;
case ARG_REG_DE_IND: LastPrintBuff("(de)"); break;
case ARG_REG_SP_IND: LastPrintBuff("(sp)"); break;
case ARG_REG_IX: LastPrintBuff("ix"); break;
case ARG_REG_IX_IND: {
LastPrintBuff("(ix");
if (inst->flags&FLAGS_INDEXREG) {
dta=inst->data+2;
LastPrintBuff("+");
LastPrintBuffLongHexValue((word)(dta[0]));
}LastPrintBuff(")");
}break;
case ARG_REG_IY: LastPrintBuff("iy"); break;
case ARG_REG_IY_IND: {
LastPrintBuff("(iy");
if (inst->flags&FLAGS_INDEXREG) {
dta=inst->data+2;
LastPrintBuff("+");
LastPrintBuffLongHexValue((word)(dta[0]));
}
LastPrintBuff(")");
}break;
case ARG_REG_C_IND:LastPrintBuff("(c)"); break;
case ARG_REG_AF: LastPrintBuff("af"); break;
case ARG_REG_AF2: LastPrintBuff("af'"); break;
case ARG_IMM: {
dta=inst->data+inst->length;
if (inst->mode32) {
dta-=4;
switch (inst->override) {
case over_decimal: {
if (inst->displayflags&DISPFLAG_NEGATE) LastPrintBuff("-%02lu",0-*(dword *)dta);
else LastPrintBuff("%02lu",*(dword *)dta);
}break;
case over_char: {
LastPrintBuff("'");
for (i=3;i>=0;i--) if (dta[i]) LastPrintBuff("%c",dta[i]);
LastPrintBuff("'");
}break;
case over_dsoffset: {
loc.assign(inst->addr.segm,*(dword *)dta);
PrintOffset(loc);
}break;
case over_single: {
sprintf(fbuff,"(float)%g",*(float *)dta);
LastPrintBuff(fbuff);
}break;
default: {
if (inst->displayflags&DISPFLAG_NEGATE) {
LastPrintBuff("-");
LastPrintBuffLongHexValue(0-*(dword *)dta);
}else LastPrintBuffLongHexValue(*(dword *)dta);
}break;
}/*switch*/
}else{ dta-=2;
if (inst->override==over_decimal) {
if (inst->displayflags&DISPFLAG_NEGATE)
LastPrintBuff("-%02lu",0x10000-((word *)dta)[0]);
else LastPrintBuff("%02lu",((word *)dta)[0]);
}else if(inst->override==over_char) {
LastPrintBuff("\"");
for (i=1;i>=0;i--) if (dta[i]) LastPrintBuff("%c",dta[i]);
LastPrintBuff("\"");
}else{
if (inst->displayflags&DISPFLAG_NEGATE) {
LastPrintBuff("-");
LastPrintBuffLongHexValue(0x10000-((word *)dta)[0]);
}else LastPrintBuffLongHexValue(((word *)dta)[0]);
}
}
}break;
case ARG_IMM_SINGLE:
dta=inst->data+inst->length-4;
sprintf(fbuff,"%g",*(float *)dta);
LastPrintBuff(fbuff);
break;
case ARG_IMM_DOUBLE:
dta=inst->data+inst->length-8;
sprintf(fbuff,"%g",*(double *)dta);
LastPrintBuff(fbuff);
break;
case ARG_IMM_LONGDOUBLE:
dta=inst->data+inst->length-10;
sprintf(fbuff,"%Lg",*(long double *)dta);
LastPrintBuff(fbuff);
break;
case ARG_IMM32: {
dta=inst->data+inst->length-4;
switch (inst->override) {
case over_decimal:
if (inst->displayflags&DISPFLAG_NEGATE) LastPrintBuff("-%02lu",0-((dword *)dta)[0]);
else LastPrintBuff( "%02lu",((dword *)dta)[0]);
break;
case over_char:
LastPrintBuff("\'");
for(i=3;i>=0;i--) if(dta[i]) LastPrintBuff("%c",dta[i]);
LastPrintBuff("\'");
break;
case over_dsoffset:
loc.assign(inst->addr.segm,*(dword *)dta);
PrintOffset(loc);
break;
case over_single:
sprintf(fbuff,"(float)%g",*(float *)dta);
LastPrintBuff(fbuff);
break;
default:
if (inst->displayflags&DISPFLAG_NEGATE) {
LastPrintBuff("-");
LastPrintBuffLongHexValue(0-((dword *)dta)[0]);
}else LastPrintBuffLongHexValue(((dword *)dta)[0]);
break;
}/*switch*/
}break;
case ARG_STRING: {
rm=0;
LastPrintBuff("\"");
sp=0;
while (inst->data[rm]) {
if (inst->data[rm]<32) {
LastPrintBuff("\",");
LastPrintBuffHexValue(inst->data[rm]);
LastPrintBuff(",\"");
}else LastPrintBuff("%c",inst->data[rm]);
rm++;
sp++;
if (sp>MAX_STRINGPRINT) break;
}
LastPrintBuff("\",00h");
}break;
case ARG_PSTRING: {
dta=inst->data;
rm=dta[0];
dta++;
LastPrintBuffHexValue((byte)rm);
LastPrintBuff(",\"");
sp=0;
while (rm) {
if (dta[0]<32) {
LastPrintBuff("\",");
LastPrintBuffHexValue(*dta);
LastPrintBuff(",\"");
}else LastPrintBuff("%c",*dta);
dta++;
rm--;
sp++;
if (sp>MAX_STRINGPRINT) break;
}
LastPrintBuff("\"");
}break;
case ARG_DOSSTRING: {
dta=inst->data;
rm=inst->length;
rm--;
LastPrintBuff("\"");
sp=0;
while (rm) {
if (dta[0]<32) {
LastPrintBuff("\",");
LastPrintBuffHexValue(dta[0]);
LastPrintBuff(",\"");
}else LastPrintBuff("%c",dta[0]);
dta++;
rm--;
sp++;
if (sp>MAX_STRINGPRINT) break;
}
LastPrintBuff("\"");
}break;
case ARG_CUNICODESTRING: // missing DW instead DB (?)
dta=inst->data;
rm=inst->length;
rm-=(byte)2;
LastPrintBuff("\"");
sp=0;
while (rm) {
if (dta[0]<32) {
LastPrintBuff("\",");
LastPrintBuffHexValue(dta[0]);
LastPrintBuff(",\"");
}else LastPrintBuff("%c",dta[0]);
dta+=2;
rm-=(byte)2;
sp++;
if (sp>MAX_STRINGPRINT) break;
}
LastPrintBuff("\"");
break;
case ARG_PUNICODESTRING:
dta=inst->data+2;
rm=inst->length;
rm-=(byte)2;
sp=0;
LastPrintBuffHexValue((byte)(rm/2));
LastPrintBuff(",\"");
while (rm) {
if (dta[0]<32) {
LastPrintBuff("\",");
LastPrintBuffHexValue(dta[0]);
LastPrintBuff(",\"");
}else LastPrintBuff("%c",dta[0]);
dta+=2;
rm-=(byte)2;
sp++;
if (sp>MAX_STRINGPRINT) break;
}
LastPrintBuff("\"");
break;
case ARG_MEMLOC:
if (inst->flags&FLAGS_SEGPREFIX) outprefix(pbyte);
dta=inst->data+inst->length;
if (options.mode32) {
dta-=4;
loc.assign(inst->addr.segm,*(dword *)dta);
if (inst->flags&FLAGS_8BIT) LastPrintBuff("byte ptr");
else if (inst->flags&FLAGS_ADDRPREFIX) LastPrintBuff("word ptr");
else LastPrintBuff("dword ptr");
PrintMemVar(loc);
}else{
dta-=2;
loc.assign(inst->addr.segm,((word *)dta)[0]);
if (inst->flags&FLAGS_8BIT) LastPrintBuff("byte ptr");
if (inst->flags&FLAGS_ADDRPREFIX) LastPrintBuff("dword ptr");
else LastPrintBuff("word ptr");
PrintMemVar(loc);
}
break;
case ARG_MEMLOC16:
if (inst->flags&FLAGS_SEGPREFIX) outprefix(pbyte);
dta=inst->data+inst->length-2;
if (options.processor==PROC_Z80) {
loc.assign(inst->addr.segm,*(dword *)dta);
PrintMemVar(loc);
}else{
loc.assign(inst->addr.segm,*(word *)dta);
PrintMemVar(loc);
}
break;
case ARG_SIMM8:
dta=inst->data+inst->length-1;
if (inst->override==over_char) {
LastPrintBuff("\"");
for(i=0;i>=0;i--) if(dta[i]) LastPrintBuff("%c",dta[i]);
LastPrintBuff("\"");
}else if (dta[0]&0x80) {
if (inst->override==over_decimal) LastPrintBuff("%02lu",(word)(0x100-dta[0]));
else{
LastPrintBuff("-");
LastPrintBuffLongHexValue((word)(0x100-dta[0]));
}
}else{
if (inst->override==over_decimal) LastPrintBuff("%02lu",(word)(dta[0]));
else LastPrintBuffLongHexValue((word)(dta[0]));
}
break;
case ARG_IMM8:
dta=inst->data+inst->length-1;
if(inst->override==over_decimal)
{ if(inst->displayflags&DISPFLAG_NEGATE)
LastPrintBuff("-%02lu",0x100-(word)(dta[0]));
else
LastPrintBuff("%02lu",(word)(dta[0]));
}
else if(inst->override==over_char)
{ LastPrintBuff("\"");
for(i=0;i>=0;i--)
if(dta[i])
LastPrintBuff("%c",dta[i]);
LastPrintBuff("\"");
}
else
{ if(inst->displayflags&DISPFLAG_NEGATE)
{ LastPrintBuff("-");
LastPrintBuffLongHexValue(0x100-(word)(dta[0]));
}
else
LastPrintBuffLongHexValue((word)(dta[0]));
}
break;
case ARG_IMM8_IND:
dta=inst->data+inst->length-1;
LastPrintBuff("(");
LastPrintBuffLongHexValue((word)(dta[0]));
LastPrintBuff(")");
break;
case ARG_IMM16:
dta=inst->data+inst->length-2;
if(inst->override==over_decimal)
{ if(inst->displayflags&DISPFLAG_NEGATE)
LastPrintBuff("-%02lu",0x10000-((word *)dta)[0]);
else
LastPrintBuff("%02lu",((word *)dta)[0]);
}
else if(inst->override==over_char)
{ LastPrintBuff("\"");
for(i=1;i>=0;i--)
if(dta[i])
LastPrintBuff("%c",dta[i]);
LastPrintBuff("\"");
}
else
{ if(inst->displayflags&DISPFLAG_NEGATE)
{ LastPrintBuff("-");
LastPrintBuffLongHexValue(0x10000-((word *)dta)[0]);
}
else
LastPrintBuffLongHexValue(((word *)dta)[0]);
}
break;
case ARG_IMM16_A:
dta=inst->data+inst->length-3;
LastPrintBuffLongHexValue(((word *)dta)[0]);
break;
case ARG_RELIMM8:
dta=inst->data+inst->length-1;
if(inst->mode32) {
targetd=(dword)((signed char)dta[0]+inst->addr.offs+inst->length);
loc.assign(inst->addr.segm,targetd);
PrintLongHex(loc);
}else{
targetw=(word)((signed char)dta[0]+inst->addr.offs+inst->length);
loc.assign(inst->addr.segm,targetw);
PrintLongHex(loc);
}
break;
case ARG_RELIMM:
dta=inst->data+inst->length;
if(inst->mode32)
{ dta-=4;
targetd=((dword *)dta)[0]+inst->addr.offs+inst->length;
loc.assign(inst->addr.segm,targetd);
PrintLongHex(loc);
}
else
{ dta-=2;
targetw=(word)(((word *)dta)[0]+inst->addr.offs+inst->length);
loc.assign(inst->addr.segm,targetw);
PrintLongHex(loc);
}
break;
case ARG_REG:
dta=inst->data+inst->modrm;
if(options.processor==PROC_Z80)
LastPrintBuff(regzascii[dta[0]&0x07]);
else if(((asminstdata *)(inst->tptr))->flags&FLAGS_8BIT)
LastPrintBuff(reg8ascii[(dta[0]>>3)&0x07]);
else if(inst->mode32)
LastPrintBuff(reg32ascii[(dta[0]>>3)&0x07]);
else
LastPrintBuff(reg16ascii[(dta[0]>>3)&0x07]);
break;
case ARG_MREG:
dta=inst->data+inst->modrm;
LastPrintBuff(regmascii[(dta[0]>>3)&0x07]);
break;
case ARG_XREG:
dta=inst->data+inst->modrm;
LastPrintBuff(regxascii[(dta[0]>>3)&0x07]);
break;
case ARG_FREG:
dta=inst->data+inst->modrm;
LastPrintBuff(regfascii[dta[0]&0x07]);
break;
case ARG_SREG:
dta=inst->data+inst->modrm;
LastPrintBuff(regsascii[(dta[0]>>3)&0x07]);
break;
case ARG_CREG:
dta=inst->data+inst->modrm;
LastPrintBuff(regcascii[(dta[0]>>3)&0x07]);
break;
case ARG_DREG:
dta=inst->data+inst->modrm;
LastPrintBuff(regdascii[(dta[0]>>3)&0x07]);
break;
case ARG_TREG:
case ARG_TREG_67:
dta=inst->data+inst->modrm;
LastPrintBuff(regtascii[(dta[0]>>3)&0x07]);
break;
case ARG_MODREG:
case ARG_MMXMODRM:
case ARG_XMMMODRM:
case ARG_MODRM8:
case ARG_MODRM16:
case ARG_MODRM_S:
case ARG_MODRMM512:
case ARG_MODRMQ:
case ARG_MODRM_SREAL:
case ARG_MODRM_PTR:
case ARG_MODRM_WORD:
case ARG_MODRM_BCD:
case ARG_MODRM_SINT:
case ARG_MODRM_EREAL:
case ARG_MODRM_DREAL:
case ARG_MODRM_WINT:
case ARG_MODRM_LINT:
case ARG_MODRM_FPTR:
case ARG_MODRM: {
dta=inst->data+inst->modrm;
rm=(byte)((dta[0]&0xc0)>>6);
modrm=(byte)(dta[0]&0x07);
a1=DSMITEM_ARG1(inst);
a2=DSMITEM_ARG2(inst);
sib=dta[1];
if (a1==ARG_IMM || a2==ARG_IMM || a1==ARG_IMM8 || a2==ARG_IMM8 || a2==ARG_NONE
||a1==ARG_SIMM8 || a2==ARG_SIMM8 || modrm==5 && rm==0
|| modrm==4 && rm==2 && sib&0x07==5
|| modrm==4 && rm==0 && sib&0x07==5) {
if (rm<3) {
switch (a) {
case ARG_MODRM8: LastPrintBuff("byte ptr "); break;
case ARG_MODRM16:
case ARG_MODRM_WORD: LastPrintBuff("word ptr "); break;
case ARG_MMXMODRM:
case ARG_XMMMODRM: LastPrintBuff("dword ptr "); break;
case ARG_MODRMQ: LastPrintBuff("qword ptr "); break;
case ARG_MODRM_S: LastPrintBuff("fword ptr "); break; // 6 bytes=fword
case ARG_MODRM_SREAL: LastPrintBuff("dword ptr "); break; // single real=4 bytes=dword
case ARG_MODRM_BCD: LastPrintBuff("tbyte ptr "); break; // packed bcd=10 bytes=tbyte
case ARG_MODRM_SINT: LastPrintBuff("dword ptr "); break; // short int=4 bytes
case ARG_MODRM_WINT: LastPrintBuff("word ptr "); break; // word int =2 bytes
case ARG_MODRM_LINT: LastPrintBuff("qword ptr "); break; // long int = 8 bytes
case ARG_MODRMM512: LastPrintBuff("byte ptr "); break; // points to 512 bits=64 bytes of memory......
case ARG_MODRM_EREAL: LastPrintBuff("tbyte ptr "); break; // extended real=10 bytes
case ARG_MODRM_DREAL: LastPrintBuff("qword ptr "); break; // double real=8 bytes
case ARG_MODRM:
if (inst->flags&FLAGS_8BIT) LastPrintBuff("byte ptr ");
else if (inst->mode32) LastPrintBuff("dword ptr ");
else LastPrintBuff("word ptr ");
break;
}/*switch(a)*/
}
}else if (a1==ARG_REG || a2==ARG_REG) {
if (rm<3) {
switch (a) { // re movzx, movsx type instructions
case ARG_MODRM8: LastPrintBuff("byte ptr "); break;
case ARG_MODRM16: LastPrintBuff("word ptr "); break;
}/*switch(a)*/
}
}
switch (rm) {
case 0:
if(inst->flags&FLAGS_SEGPREFIX)
outprefix(pbyte);
if(options.mode32)
{ if(modrm==5)
{ loc.assign(inst->addr.segm,((dword *)(&dta[1]))[0]);
PrintMemVar(loc);
}
else if(modrm==4) // case 4=sib
{ sib=dta[1];
if((sib&0x07)==5) // disp32
{ loc.assign(inst->addr.segm,((dword *)(&dta[2]))[0]);
PrintMemVar(loc);
}
else
{ LastPrintBuff("[%s]",reg32ascii[sib&0x07]);
}
if(((sib>>3)&0x07)==4) // no scaled index reg
{
}
else
{ LastPrintBuff("[%s",reg32ascii[(sib>>3)&0x07]);
switch(sib>>6)
{ case 0:
LastPrintBuff("]");
break;
case 1:
LastPrintBuff("*2]");
break;
case 2:
LastPrintBuff("*4]");
break;
case 3:
LastPrintBuff("*8]");
break;
}
}
}
else
LastPrintBuff("[%s]",reg32ascii[dta[0]&0x07]);
}
else
{ if(modrm==6)
{ loc.assign(inst->addr.segm,((word *)(&dta[1]))[0]);
PrintMemVar(loc);
}
else
LastPrintBuff("[%s]",regind16ascii[dta[0]&0x07]);
}
break;
case 1:
if(inst->flags&FLAGS_SEGPREFIX)
outprefix(pbyte);
if(options.mode32)
{ if(modrm==4) // case 4=sib
{ sib=dta[1];
if(dta[2]&0x80)
{ LastPrintBuff("[%s-",reg32ascii[dta[1]&0x07]);
LastPrintBuffHexValue((byte)(-dta[2]));
}
else
{ LastPrintBuff("[%s+",reg32ascii[dta[1]&0x07]);
LastPrintBuffHexValue(dta[2]);
}
if(((sib>>3)&0x07)==4) // no scaled index reg
LastPrintBuff("]");
else
{ LastPrintBuff("][%s",reg32ascii[(sib>>3)&0x07]);
switch(sib>>6)
{ case 0:
LastPrintBuff("]");
break;
case 1:
LastPrintBuff("*2]");
break;
case 2:
LastPrintBuff("*4]");
break;
case 3:
LastPrintBuff("*8]");
break;
}
}
}
else if(dta[1]&0x80)
{ LastPrintBuff("[%s-",reg32ascii[dta[0]&0x07]);
LastPrintBuffHexValue((byte)(-dta[1]));
LastPrintBuff("]");
}
else
{ LastPrintBuff("[%s+",reg32ascii[dta[0]&0x07]);
LastPrintBuffHexValue(dta[1]);
LastPrintBuff("]");
}
}
else
{ if(dta[1]&0x80)
{ LastPrintBuff("[%s-",regind16ascii[dta[0]&0x07]);
LastPrintBuffHexValue((byte)(-dta[1]));
LastPrintBuff("]");
}
else
{ LastPrintBuff("[%s+",regind16ascii[dta[0]&0x07]);
LastPrintBuffHexValue(dta[1]);
LastPrintBuff("]");
}
}
break;
case 2:
if (inst->flags&FLAGS_SEGPREFIX) outprefix(pbyte);
if (options.mode32) {
loc.assign(inst->addr.segm,((dword *)(&dta[1]))[0]);
if (modrm==4) { // case 4=sib
sib=dta[1];
loc.assign(inst->addr.segm,((dword *)(&dta[2]))[0]);
LastPrintBuff("[");
if (name->isname(loc)) {
LastPrintBuff("%s+",reg32ascii[sib&0x07]);
name->printname(loc);
}else if (import->isname(loc)) {
LastPrintBuff("%s+",reg32ascii[sib&0x07]);
import->printname(loc);
}else if(expt->isname(loc)) {
LastPrintBuff("%s+",reg32ascii[sib&0x07]);
expt->printname(loc);
}else if(dta[5]&0x80) {
LastPrintBuff("%s-",reg32ascii[sib&0x07]);
LastPrintBuffLongHexValue(0-((dword *)(&dta[2]))[0]);
}else{
LastPrintBuff("%s+",reg32ascii[sib&0x07]);
LastPrintBuffLongHexValue(((dword *)(&dta[2]))[0]);
}
if (((sib>>3)&0x07)==4) // no scaled index reg
LastPrintBuff("]");
else{
LastPrintBuff("][%s",reg32ascii[(sib>>3)&0x07]);
switch (sib>>6) {
case 0: LastPrintBuff("]"); break;
case 1: LastPrintBuff("*2]"); break;
case 2: LastPrintBuff("*4]"); break;
case 3: LastPrintBuff("*8]"); break;
}
}
}else if (name->isname(loc)) {
name->printname(loc);
LastPrintBuff("[%s]",reg32ascii[dta[0]&0x07]);
}else if (import->isname(loc)) {
import->printname(loc);
LastPrintBuff("[%s]",reg32ascii[dta[0]&0x07]);
}else if (expt->isname(loc)) {
expt->printname(loc);
LastPrintBuff("[%s]",reg32ascii[dta[0]&0x07]);
}else if (dta[4]&0x80) {
LastPrintBuff("[%s-",reg32ascii[dta[0]&0x07]);
LastPrintBuffLongHexValue(0-*(dword*)(dta+1));
LastPrintBuff("]");
}else{
LastPrintBuff("[%s+",reg32ascii[dta[0]&0x07]);
LastPrintBuffLongHexValue(*(dword*)(dta+1));
LastPrintBuff("]");
}
}else{
loc.assign(inst->addr.segm,((word *)(&dta[1]))[0]);
if (name->isname(loc)) {
name->printname(loc);
LastPrintBuff("[%s]",regind16ascii[*dta&0x07]);
}else if (import->isname(loc)) {
import->printname(loc);
LastPrintBuff("[%s]",regind16ascii[*dta&0x07]);
}else if (expt->isname(loc)) {
expt->printname(loc);
LastPrintBuff("[%s]",regind16ascii[*dta&0x07]);
}else if (dta[2]&0x80) {
LastPrintBuff("[%s-",regind16ascii[*dta&0x07]);
LastPrintBuffLongHexValue(0x10000-((word *)(&dta[1]))[0]);
LastPrintBuff("]");
}else{
LastPrintBuff("[%s+",regind16ascii[dta[0]&0x07]);
LastPrintBuffLongHexValue(((word *)(&dta[1]))[0]);
LastPrintBuff("]");
}
}
break;
case 3:
if (a==ARG_MMXMODRM) LastPrintBuff(regmascii[dta[0]&0x07]);
else if(a==ARG_XMMMODRM)
LastPrintBuff(regxascii[dta[0]&0x07]);
else if((((asminstdata *)(inst->tptr))->flags&FLAGS_8BIT)||(a==ARG_MODRM8))
LastPrintBuff(reg8ascii[dta[0]&0x07]);
else if((inst->mode32)&&(a!=ARG_MODRM16))
LastPrintBuff(reg32ascii[dta[0]&0x07]);
else LastPrintBuff(reg16ascii[dta[0]&0x07]);
}/*switch(rm)*/
}break;
case ARG_IMM_1:
if(inst->override==over_decimal)
LastPrintBuff("1");
else
LastPrintBuff("1h");
break;
case ARG_FADDR:
dta=inst->data+inst->length;
if(options.mode32)
{ dta-=6;
loc.assign(((word *)(&dta[4]))[0],((dword *)(&dta[0]))[0]);
if (!PrintFoundName(loc)) LastPrintBuff("%04x:%08lxh",loc.segm,loc.offs);
}
else
{ dta-=4;
loc.assign(((word *)(&dta[2]))[0],((word *)(&dta[0]))[0]);
if (!PrintFoundName(loc)) LastPrintBuff("%04x:%04xh",loc.segm,loc.offs);
}
break;
case ARG_BIT:
dta=inst->data+inst->length-1;
LastPrintBuff("%x",(dta[0]>>3)&7);
break;
case ARG_NONE:
if(inst->flags&FLAGS_SEGPREFIX)
outprefix(pbyte);
break;
case ARG_NONEBYTE: break;
}
if (inst->flags&FLAGS_ADDRPREFIX)
options.mode32=!options.mode32;
}
/************************************************************************
* outcomment *
* - prints a disassembly comment to the buffer *
************************************************************************/
void disio::outcomment(dsmitem *inst) {
LastPrintBuff(";%s",inst->tptr);
}
/************************************************************************
* dumpblocktofile *
* - this is the text and asm output routine. It needs a lot more work *
* doing to it and is presently a fairly simple dump of a block of *
* code. *
* - this routine was a quick hack and complete rip of the dumptofile *
* routine which follows. the two routines need the common workings *
* put together and both need rewriting *
************************************************************************/
void disio::dumpblocktofile(char *fname,bool printaddrs) {
HANDLE efile;
dword num;
dsmitem *tblock,fdsm;
dsegitem *dblock,*nxtblock;
lptr outhere,nptr;
int i;
char ehdr[300];
if (!blk.checkblock()) return;
efile=CreateFile(fname,GENERIC_WRITE,0,NULL,CREATE_NEW,0,NULL);
if(efile==INVALID_HANDLE_VALUE) {
MessageBox(MainWnd,"File Creation Failed","Borg Disassembler Alert",MB_OK);
return;
}
// scheduler.stopthread();
WriteFile(efile,"; ",2,&num,NULL);
WriteFile(efile,winname,lstrlen(winname),&num,NULL);
WriteFile(efile,"\r\n;\r\n",5,&num,NULL);
WriteFile(efile,hdr,lstrlen(hdr),&num,NULL);
WriteFile(efile,hdr2,lstrlen(hdr2),&num,NULL);
WriteFile(efile,";\r\n",3,&num,NULL);
wsprintf(ehdr,"; block dump from: %04x:%08lxh to %04x:%08lxh",blk.top.segm,blk.top.offs,blk.bottom.segm,blk.bottom.offs);
WriteFile(efile,ehdr,lstrlen(ehdr),&num,NULL);
WriteFile(efile,"\r\n",2,&num,NULL);
WriteFile(efile,"\r\n",2,&num,NULL);
// find current position.
fdsm.addr=blk.top;
fdsm.type=dsmnull;
tblock=dsm->find(&fdsm);
while (tblock) {
if (tblock->addr<blk.top) tblock=dsm->nextiterator();
else break;
}
// now tblock= first position
dblock=dta->findseg(blk.top);
outhere=blk.top;
while (dblock && (outhere<=blk.bottom)) {
ClearBuff(); // clear buffer - ready to start
for (i=0;i<size.y;i++) {
if (tblock) {
if(outhere==tblock->addr) {
switch(tblock->type) {
case dsmcode:
outinst(tblock,printaddrs);
break;
case dsmnameloc:
printlineheader(tblock->addr,printaddrs);
LastPrintBuff("%s:",tblock->data);
break;
case dsmxref:
// temp measure - print first (build 17)
printlineheader(tblock->addr,printaddrs);
LastPrintBuff(";");
LastPrintBuffEpos(COMMENTPOS);
LastPrintBuff("XREFS First: ");
xrefs->printfirst(tblock->addr);
break;
default:
printlineheader(tblock->addr,printaddrs);
outcomment(tblock);
}
outhere+=tblock->length;
tblock=dsm->nextiterator();
}else{
outdb(&outhere,printaddrs);
outhere++;
}
}else{
outdb(&outhere,printaddrs);
outhere++;
}
// check if gone beyond seg, get next seg.
/*if(dta->beyondseg(outhere))*/ // changed build 14
// rewritten build 17. seeks dseg from start, and finds next now.
if (outhere>=(dblock->addr+dblock->size)) {
dta->resetiterator();
nxtblock=dta->nextiterator();
while (nxtblock) {
if (nxtblock->addr==dblock->addr) {
dblock=dta->nextiterator();
break;
}
nxtblock=dta->nextiterator();
if (!nxtblock) dblock=NULL;
}
if (!dblock) break;
outhere=dblock->addr;
}
if (outhere>blk.bottom) break;
if (!outhere.segm) break;
}
DumpBuff(efile);
}
DoneBuff();
CloseHandle(efile);
// scheduler.continuethread();
scheduler.addtask(windowupdate,priority_window,nlptr,NULL);
}
/************************************************************************
* dumptofile *
* - this is the text and asm output routine. It needs a lot more work *
* doing to it and is presently a fairly simple dump of the code. *
************************************************************************/
void disio::dumptofile(char *fname,bool printaddrs)
{ SECURITY_ATTRIBUTES securityatt;
HANDLE efile;
dword num;
dsmitem *tblock;
dsegitem *dblock,*nxtblock;
lptr outhere,nptr;
int i;
securityatt.nLength=sizeof(SECURITY_ATTRIBUTES);
securityatt.lpSecurityDescriptor=NULL;
securityatt.bInheritHandle=false;
efile=CreateFile(fname,GENERIC_WRITE,0,&securityatt,CREATE_NEW,0,NULL);
if(efile==INVALID_HANDLE_VALUE)
{ MessageBox(MainWnd,"File Creation Failed","Borg Disassembler Alert",MB_OK);
return;
}
// scheduler.stopthread();
WriteFile(efile,"; ",2,&num,NULL);
WriteFile(efile,winname,lstrlen(winname),&num,NULL);
WriteFile(efile,"\r\n;\r\n",5,&num,NULL);
WriteFile(efile,hdr,lstrlen(hdr),&num,NULL);
WriteFile(efile,hdr2,lstrlen(hdr2),&num,NULL);
WriteFile(efile,"\r\n",2,&num,NULL);
// find current position.
dsm->resetiterator();
tblock=dsm->nextiterator();
// now tblock= first position
dta->resetiterator();
dblock=dta->nextiterator();
outhere=dblock->addr;
while (dblock) {
ClearBuff(); // clear buffer - ready to start
for (i=0;i<size.y;i++) {
if (tblock) {
if (outhere==tblock->addr) {
switch (tblock->type) {
case dsmcode:
outinst(tblock,printaddrs);
break;
case dsmnameloc:
printlineheader(tblock->addr,printaddrs);
LastPrintBuff("%s:",tblock->data);
break;
case dsmxref:
// temp measure - print first (build 17)
printlineheader(tblock->addr,printaddrs);
LastPrintBuff(";");
LastPrintBuffEpos(COMMENTPOS);
LastPrintBuff("XREFS First: ");
xrefs->printfirst(tblock->addr);
break;
default:
printlineheader(tblock->addr,printaddrs);
outcomment(tblock);
}
outhere+=tblock->length;
tblock=dsm->nextiterator();
}else{
outdb(&outhere,printaddrs);
outhere++;
}
}else{
outdb(&outhere,printaddrs);
outhere++;
}
// check if gone beyond seg, get next seg.
/*if(dta->beyondseg(outhere))*/ // changed build 14
// rewritten build 17. seeks dseg from start, and finds next now.
if (outhere>=(dblock->addr+dblock->size)) {
dta->resetiterator();
nxtblock=dta->nextiterator();
while (nxtblock!=NULL) {
if (nxtblock->addr==dblock->addr) {
dblock=dta->nextiterator();
break;
}
nxtblock=dta->nextiterator();
if (!nxtblock) dblock=NULL;
}
if (!dblock) break;
outhere=dblock->addr;
}
if (!outhere.segm) break;
}
DumpBuff(efile);
}
DoneBuff();
CloseHandle(efile);
// scheduler.continuethread();
scheduler.addtask(windowupdate,priority_window,nlptr,NULL);
}
/************************************************************************
* mainwind.cpp *
* This is one of a few files which contain some old code, a lot of *
* hacks, a lot of hastily stuffed lines and variables, etc, and is in *
* in need of an overhaul. Its also why I left commenting it until the *
* last four files (disasm,fileload,dasm and this one!). Whilst making *
* these comments I have taken a small opportunity to tidy it a little. *
* This file controls output to the main window. It keeps a small buffer *
* of disassembled lines, and it uses this buffer to repaint the main *
* window when WM_PAINT requests are received. *
* Whenever the disassembly is changed or the user scrolls there is a *
* windowupdate request sent to the scheduler with a high priority. *
* When the windowupdate is processed it is passed to the windowupdate *
* or scroller function in disio. disio will regenerate the buffer as *
* required and then invalidate the main window so that a repaint is *
* done. *
* The functions here include basic formatted output to the buffer as *
* well as the window repaints. Repaints will not be done while the *
* buffer is being updated, but will wait for the buffer update to *
* finish and then do the repaint. *
* The functions also use extensive critical sections which ensure that *
* we do not start clearing the buffer during a window update, etc *
************************************************************************/
/************************************************************************
* DoPaint *
* - This is the main painting routine. If the program is quitting then *
* it returns (we dont want thread clashes due to critical sections *
* here and theres no point to repainting when we're exitting). *
* - If the buffer is not ready then we wait, and go to sleep. *
* - Otherwise the routine paints the screen from the buffer, using the *
* selected font and colours *
************************************************************************/
void disio::DoPaint(void) {
PAINTSTRUCT ps; // holds PAINT information
int i;
// while (bufferbusy) Sleep(0); // wait if filling buffer
// if (KillThread) return;
// EnterCriticalSection(&cs);
BeginPaint(wnd,&ps);
SelectObject(ps.hdc,Font);
SetTextColor(ps.hdc,options.textcolor);
for (i=0;i<size.y;i++) {
RECT R;
SetBkColor(ps.hdc,
i==sel ? options.highcolor : options.bgcolor);
GetItemRect(i,&R);
ExtTextOut(ps.hdc,-hpos*CharBox.x,R.top,ETO_OPAQUE,&R,
MainBuff[i],i<lastline?lstrlen(MainBuff[i]):0,NULL);
}
EndPaint(wnd,&ps);
// LeaveCriticalSection(&cs);
}
/************************************************************************
* ClearBuff *
* - This should be called before each reworking of the buffer. It *
* clears the buffer and stops any repainting from taking place. *
* - It also resets the line pointer to the start of the buffer. *
************************************************************************/
void disio::ClearBuff(void) {
// int i;
// EnterCriticalSection(&cs);
// for (i=0;i<size.y;i++) {
// MainBuff[i][0]='\0';
// }
lastline=0;
// bufferbusy=true;
// LeaveCriticalSection(&cs);
}
/************************************************************************
* DoneBuff *
* - This should be called after a reworking of the buffer. It reenables *
* window repainting. *
************************************************************************/
void disio::DoneBuff(void) {
// EnterCriticalSection(&cs);
// bufferbusy=false;
// LeaveCriticalSection(&cs);
}
/************************************************************************
* PrintBuff *
* - This is the printf of the buffer and is similar to wvsprintf but *
* output is to the main buffer. Note that the line pointer is moved *
* on after a call, so we move to the next line automatically. *
************************************************************************/
// adds next line to the buffer.
void disio::PrintBuff(char *szFormat,...) {
// EnterCriticalSection(&cs);
va_list vaArgs;
va_start(vaArgs,szFormat);
if (lastline<size.y) {
wvsprintf(MainBuff[lastline++],szFormat,vaArgs);
}
va_end(vaArgs);
// just zero end of buffer.....in case.
// MainBuff[BUFFER_LINES*max_length]=0;
// LeaveCriticalSection(&cs);
}
/************************************************************************
* LastPrintBuffEpos *
* - Often we use PrintBuff followed by LastPrintBuff to construct a *
* line of output a piece at a time. This function provides basic *
* formatting by allowing us to set the cursor position on the last *
* line printed, by adding spaces until the position. *
************************************************************************/
// adds blanks to previous line to set position
void disio::LastPrintBuffEpos(int xpos) {
int i;
int spos;
if (!lastline) return;
// EnterCriticalSection(&cs);
spos=lastline-1;
i=lstrlen(MainBuff[spos]);
while (i<xpos) {
MainBuff[spos][i]=' ';
i++;
MainBuff[spos][i]='\0';
}
// LeaveCriticalSection(&cs);
}
/************************************************************************
* LastPrintBuffHexValue *
* - Same as LastPrintBuff, but prints num only, in hex. It prints a *
* leading zero where the leading char is alpha. *
************************************************************************/
void disio::LastPrintBuffHexValue(byte num)
{ char tstr[20];
wsprintf(tstr,"%02xh",num);
if((tstr[0]>='a')&&(tstr[0]<='f'))
LastPrintBuff("0");
LastPrintBuff("%02xh",num);
}
/************************************************************************
* LastPrintBuffHexValue *
* - Same as LastPrintBuff, but prints num only, in hex. It prints a *
* leading zero where the leading char is alpha. *
************************************************************************/
void disio::LastPrintBuffLongHexValue(dword num) {
char tstr[20];
wsprintf(tstr,"%02lxh",num);
if (tstr[0]>='a' && tstr[0]<='f') LastPrintBuff("0");
LastPrintBuff(tstr); // doesn't contain "%"
}
/************************************************************************
* LastPrintBuff *
* - This is the same as PrintBuff except that instead of printing a new *
* line it goes back to the last line and adds more to the end of it *
* - So a set of calls tends to look like PrintBuff, LastPrintBuffEPos, *
* LastPrintBuff, LastPrintBuffEPos, LastPrintBuff, PrintBuff, etc *
************************************************************************/
void disio::LastPrintBuff(char *szFormat,...) {
int spos,len;
char s[MAX_LENGTH];
if (!lastline) return;
spos=lastline-1;
// EnterCriticalSection(&cs);
va_list vaArgs;
va_start(vaArgs,szFormat);
wvsprintf(s,szFormat,vaArgs);
va_end(vaArgs);
len=lstrlen(MainBuff[spos]);
lstrcpyn(MainBuff[spos]+len,s,MAX_LENGTH-len); // append and watch size
// LeaveCriticalSection(&cs);
}
/************************************************************************
* DumpBuff *
* - Now this is a real hack. Instead of writing proper file IO routines *
* I simply write a buffer full at a time, and dump each to a file.... *
* Then when I've written the file out I regenerate the buffer for the *
* display again....... to be rewritten...... *
************************************************************************/
void disio::DumpBuff(HANDLE efile) {
DWORD num;
int i;
for (i=0;i<lastline;i++) {
WriteFile(efile,MainBuff[i],lstrlen(MainBuff[i]),&num,NULL);
WriteFile(efile,"\r\n",2,&num,NULL);
}
}
Vorgefundene Kodierung: UTF-8 | 0
|