Bitu Program::GetEnvCount(void) { PhysPt env_read=PhysMake(psp->GetEnvironment(),0); Bitu num=0; while (mem_readb(env_read)!=0) { for (;mem_readb(env_read);env_read++) {}; env_read++; num++; } return num; }
Bit16u DOS_PSP::FindFreeFileEntry(void) { PhysPt files=Real2Phys(sGet(sPSP,file_table)); for (Bit16u i=0;i<sGet(sPSP,max_files);i++) { if (mem_readb(files+i)==0xff) return i; } return 0xff; }
Bit16u DOS_PSP::FindEntryByHandle(Bit8u handle) { PhysPt files=Real2Phys(sGet(sPSP,file_table)); for (Bit16u i=0;i<sGet(sPSP,max_files);i++) { if (mem_readb(files+i)==handle) return i; } return 0xFF; }
Bitu Program::GetEnvCount(void) { PhysPt env_base,env_fence,env_scan; Bitu num = 0; if (dos_kernel_disabled) { LOG_MSG("BUG: Program::GetEnvCount() called with DOS kernel disabled (such as OS boot).\n"); return 0; } if (!LocateEnvironmentBlock(env_base,env_fence,psp->GetEnvironment())) { LOG_MSG("Warning: GetEnvCount() was not able to locate the program's environment block\n"); return false; } env_scan = env_base; while (env_scan < env_fence) { /* "NAME" + "=" + "VALUE" + "\0" */ /* end of the block is a NULL string meaning a \0 follows the last string's \0 */ if (mem_readb(env_scan++) == 0) break; /* normal end of block */ num++; if (!EnvPhys_ScanUntilNextString(env_scan,env_fence)) break; } return num; }
bool Program::GetEnvNum(Bitu want_num,std::string & result) { PhysPt env_base,env_fence,env_scan; Bitu num = 0; if (dos_kernel_disabled) { LOG_MSG("BUG: Program::GetEnvNum() called with DOS kernel disabled (such as OS boot).\n"); return false; } if (!LocateEnvironmentBlock(env_base,env_fence,psp->GetEnvironment())) { LOG_MSG("Warning: GetEnvCount() was not able to locate the program's environment block\n"); return false; } result.clear(); env_scan = env_base; while (env_scan < env_fence) { /* "NAME" + "=" + "VALUE" + "\0" */ /* end of the block is a NULL string meaning a \0 follows the last string's \0 */ if (mem_readb(env_scan) == 0) break; /* normal end of block */ if (num == want_num) { EnvPhys_StrCpyToCPPString(result,env_scan,env_fence); return true; } num++; if (!EnvPhys_ScanUntilNextString(env_scan,env_fence)) break; } return false; }
static Bitu PROGRAMS_Handler(void) { /* This sets up everything for a program start up call */ Bitu size=sizeof(Bit8u); Bit8u index; /* Read the index from program code in memory */ PhysPt reader=PhysMake(dos.psp(),256+sizeof(exe_block)); HostPt writer=(HostPt)&index; for (;size>0;size--) *writer++=mem_readb(reader++); Program * new_program = NULL; if (index > internal_progs.size()) E_Exit("something is messing with the memory"); InternalProgramEntry *ipe = internal_progs[index]; if (ipe == NULL) E_Exit("Attempt to run internal program slot with nothing allocated"); if (ipe->main == NULL) return CBRET_NONE; PROGRAMS_Main * handler = internal_progs[index]->main; (*handler)(&new_program); try { /* "BOOT" can throw an exception (int(2)) */ new_program->Run(); delete new_program; } catch (...) { /* well if it happened, free the program anyway to avert memory leaks */ delete new_program; throw; /* pass it on */ } return CBRET_NONE; }
void DOS_FreeProcessMemory(unsigned short pspseg) { while (1) { if (pspseg) foo (); char *addr = (char*)(&((sMCB*)0)->type); if (mem_readb(addr)==0x5a) break; } };
Bit8u VESA_SetPalette(PhysPt data,Bitu index,Bitu count) { //Structure is (vesa 3.0 doc): blue,green,red,alignment Bit8u r,g,b; if (index>255) return VESA_FAIL; if (index+count>256) return VESA_FAIL; IO_Write(0x3c8,(Bit8u)index); while (count) { b = mem_readb(data++); g = mem_readb(data++); r = mem_readb(data++); data++; IO_Write(0x3c9,r); IO_Write(0x3c9,g); IO_Write(0x3c9,b); count--; } return VESA_SUCCESS; }
static void dma(uint8_t value) { int addr = value << 8; if (value > 0xF1) return; for (int i = 0; i < 160; i++) mem_writeb(0xFE00 + i, mem_readb(addr + i)); }
bool EnvPhys_ScanUntilNextString(PhysPt &env_scan,PhysPt env_fence) { /* scan until end of block or NUL */ while (env_scan < env_fence && mem_readb(env_scan) != 0) env_scan++; /* if we hit the fence, that's something to warn about. */ if (env_scan >= env_fence) { LOG_MSG("Warning: environment string scan hit the end of the environment block without terminating NUL\n"); return false; } /* if we stopped at anything other than a NUL, that's something to warn about */ if (mem_readb(env_scan) != 0) { LOG_MSG("Warning: environment string scan scan stopped without hitting NUL\n"); return false; } env_scan++; /* skip NUL */ return true; }
static void VGA_CopyRow(Bit8u cleft,Bit8u cright,Bit8u rold,Bit8u rnew,PhysPt base) { PhysPt src,dest;Bitu copy; Bit8u cheight = real_readb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT); dest=base+8u*((CurMode->twidth*rnew)*cheight+cleft); src=base+8u*((CurMode->twidth*rold)*cheight+cleft); Bitu nextline=8u*(Bitu)CurMode->twidth; Bitu rowsize=8u*(Bitu)(cright-cleft); copy=cheight; for (;copy>0;copy--) { for (Bitu x=0;x<rowsize;x++) mem_writeb(dest+x,mem_readb(src+x)); dest+=nextline;src+=nextline; } }
Bits CPU_Core_Normal_Run(void) { while (CPU_Cycles-->0) { LOADIP; core.opcode_index=cpu.code.big*0x200; core.prefixes=cpu.code.big; core.ea_table=&EATable[cpu.code.big*256]; BaseDS=SegBase(ds); BaseSS=SegBase(ss); core.base_val_ds=ds; #if C_DEBUG #if C_HEAVY_DEBUG if (DEBUG_HeavyIsBreakpoint()) { FillFlags(); return debugCallback; }; #endif cycle_count++; #endif restart_opcode: switch (core.opcode_index+Fetchb()) { #include "core_normal/prefix_none.h" #include "core_normal/prefix_0f.h" #include "core_normal/prefix_66.h" #include "core_normal/prefix_66_0f.h" default: illegal_opcode: #if C_DEBUG { Bitu len=(GETIP-reg_eip); LOADIP; if (len>16) len=16; char tempcode[16*2+1];char * writecode=tempcode; for (;len>0;len--) { sprintf(writecode,"%02X",mem_readb(core.cseip++)); writecode+=2; } LOG(LOG_CPU,LOG_NORMAL)("Illegal/Unhandled opcode %s",tempcode); } #endif CPU_Exception(6,0); continue; } SAVEIP; } FillFlags(); return CBRET_NONE; decode_end: SAVEIP; FillFlags(); return CBRET_NONE; }
int EnvPhys_StrCmp(PhysPt es,PhysPt ef,const char *ls) { unsigned char a,b; while (1) { a = mem_readb(es++); b = (unsigned char)(*ls++); if (a == '=') a = 0; if (a == 0 && b == 0) break; if (a == b) continue; return (int)a - (int)b; } return 0; }
//=========================================================================== BOOL MemExportar(WORD EndInicial, WORD EndFinal) { #ifdef _WINDOWS OPENFILENAME ofn; #endif // _WINDOWS FILE *Arquivo; char *Buffer; DWORD TamMem; char directory[MAX_PATH] = ""; char filename[MAX_PATH] = ""; unsigned int c; TamMem = EndFinal - EndInicial + 1; Buffer = (char *)malloc(TamMem); for (c = 0; c < TamMem; c++) Buffer[c] = mem_readb(EndInicial + c, 0); //memcpy((void *)Buffer, (const void*)(mem+EndInicial), (size_t)(TamMem)); #ifdef _WINDOWS memset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = (HWND)framewindow; ofn.hInstance = (HINSTANCE)instance; ofn.lpstrFilter = "Todos os Arquivos\0*.*\0"; ofn.lpstrFile = filename; ofn.nMaxFile = MAX_PATH; ofn.lpstrInitialDir = directory; ofn.Flags = OFN_OVERWRITEPROMPT; ofn.lpstrTitle = "Escolha o Arquivo"; if (GetSaveFileName(&ofn)) #else // _WINDOWS if (0) #endif // _WINDOWS { Arquivo = fopen(filename, "wb"); if (!Arquivo) { FrameMostraMensagemErro("Erro ao criar arquivo!"); return -1; } if (!fwrite(Buffer, TamMem, 1, Arquivo)) { FrameMostraMensagemErro("Erro ao criar arquivo!"); fclose(Arquivo); return -1; } fclose(Arquivo); return 0; } return -1; }
static Bitu INT70_Handler(void) { /* Acknowledge irq with cmos */ IO_Write(0x70,0xc); IO_Read(0x71); if (mem_readb(BIOS_WAIT_FLAG_ACTIVE)) { Bit32u count=mem_readd(BIOS_WAIT_FLAG_COUNT); if (count>997) { mem_writed(BIOS_WAIT_FLAG_COUNT,count-997); } else { mem_writed(BIOS_WAIT_FLAG_COUNT,0); PhysPt where=Real2Phys(mem_readd(BIOS_WAIT_FLAG_POINTER)); mem_writeb(where,mem_readb(where)|0x80); mem_writeb(BIOS_WAIT_FLAG_ACTIVE,0); mem_writed(BIOS_WAIT_FLAG_POINTER,RealMake(0,BIOS_WAIT_FLAG_TEMP)); IO_Write(0x70,0xb); IO_Write(0x71,IO_Read(0x71)&~0x40); } } /* Signal EOI to both pics */ IO_Write(0xa0,0x20); IO_Write(0x20,0x20); return 0; }
Program::Program() { /* Find the command line and setup the PSP */ psp = new DOS_PSP(dos.psp()); /* Scan environment for filename */ PhysPt envscan=PhysMake(psp->GetEnvironment(),0); while (mem_readb(envscan)) envscan+=mem_strlen(envscan)+1; envscan+=3; CommandTail tail; MEM_BlockRead(PhysMake(dos.psp(),128),&tail,128); if (tail.count<127) tail.buffer[tail.count]=0; else tail.buffer[126]=0; char filename[256+1]; MEM_StrCopy(envscan,filename,256); cmd = new CommandLine(filename,tail.buffer); }
static Bitu PROGRAMS_Handler(void) { /* This sets up everything for a program start up call */ Bitu size=sizeof(Bit8u); Bit8u index; /* Read the index from program code in memory */ PhysPt reader=PhysMake(dos.psp(),256+sizeof(exe_block)); HostPt writer=(HostPt)&index; for (;size>0;size--) *writer++=mem_readb(reader++); Program * new_program; if(index > internal_progs.size()) E_Exit("something is messing with the memory"); PROGRAMS_Main * handler = internal_progs[index]; (*handler)(&new_program); new_program->Run(); delete new_program; return CBRET_NONE; }
//-------------------------------------------------------------------------- ssize_t idaapi dosbox_debmod_t::dbg_read_memory(ea_t ea, void *buffer, size_t size) { int i; PhysPt addr = (PhysPt)ea; uchar *buf; buf = (uchar *)buffer; //addr = addr + r_debug.base; for(i=0;i<size;i++) { buf[i] = mem_readb(addr); // printf("%02x,",buf[i]); addr++; } printf("dbg_read_memory @ %x, size=%d\n", ea, size); return size; }
static void EGA16_CopyRow(Bit8u cleft,Bit8u cright,Bit8u rold,Bit8u rnew,PhysPt base) { PhysPt src,dest;Bitu copy; Bit8u cheight = real_readb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT); dest=base+(CurMode->twidth*rnew)*cheight+cleft; src=base+(CurMode->twidth*rold)*cheight+cleft; Bitu nextline=(Bitu)CurMode->twidth; /* Setup registers correctly */ IO_Write(0x3ce,5);IO_Write(0x3cf,1); /* Memory transfer mode */ IO_Write(0x3c4,2);IO_Write(0x3c5,0xf); /* Enable all Write planes */ /* Do some copying */ Bitu rowsize=(Bitu)(cright-cleft); copy=cheight; for (;copy>0;copy--) { for (Bitu x=0;x<rowsize;x++) mem_writeb(dest+x,mem_readb(src+x)); dest+=nextline;src+=nextline; } /* Restore registers */ IO_Write(0x3ce,5);IO_Write(0x3cf,0); /* Normal transfer mode */ }
void EnvPhys_StrCpyToCPPString(std::string &result,PhysPt &env_scan,PhysPt env_fence) { char tmp[512],*w=tmp,*wf=tmp+sizeof(tmp)-1,c; result.clear(); while (env_scan < env_fence) { if ((c=(char)mem_readb(env_scan++)) == 0) break; if (w >= wf) { *w = 0; result += tmp; w = tmp; } assert(w < wf); *w++ = c; } if (w != tmp) { *w = 0; result += tmp; } }
//Does way to much. Many things should be moved to mouse reset one day void Mouse_NewVideoMode(void) { mouse.inhibit_draw=false; /* Get the correct resolution from the current video mode */ Bit8u mode=mem_readb(BIOS_VIDEO_MODE); if(mode == mouse.mode) {LOG(LOG_MOUSE,LOG_NORMAL)("New video is the same as the old"); /*return;*/} switch (mode) { case 0x00: case 0x01: case 0x02: case 0x03: { Bitu rows=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS); if ((rows==0) || (rows>250)) rows=25-1; mouse.max_y=8*(rows+1)-1; break; } case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0d: case 0x0e: case 0x13: mouse.max_y=199; break; case 0x0f: case 0x10: mouse.max_y=349; break; case 0x11: case 0x12: mouse.max_y=479; break; default: LOG(LOG_MOUSE,LOG_ERROR)("Unhandled videomode %X on reset",mode); mouse.inhibit_draw=true; return; } mouse.mode = mode; mouse.hidden = 1; mouse.max_x = 639; mouse.min_x = 0; mouse.min_y = 0; mouse.granMask = (mode == 0x0d || mode == 0x13) ? 0xfffe : 0xffff; mouse.events = 0; mouse.timer_in_progress = false; PIC_RemoveEvents(MOUSE_Limit_Events); mouse.hotx = 0; mouse.hoty = 0; mouse.background = false; mouse.screenMask = defaultScreenMask; mouse.cursorMask = defaultCursorMask; mouse.textAndMask= defaultTextAndMask; mouse.textXorMask= defaultTextXorMask; mouse.language = 0; mouse.page = 0; mouse.doubleSpeedThreshold = 64; mouse.updateRegion_x[0] = 1; mouse.updateRegion_y[0] = 1; mouse.updateRegion_x[1] = 1; mouse.updateRegion_y[1] = 1; mouse.cursorType = 0; mouse.enabled=true; mouse.oldhidden=1; oldmouseX = static_cast<Bit16s>(mouse.x); oldmouseY = static_cast<Bit16s>(mouse.y); }
Bits CPU_Core_Prefetch_Run(void) { bool invalidate_pq=false; while (CPU_Cycles-->0) { if (invalidate_pq) { pq_valid=false; invalidate_pq=false; } LOADIP; core.opcode_index=cpu.code.big*0x200; core.prefixes=cpu.code.big; core.ea_table=&EATable[cpu.code.big*256]; BaseDS=SegBase(ds); BaseSS=SegBase(ss); core.base_val_ds=ds; #if C_DEBUG #if C_HEAVY_DEBUG if (DEBUG_HeavyIsBreakpoint()) { FillFlags(); return debugCallback; }; #endif cycle_count++; #endif restart_opcode: Bit8u next_opcode=Fetchb(); invalidate_pq=false; if (core.opcode_index&OPCODE_0F) invalidate_pq=true; else switch (next_opcode) { case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f: // jcc case 0x9a: // call case 0xc2: case 0xc3: // retn case 0xc8: // enter case 0xc9: // leave case 0xca: case 0xcb: // retf case 0xcc: // int3 case 0xcd: // int case 0xce: // into case 0xcf: // iret case 0xe0: // loopnz case 0xe1: // loopz case 0xe2: // loop case 0xe3: // jcxz case 0xe8: // call case 0xe9: case 0xea: case 0xeb: // jmp case 0xff: invalidate_pq=true; break; default: break; } switch (core.opcode_index+next_opcode) { #include "core_normal/prefix_none.h" #include "core_normal/prefix_0f.h" #include "core_normal/prefix_66.h" #include "core_normal/prefix_66_0f.h" default: illegal_opcode: #if C_DEBUG { bool ignore=false; Bitu len=(GETIP-reg_eip); LOADIP; if (len>16) len=16; char tempcode[16*2+1];char * writecode=tempcode; if (ignore_opcode_63 && mem_readb(core.cseip) == 0x63) ignore = true; for (;len>0;len--) { sprintf(writecode,"%02X",mem_readb(core.cseip++)); writecode+=2; } if (!ignore) LOG(LOG_CPU,LOG_NORMAL)("Illegal/Unhandled opcode %s",tempcode); } #endif CPU_Exception(6,0); invalidate_pq=true; continue; } SAVEIP; } FillFlags(); return CBRET_NONE; decode_end: SAVEIP; FillFlags(); return CBRET_NONE; }
void mem_strcpy(PhysPt dest,PhysPt src) { Bit8u r; while ( (r = mem_readb(src++)) ) mem_writeb_inline(dest++,r); mem_writeb_inline(dest,0); }
static Bitu DOS_21Handler(void) { if (((reg_ah != 0x50) && (reg_ah != 0x51) && (reg_ah != 0x62) && (reg_ah != 0x64)) && (reg_ah<0x6c)) { DOS_PSP psp(dos.psp()); psp.SetStack(RealMake(SegValue(ss),reg_sp-18)); } char name1[DOSNAMEBUF+2+DOS_NAMELENGTH_ASCII]; char name2[DOSNAMEBUF+2+DOS_NAMELENGTH_ASCII]; static Bitu time_start = 0; //For emulating temporary time changes. switch (reg_ah) { case 0x00: /* Terminate Program */ DOS_Terminate(mem_readw(SegPhys(ss)+reg_sp+2),false,0); break; case 0x01: /* Read character from STDIN, with echo */ { Bit8u c;Bit16u n=1; dos.echo=true; DOS_ReadFile(STDIN,&c,&n); reg_al=c; dos.echo=false; } break; case 0x02: /* Write character to STDOUT */ { Bit8u c=reg_dl;Bit16u n=1; DOS_WriteFile(STDOUT,&c,&n); //Not in the official specs, but happens nonetheless. (last written character) reg_al = c;// reg_al=(c==9)?0x20:c; //Officially: tab to spaces } break; case 0x03: /* Read character from STDAUX */ { Bit16u port = real_readw(0x40,0); if(port!=0 && serialports[0]) { Bit8u status; // RTS/DTR on IO_WriteB(port+4,0x3); serialports[0]->Getchar(®_al, &status, true, 0xFFFFFFFF); } } break; case 0x04: /* Write Character to STDAUX */ { Bit16u port = real_readw(0x40,0); if(port!=0 && serialports[0]) { // RTS/DTR on IO_WriteB(port+4,0x3); serialports[0]->Putchar(reg_dl,true,true, 0xFFFFFFFF); // RTS off IO_WriteB(port+4,0x1); } } break; case 0x05: /* Write Character to PRINTER */ E_Exit("DOS:Unhandled call %02X",reg_ah); break; case 0x06: /* Direct Console Output / Input */ switch (reg_dl) { case 0xFF: /* Input */ { //Simulate DOS overhead for timing sensitive games //MM1 overhead(); //TODO Make this better according to standards if (!DOS_GetSTDINStatus()) { reg_al=0; CALLBACK_SZF(true); break; } Bit8u c;Bit16u n=1; DOS_ReadFile(STDIN,&c,&n); reg_al=c; CALLBACK_SZF(false); break; } default: { Bit8u c = reg_dl;Bit16u n = 1; DOS_WriteFile(STDOUT,&c,&n); reg_al = reg_dl; } break; }; break; case 0x07: /* Character Input, without echo */ { Bit8u c;Bit16u n=1; DOS_ReadFile (STDIN,&c,&n); reg_al=c; break; }; case 0x08: /* Direct Character Input, without echo (checks for breaks officially :)*/ { Bit8u c;Bit16u n=1; DOS_ReadFile (STDIN,&c,&n); reg_al=c; break; }; case 0x09: /* Write string to STDOUT */ { Bit8u c;Bit16u n=1; PhysPt buf=SegPhys(ds)+reg_dx; while ((c=mem_readb(buf++))!='$') { DOS_WriteFile(STDOUT,&c,&n); } } break; case 0x0a: /* Buffered Input */ { //TODO ADD Break checkin in STDIN but can't care that much for it PhysPt data=SegPhys(ds)+reg_dx; Bit8u free=mem_readb(data); Bit8u read=0;Bit8u c;Bit16u n=1; if (!free) break; free--; for(;;) { DOS_ReadFile(STDIN,&c,&n); if (c == 8) { // Backspace if (read) { //Something to backspace. // STDOUT treats backspace as non-destructive. DOS_WriteFile(STDOUT,&c,&n); c = ' '; DOS_WriteFile(STDOUT,&c,&n); c = 8; DOS_WriteFile(STDOUT,&c,&n); --read; } continue; } if (read == free && c != 13) { // Keyboard buffer full Bit8u bell = 7; DOS_WriteFile(STDOUT, &bell, &n); continue; } DOS_WriteFile(STDOUT,&c,&n); mem_writeb(data+read+2,c); if (c==13) break; read++; }; mem_writeb(data+1,read); break; }; case 0x0b: /* Get STDIN Status */ if (!DOS_GetSTDINStatus()) {reg_al=0x00;} else {reg_al=0xFF;} //Simulate some overhead for timing issues //Tankwar menu (needs maybe even more) overhead(); break; case 0x0c: /* Flush Buffer and read STDIN call */ { /* flush buffer if STDIN is CON */ Bit8u handle=RealHandle(STDIN); if (handle!=0xFF && Files[handle] && Files[handle]->IsName("CON")) { Bit8u c;Bit16u n; while (DOS_GetSTDINStatus()) { n=1; DOS_ReadFile(STDIN,&c,&n); } } switch (reg_al) { case 0x1: case 0x6: case 0x7: case 0x8: case 0xa: { Bit8u oldah=reg_ah; reg_ah=reg_al; DOS_21Handler(); reg_ah=oldah; } break; default: // LOG_ERROR("DOS:0C:Illegal Flush STDIN Buffer call %d",reg_al); reg_al=0; break; } } break; //TODO Find out the values for when reg_al!=0 //TODO Hope this doesn't do anything special case 0x0d: /* Disk Reset */ //Sure let's reset a virtual disk break; case 0x0e: /* Select Default Drive */ DOS_SetDefaultDrive(reg_dl); reg_al=DOS_DRIVES; break; case 0x0f: /* Open File using FCB */ if(DOS_FCBOpen(SegValue(ds),reg_dx)){ reg_al=0; }else{ reg_al=0xff; } LOG(LOG_FCB,LOG_NORMAL)("DOS:0x0f FCB-fileopen used, result:al=%d",reg_al); break; case 0x10: /* Close File using FCB */ if(DOS_FCBClose(SegValue(ds),reg_dx)){ reg_al=0; }else{ reg_al=0xff; } LOG(LOG_FCB,LOG_NORMAL)("DOS:0x10 FCB-fileclose used, result:al=%d",reg_al); break; case 0x11: /* Find First Matching File using FCB */ if(DOS_FCBFindFirst(SegValue(ds),reg_dx)) reg_al = 0x00; else reg_al = 0xFF; LOG(LOG_FCB,LOG_NORMAL)("DOS:0x11 FCB-FindFirst used, result:al=%d",reg_al); break; case 0x12: /* Find Next Matching File using FCB */ if(DOS_FCBFindNext(SegValue(ds),reg_dx)) reg_al = 0x00; else reg_al = 0xFF; LOG(LOG_FCB,LOG_NORMAL)("DOS:0x12 FCB-FindNext used, result:al=%d",reg_al); break; case 0x13: /* Delete File using FCB */ if (DOS_FCBDeleteFile(SegValue(ds),reg_dx)) reg_al = 0x00; else reg_al = 0xFF; LOG(LOG_FCB,LOG_NORMAL)("DOS:0x16 FCB-Delete used, result:al=%d",reg_al); break; case 0x14: /* Sequential read from FCB */ reg_al = DOS_FCBRead(SegValue(ds),reg_dx,0); LOG(LOG_FCB,LOG_NORMAL)("DOS:0x14 FCB-Read used, result:al=%d",reg_al); break; case 0x15: /* Sequential write to FCB */ reg_al=DOS_FCBWrite(SegValue(ds),reg_dx,0); LOG(LOG_FCB,LOG_NORMAL)("DOS:0x15 FCB-Write used, result:al=%d",reg_al); break; case 0x16: /* Create or truncate file using FCB */ if (DOS_FCBCreate(SegValue(ds),reg_dx)) reg_al = 0x00; else reg_al = 0xFF; LOG(LOG_FCB,LOG_NORMAL)("DOS:0x16 FCB-Create used, result:al=%d",reg_al); break; case 0x17: /* Rename file using FCB */ if (DOS_FCBRenameFile(SegValue(ds),reg_dx)) reg_al = 0x00; else reg_al = 0xFF; break; case 0x1b: /* Get allocation info for default drive */ if (!DOS_GetAllocationInfo(0,®_cx,®_al,®_dx)) reg_al=0xff; break; case 0x1c: /* Get allocation info for specific drive */ if (!DOS_GetAllocationInfo(reg_dl,®_cx,®_al,®_dx)) reg_al=0xff; break; case 0x21: /* Read random record from FCB */ { Bit16u toread=1; reg_al = DOS_FCBRandomRead(SegValue(ds),reg_dx,&toread,true); } LOG(LOG_FCB,LOG_NORMAL)("DOS:0x21 FCB-Random read used, result:al=%d",reg_al); break; case 0x22: /* Write random record to FCB */ { Bit16u towrite=1; reg_al=DOS_FCBRandomWrite(SegValue(ds),reg_dx,&towrite,true); } LOG(LOG_FCB,LOG_NORMAL)("DOS:0x22 FCB-Random write used, result:al=%d",reg_al); break; case 0x23: /* Get file size for FCB */ if (DOS_FCBGetFileSize(SegValue(ds),reg_dx)) reg_al = 0x00; else reg_al = 0xFF; break; case 0x24: /* Set Random Record number for FCB */ DOS_FCBSetRandomRecord(SegValue(ds),reg_dx); break; case 0x27: /* Random block read from FCB */ reg_al = DOS_FCBRandomRead(SegValue(ds),reg_dx,®_cx,false); LOG(LOG_FCB,LOG_NORMAL)("DOS:0x27 FCB-Random(block) read used, result:al=%d",reg_al); break; case 0x28: /* Random Block write to FCB */ reg_al=DOS_FCBRandomWrite(SegValue(ds),reg_dx,®_cx,false); LOG(LOG_FCB,LOG_NORMAL)("DOS:0x28 FCB-Random(block) write used, result:al=%d",reg_al); break; case 0x29: /* Parse filename into FCB */ { Bit8u difference; char string[1024]; MEM_StrCopy(SegPhys(ds)+reg_si,string,1023); // 1024 toasts the stack reg_al=FCB_Parsename(SegValue(es),reg_di,reg_al ,string, &difference); reg_si+=difference; } LOG(LOG_FCB,LOG_NORMAL)("DOS:29:FCB Parse Filename, result:al=%d",reg_al); break; case 0x19: /* Get current default drive */ reg_al=DOS_GetDefaultDrive(); break; case 0x1a: /* Set Disk Transfer Area Address */ dos.dta(RealMakeSeg(ds,reg_dx)); break; case 0x25: /* Set Interrupt Vector */ RealSetVec(reg_al,RealMakeSeg(ds,reg_dx)); break; case 0x26: /* Create new PSP */ DOS_NewPSP(reg_dx,DOS_PSP(dos.psp()).GetSize()); reg_al=0xf0; /* al destroyed */ break; case 0x2a: /* Get System Date */ { reg_ax=0; // get time CALLBACK_RunRealInt(0x1a); if(reg_al) DOS_AddDays(reg_al); int a = (14 - dos.date.month)/12; int y = dos.date.year - a; int m = dos.date.month + 12*a - 2; reg_al=(dos.date.day+y+(y/4)-(y/100)+(y/400)+(31*m)/12) % 7; reg_cx=dos.date.year; reg_dh=dos.date.month; reg_dl=dos.date.day; } break; case 0x2b: /* Set System Date */ if (reg_cx<1980) { reg_al=0xff;break;} if ((reg_dh>12) || (reg_dh==0)) { reg_al=0xff;break;} if (reg_dl==0) { reg_al=0xff;break;} if (reg_dl>DOS_DATE_months[reg_dh]) { if(!((reg_dh==2)&&(reg_cx%4 == 0)&&(reg_dl==29))) // february pass { reg_al=0xff;break; } } dos.date.year=reg_cx; dos.date.month=reg_dh; dos.date.day=reg_dl; reg_al=0; break; case 0x2c: { /* Get System Time */ reg_ax=0; // get time CALLBACK_RunRealInt(0x1a); if(reg_al) DOS_AddDays(reg_al); reg_ah=0x2c; Bitu ticks=((Bitu)reg_cx<<16)|reg_dx; if(time_start<=ticks) ticks-=time_start; Bitu time=(Bitu)((100.0/((double)PIT_TICK_RATE/65536.0)) * (double)ticks); reg_dl=(Bit8u)((Bitu)time % 100); // 1/100 seconds time/=100; reg_dh=(Bit8u)((Bitu)time % 60); // seconds time/=60; reg_cl=(Bit8u)((Bitu)time % 60); // minutes time/=60; reg_ch=(Bit8u)((Bitu)time % 24); // hours //Simulate DOS overhead for timing-sensitive games //Robomaze 2 overhead(); break; } case 0x2d: /* Set System Time */ LOG(LOG_DOSMISC,LOG_ERROR)("DOS:Set System Time not supported"); //Check input parameters nonetheless if( reg_ch > 23 || reg_cl > 59 || reg_dh > 59 || reg_dl > 99 ) reg_al = 0xff; else { //Allow time to be set to zero. Restore the orginal time for all other parameters. (QuickBasic) if (reg_cx == 0 && reg_dx == 0) {time_start = mem_readd(BIOS_TIMER);LOG_MSG("Warning: game messes with DOS time!");} else time_start = 0; reg_al = 0; } break; case 0x2e: /* Set Verify flag */ dos.verify=(reg_al==1); break; case 0x2f: /* Get Disk Transfer Area */ SegSet16(es,RealSeg(dos.dta())); reg_bx=RealOff(dos.dta()); break; case 0x30: /* Get DOS Version */ if (reg_al==0) reg_bh=0xFF; /* Fake Microsoft DOS */ if (reg_al==1) reg_bh=0x10; /* DOS is in HMA */ reg_al=dos.version.major; reg_ah=dos.version.minor; /* Serialnumber */ reg_bl=0x00; reg_cx=0x0000; break; case 0x31: /* Terminate and stay resident */ // Important: This service does not set the carry flag! DOS_ResizeMemory(dos.psp(),®_dx); DOS_Terminate(dos.psp(),true,reg_al); break; case 0x1f: /* Get drive parameter block for default drive */ case 0x32: /* Get drive parameter block for specific drive */ { /* Officially a dpb should be returned as well. The disk detection part is implemented */ Bit8u drive=reg_dl; if (!drive || reg_ah==0x1f) drive = DOS_GetDefaultDrive(); else drive--; if (Drives[drive]) { reg_al = 0x00; SegSet16(ds,dos.tables.dpb); reg_bx = drive;//Faking only the first entry (that is the driveletter) LOG(LOG_DOSMISC,LOG_ERROR)("Get drive parameter block."); } else { reg_al=0xff; } } break; case 0x33: /* Extended Break Checking */ switch (reg_al) { case 0:reg_dl=dos.breakcheck;break; /* Get the breakcheck flag */ case 1:dos.breakcheck=(reg_dl>0);break; /* Set the breakcheck flag */ case 2:{bool old=dos.breakcheck;dos.breakcheck=(reg_dl>0);reg_dl=old;}break; case 3: /* Get cpsw */ /* Fallthrough */ case 4: /* Set cpsw */ LOG(LOG_DOSMISC,LOG_ERROR)("Someone playing with cpsw %x",reg_ax); break; case 5:reg_dl=3;break;//TODO should be z /* Always boot from c: :) */ case 6: /* Get true version number */ reg_bl=dos.version.major; reg_bh=dos.version.minor; reg_dl=dos.version.revision; reg_dh=0x10; /* Dos in HMA */ break; default: LOG(LOG_DOSMISC,LOG_ERROR)("Weird 0x33 call %2X",reg_al); reg_al =0xff; break; } break; case 0x34: /* Get INDos Flag */ SegSet16(es,DOS_SDA_SEG); reg_bx=DOS_SDA_OFS + 0x01; break; case 0x35: /* Get interrupt vector */ reg_bx=real_readw(0,((Bit16u)reg_al)*4); SegSet16(es,real_readw(0,((Bit16u)reg_al)*4+2)); break; case 0x36: /* Get Free Disk Space */ { Bit16u bytes,clusters,free; Bit8u sectors; if (DOS_GetFreeDiskSpace(reg_dl,&bytes,§ors,&clusters,&free)) { reg_ax=sectors; reg_bx=free; reg_cx=bytes; reg_dx=clusters; } else { Bit8u drive=reg_dl; if (drive==0) drive=DOS_GetDefaultDrive(); else drive--; if (drive<2) { // floppy drive, non-present drivesdisks issue floppy check through int24 // (critical error handler); needed for Mixed up Mother Goose (hook) // CALLBACK_RunRealInt(0x24); } reg_ax=0xffff; // invalid drive specified } } break; case 0x37: /* Get/Set Switch char Get/Set Availdev thing */ //TODO Give errors for these functions to see if anyone actually uses this shit- switch (reg_al) { case 0: reg_al=0;reg_dl=0x2f;break; /* always return '/' like dos 5.0+ */ case 1: reg_al=0;break; case 2: reg_al=0;reg_dl=0x2f;break; case 3: reg_al=0;break; }; LOG(LOG_MISC,LOG_ERROR)("DOS:0x37:Call for not supported switchchar"); break; case 0x38: /* Set Country Code */ if (reg_al==0) { /* Get country specidic information */ PhysPt dest = SegPhys(ds)+reg_dx; MEM_BlockWrite(dest,dos.tables.country,0x18); reg_ax = reg_bx = 0x01; CALLBACK_SCF(false); break; } else { /* Set country code */ LOG(LOG_MISC,LOG_ERROR)("DOS:Setting country code not supported"); } CALLBACK_SCF(true); break; case 0x39: /* MKDIR Create directory */ MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); if (DOS_MakeDir(name1)) { reg_ax=0x05; /* ax destroyed */ CALLBACK_SCF(false); } else { reg_ax=dos.errorcode; CALLBACK_SCF(true); } break; case 0x3a: /* RMDIR Remove directory */ MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); if (DOS_RemoveDir(name1)) { reg_ax=0x05; /* ax destroyed */ CALLBACK_SCF(false); } else { reg_ax=dos.errorcode; CALLBACK_SCF(true); LOG(LOG_MISC,LOG_NORMAL)("Remove dir failed on %s with error %X",name1,dos.errorcode); } break; case 0x3b: /* CHDIR Set current directory */ MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); if (DOS_ChangeDir(name1)) { reg_ax=0x00; /* ax destroyed */ CALLBACK_SCF(false); } else { reg_ax=dos.errorcode; CALLBACK_SCF(true); } break; case 0x3c: /* CREATE Create of truncate file */ MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); if (DOS_CreateFile(name1,reg_cx,®_ax)) { CALLBACK_SCF(false); } else { reg_ax=dos.errorcode; CALLBACK_SCF(true); } break; case 0x3d: /* OPEN Open existing file */ MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); if (DOS_OpenFile(name1,reg_al,®_ax)) { CALLBACK_SCF(false); } else { reg_ax=dos.errorcode; CALLBACK_SCF(true); } break; case 0x3e: /* CLOSE Close file */ if (DOS_CloseFile(reg_bx)) { // reg_al=0x01; /* al destroyed. Refcount */ CALLBACK_SCF(false); } else { reg_ax=dos.errorcode; CALLBACK_SCF(true); } break; case 0x3f: /* READ Read from file or device */ { Bit16u toread=reg_cx; dos.echo=true; if (DOS_ReadFile(reg_bx,dos_copybuf,&toread)) { MEM_BlockWrite(SegPhys(ds)+reg_dx,dos_copybuf,toread); reg_ax=toread; CALLBACK_SCF(false); } else { reg_ax=dos.errorcode; CALLBACK_SCF(true); } modify_cycles(reg_ax); dos.echo=false; break; } case 0x40: /* WRITE Write to file or device */ { Bit16u towrite=reg_cx; MEM_BlockRead(SegPhys(ds)+reg_dx,dos_copybuf,towrite); if (DOS_WriteFile(reg_bx,dos_copybuf,&towrite)) { reg_ax=towrite; CALLBACK_SCF(false); } else { reg_ax=dos.errorcode; CALLBACK_SCF(true); } modify_cycles(reg_ax); break; }; case 0x41: /* UNLINK Delete file */ MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); if (DOS_UnlinkFile(name1)) { CALLBACK_SCF(false); } else { reg_ax=dos.errorcode; CALLBACK_SCF(true); } break; case 0x42: /* LSEEK Set current file position */ { Bit32u pos=(reg_cx<<16) + reg_dx; if (DOS_SeekFile(reg_bx,&pos,reg_al)) { reg_dx=(Bit16u)(pos >> 16); reg_ax=(Bit16u)(pos & 0xFFFF); CALLBACK_SCF(false); } else { reg_ax=dos.errorcode; CALLBACK_SCF(true); } break; }
void DOS_FCB::GetAttr(Bit8u& attr) { if(extended) attr=mem_readb(pt - 1); }
/* NTS: "entry" string must have already been converted to uppercase */ bool Program::SetEnv(const char * entry,const char * new_string) { PhysPt env_base,env_fence,env_scan; size_t nsl = 0,el = 0,needs; if (dos_kernel_disabled) { LOG_MSG("BUG: Program::SetEnv() called with DOS kernel disabled (such as OS boot).\n"); return false; } if (!LocateEnvironmentBlock(env_base,env_fence,psp->GetEnvironment())) { LOG_MSG("Warning: SetEnv() was not able to locate the program's environment block\n"); return false; } el = strlen(entry); if (*new_string != 0) nsl = strlen(new_string); needs = nsl+1+el+1+1; /* entry + '=' + new_string + '\0' + '\0' */ /* look for the variable in the block. break the loop if found */ env_scan = env_base; while (env_scan < env_fence) { if (mem_readb(env_scan) == 0) break; if (EnvPhys_StrCmp(env_scan,env_fence,entry) == 0) { /* found it. remove by shifting the rest of the environment block over */ int zeroes=0; PhysPt s,d; /* before we remove it: is there room for the new value? */ if (nsl != 0) { if ((env_scan+needs) > env_fence) { LOG_MSG("Program::SetEnv() error, insufficient room for environment variable %s=%s\n",entry,new_string); return false; } } s = env_scan; d = env_scan; while (s < env_fence && mem_readb(s) != 0) s++; if (s < env_fence && mem_readb(s) == 0) s++; while (s < env_fence) { unsigned char b = mem_readb(s++); if (b == 0) zeroes++; else zeroes=0; mem_writeb(d++,b); if (zeroes >= 2) break; /* two consecutive zeros means the end of the block */ } } else { /* scan to next string */ if (!EnvPhys_ScanUntilNextString(env_scan,env_fence)) break; } } /* At this point, env_scan points to the first byte beyond the block */ /* add the string to the end of the block */ if (*new_string != 0) { if ((env_scan+needs) > env_fence) { LOG_MSG("Program::SetEnv() error, insufficient room for environment variable %s=%s\n",entry,new_string); return false; } assert(env_scan < env_fence); for (const char *s=entry;*s != 0;) mem_writeb(env_scan++,*s++); mem_writeb(env_scan++,'='); assert(env_scan < env_fence); for (const char *s=new_string;*s != 0;) mem_writeb(env_scan++,*s++); mem_writeb(env_scan++,0); mem_writeb(env_scan++,0); assert(env_scan < env_fence); } return true; }
Bit8u DOS_PSP::GetFileHandle(Bit16u index) { if (index>=sGet(sPSP,max_files)) return 0xff; PhysPt files=Real2Phys(sGet(sPSP,file_table)); return mem_readb(files+index); }
bool INT10_VideoState_Save(Bitu state,RealPt buffer) { Bitu ct; if ((state&7)==0) return false; Bitu base_seg=RealSeg(buffer); Bitu base_dest=RealOff(buffer)+0x20; if (state&1) { real_writew(base_seg,RealOff(buffer),base_dest); Bit16u crt_reg=real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); real_writew(base_seg,base_dest+0x40,crt_reg); real_writeb(base_seg,base_dest+0x00,IO_ReadB(0x3c4)); real_writeb(base_seg,base_dest+0x01,IO_ReadB(0x3d4)); real_writeb(base_seg,base_dest+0x02,IO_ReadB(0x3ce)); IO_ReadB(crt_reg+6); real_writeb(base_seg,base_dest+0x03,IO_ReadB(0x3c0)); real_writeb(base_seg,base_dest+0x04,IO_ReadB(0x3ca)); // sequencer for (ct=1; ct<5; ct++) { IO_WriteB(0x3c4,ct); real_writeb(base_seg,base_dest+0x04+ct,IO_ReadB(0x3c5)); } real_writeb(base_seg,base_dest+0x09,IO_ReadB(0x3cc)); // crt controller for (ct=0; ct<0x19; ct++) { IO_WriteB(crt_reg,ct); real_writeb(base_seg,base_dest+0x0a+ct,IO_ReadB(crt_reg+1)); } // attr registers for (ct=0; ct<4; ct++) { IO_ReadB(crt_reg+6); IO_WriteB(0x3c0,0x10+ct); real_writeb(base_seg,base_dest+0x33+ct,IO_ReadB(0x3c1)); } // graphics registers for (ct=0; ct<9; ct++) { IO_WriteB(0x3ce,ct); real_writeb(base_seg,base_dest+0x37+ct,IO_ReadB(0x3cf)); } // save some registers IO_WriteB(0x3c4,2); Bit8u crtc_2=IO_ReadB(0x3c5); IO_WriteB(0x3c4,4); Bit8u crtc_4=IO_ReadB(0x3c5); IO_WriteB(0x3ce,6); Bit8u gfx_6=IO_ReadB(0x3cf); IO_WriteB(0x3ce,5); Bit8u gfx_5=IO_ReadB(0x3cf); IO_WriteB(0x3ce,4); Bit8u gfx_4=IO_ReadB(0x3cf); // reprogram for full access to plane latches IO_WriteW(0x3c4,0x0f02); IO_WriteW(0x3c4,0x0704); IO_WriteW(0x3ce,0x0406); IO_WriteW(0x3ce,0x0105); mem_writeb(0xaffff,0); for (ct=0; ct<4; ct++) { IO_WriteW(0x3ce,0x0004+ct*0x100); real_writeb(base_seg,base_dest+0x42+ct,mem_readb(0xaffff)); } // restore registers IO_WriteW(0x3ce,0x0004|(gfx_4<<8)); IO_WriteW(0x3ce,0x0005|(gfx_5<<8)); IO_WriteW(0x3ce,0x0006|(gfx_6<<8)); IO_WriteW(0x3c4,0x0004|(crtc_4<<8)); IO_WriteW(0x3c4,0x0002|(crtc_2<<8)); for (ct=0; ct<0x10; ct++) { IO_ReadB(crt_reg+6); IO_WriteB(0x3c0,ct); real_writeb(base_seg,base_dest+0x23+ct,IO_ReadB(0x3c1)); } IO_WriteB(0x3c0,0x20); base_dest+=0x46; } if (state&2) { real_writew(base_seg,RealOff(buffer)+2,base_dest); real_writeb(base_seg,base_dest+0x00,mem_readb(0x410)&0x30); for (ct=0; ct<0x1e; ct++) { real_writeb(base_seg,base_dest+0x01+ct,mem_readb(0x449+ct)); } for (ct=0; ct<0x07; ct++) { real_writeb(base_seg,base_dest+0x1f+ct,mem_readb(0x484+ct)); } real_writed(base_seg,base_dest+0x26,mem_readd(0x48a)); real_writed(base_seg,base_dest+0x2a,mem_readd(0x14)); // int 5 real_writed(base_seg,base_dest+0x2e,mem_readd(0x74)); // int 1d real_writed(base_seg,base_dest+0x32,mem_readd(0x7c)); // int 1f real_writed(base_seg,base_dest+0x36,mem_readd(0x10c)); // int 43 base_dest+=0x3a; } if (state&4) { real_writew(base_seg,RealOff(buffer)+4,base_dest); Bit16u crt_reg=real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); IO_ReadB(crt_reg+6); IO_WriteB(0x3c0,0x14); real_writeb(base_seg,base_dest+0x303,IO_ReadB(0x3c1)); Bitu dac_state=IO_ReadB(0x3c7)&1; Bitu dac_windex=IO_ReadB(0x3c8); if (dac_state!=0) dac_windex--; real_writeb(base_seg,base_dest+0x000,dac_state); real_writeb(base_seg,base_dest+0x001,dac_windex); real_writeb(base_seg,base_dest+0x002,IO_ReadB(0x3c6)); for (ct=0; ct<0x100; ct++) { IO_WriteB(0x3c7,ct); real_writeb(base_seg,base_dest+0x003+ct*3+0,IO_ReadB(0x3c9)); real_writeb(base_seg,base_dest+0x003+ct*3+1,IO_ReadB(0x3c9)); real_writeb(base_seg,base_dest+0x003+ct*3+2,IO_ReadB(0x3c9)); } IO_ReadB(crt_reg+6); IO_WriteB(0x3c0,0x20); base_dest+=0x303; } if ((svgaCard==SVGA_S3Trio) && (state&8)) { real_writew(base_seg,RealOff(buffer)+6,base_dest); Bit16u crt_reg=real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); IO_WriteB(0x3c4,0x08); // Bitu seq_8=IO_ReadB(0x3c5); IO_ReadB(0x3c5); // real_writeb(base_seg,base_dest+0x00,IO_ReadB(0x3c5)); IO_WriteB(0x3c5,0x06); // unlock s3-specific registers // sequencer for (ct=0; ct<0x13; ct++) { IO_WriteB(0x3c4,0x09+ct); real_writeb(base_seg,base_dest+0x00+ct,IO_ReadB(0x3c5)); } // unlock s3-specific registers IO_WriteW(crt_reg,0x4838); IO_WriteW(crt_reg,0xa539); // crt controller Bitu ct_dest=0x13; for (ct=0; ct<0x40; ct++) { if ((ct==0x4a-0x30) || (ct==0x4b-0x30)) { IO_WriteB(crt_reg,0x45); IO_ReadB(crt_reg+1); IO_WriteB(crt_reg,0x30+ct); real_writeb(base_seg,base_dest+(ct_dest++),IO_ReadB(crt_reg+1)); real_writeb(base_seg,base_dest+(ct_dest++),IO_ReadB(crt_reg+1)); real_writeb(base_seg,base_dest+(ct_dest++),IO_ReadB(crt_reg+1)); } else { IO_WriteB(crt_reg,0x30+ct); real_writeb(base_seg,base_dest+(ct_dest++),IO_ReadB(crt_reg+1)); } } } return true; }
bool INT10_VideoState_Restore(Bitu state,RealPt buffer) { Bitu ct; if ((state&7)==0) return false; Bit16u base_seg=RealSeg(buffer); Bit16u base_dest; if (state&1) { base_dest=real_readw(base_seg,RealOff(buffer)); Bit16u crt_reg=real_readw(base_seg,base_dest+0x40); // reprogram for full access to plane latches IO_WriteW(0x3c4,0x0704); IO_WriteW(0x3ce,0x0406); IO_WriteW(0x3ce,0x0005); IO_WriteW(0x3c4,0x0002); mem_writeb(0xaffff,real_readb(base_seg,base_dest+0x42)); IO_WriteW(0x3c4,0x0102); mem_writeb(0xaffff,real_readb(base_seg,base_dest+0x43)); IO_WriteW(0x3c4,0x0202); mem_writeb(0xaffff,real_readb(base_seg,base_dest+0x44)); IO_WriteW(0x3c4,0x0402); mem_writeb(0xaffff,real_readb(base_seg,base_dest+0x45)); IO_WriteW(0x3c4,0x0f02); mem_readb(0xaffff); IO_WriteW(0x3c4,0x0100); // sequencer for (ct=1; ct<5; ct++) { IO_WriteW(0x3c4,ct+(real_readb(base_seg,base_dest+0x04+ct)<<8)); } IO_WriteB(0x3c2,real_readb(base_seg,base_dest+0x09)); IO_WriteW(0x3c4,0x0300); IO_WriteW(crt_reg,0x0011); // crt controller for (ct=0; ct<0x19; ct++) { IO_WriteW(crt_reg,ct+(real_readb(base_seg,base_dest+0x0a+ct)<<8)); } IO_ReadB(crt_reg+6); // attr registers for (ct=0; ct<4; ct++) { IO_WriteB(0x3c0,0x10+ct); IO_WriteB(0x3c0,real_readb(base_seg,base_dest+0x33+ct)); } // graphics registers for (ct=0; ct<9; ct++) { IO_WriteW(0x3ce,ct+(real_readb(base_seg,base_dest+0x37+ct)<<8)); } IO_WriteB(crt_reg+6,real_readb(base_seg,base_dest+0x04)); IO_ReadB(crt_reg+6); // attr registers for (ct=0; ct<0x10; ct++) { IO_WriteB(0x3c0,ct); IO_WriteB(0x3c0,real_readb(base_seg,base_dest+0x23+ct)); } IO_WriteB(0x3c4,real_readb(base_seg,base_dest+0x00)); IO_WriteB(0x3d4,real_readb(base_seg,base_dest+0x01)); IO_WriteB(0x3ce,real_readb(base_seg,base_dest+0x02)); IO_ReadB(crt_reg+6); IO_WriteB(0x3c0,real_readb(base_seg,base_dest+0x03)); } if (state&2) { base_dest=real_readw(base_seg,RealOff(buffer)+2); mem_writeb(0x410,(mem_readb(0x410)&0xcf) | real_readb(base_seg,base_dest+0x00)); for (ct=0; ct<0x1e; ct++) { mem_writeb(0x449+ct,real_readb(base_seg,base_dest+0x01+ct)); } for (ct=0; ct<0x07; ct++) { mem_writeb(0x484+ct,real_readb(base_seg,base_dest+0x1f+ct)); } mem_writed(0x48a,real_readd(base_seg,base_dest+0x26)); mem_writed(0x14,real_readd(base_seg,base_dest+0x2a)); // int 5 mem_writed(0x74,real_readd(base_seg,base_dest+0x2e)); // int 1d mem_writed(0x7c,real_readd(base_seg,base_dest+0x32)); // int 1f mem_writed(0x10c,real_readd(base_seg,base_dest+0x36)); // int 43 } if (state&4) { base_dest=real_readw(base_seg,RealOff(buffer)+4); Bit16u crt_reg=real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); IO_WriteB(0x3c6,real_readb(base_seg,base_dest+0x002)); for (ct=0; ct<0x100; ct++) { IO_WriteB(0x3c8,ct); IO_WriteB(0x3c9,real_readb(base_seg,base_dest+0x003+ct*3+0)); IO_WriteB(0x3c9,real_readb(base_seg,base_dest+0x003+ct*3+1)); IO_WriteB(0x3c9,real_readb(base_seg,base_dest+0x003+ct*3+2)); } IO_ReadB(crt_reg+6); IO_WriteB(0x3c0,0x14); IO_WriteB(0x3c0,real_readb(base_seg,base_dest+0x303)); Bitu dac_state=real_readb(base_seg,base_dest+0x000); if (dac_state==0) { IO_WriteB(0x3c8,real_readb(base_seg,base_dest+0x001)); } else { IO_WriteB(0x3c7,real_readb(base_seg,base_dest+0x001)); } } if ((svgaCard==SVGA_S3Trio) && (state&8)) { base_dest=real_readw(base_seg,RealOff(buffer)+6); Bit16u crt_reg=real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); Bitu seq_idx=IO_ReadB(0x3c4); IO_WriteB(0x3c4,0x08); // Bitu seq_8=IO_ReadB(0x3c5); IO_ReadB(0x3c5); // real_writeb(base_seg,base_dest+0x00,IO_ReadB(0x3c5)); IO_WriteB(0x3c5,0x06); // unlock s3-specific registers // sequencer for (ct=0; ct<0x13; ct++) { IO_WriteW(0x3c4,(0x09+ct)+(real_readb(base_seg,base_dest+0x00+ct)<<8)); } IO_WriteB(0x3c4,seq_idx); // Bitu crtc_idx=IO_ReadB(0x3d4); // unlock s3-specific registers IO_WriteW(crt_reg,0x4838); IO_WriteW(crt_reg,0xa539); // crt controller Bitu ct_dest=0x13; for (ct=0; ct<0x40; ct++) { if ((ct==0x4a-0x30) || (ct==0x4b-0x30)) { IO_WriteB(crt_reg,0x45); IO_ReadB(crt_reg+1); IO_WriteB(crt_reg,0x30+ct); IO_WriteB(crt_reg,real_readb(base_seg,base_dest+(ct_dest++))); } else { IO_WriteW(crt_reg,(0x30+ct)+(real_readb(base_seg,base_dest+(ct_dest++))<<8)); } } // mmio /* IO_WriteB(crt_reg,0x40); Bitu sysval1=IO_ReadB(crt_reg+1); IO_WriteB(crt_reg+1,sysval|1); IO_WriteB(crt_reg,0x53); Bitu sysva2=IO_ReadB(crt_reg+1); IO_WriteB(crt_reg+1,sysval2|0x10); real_writew(0xa000,0x8128,0xffff); IO_WriteB(crt_reg,0x40); IO_WriteB(crt_reg,sysval1); IO_WriteB(crt_reg,0x53); IO_WriteB(crt_reg,sysval2); IO_WriteB(crt_reg,crtc_idx); */ } return true; }
static inline Bit16u LoadMw(Bitu off) { if (last_ea86_offset == 0xffff) return (mem_readb(off) | (mem_readb(off-0xffff) << 8)); return mem_readw(off); }