DOSBox-X
|
00001 /* 00002 * Copyright (C) 2002-2020 The DOSBox Team 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License along 00015 * with this program; if not, write to the Free Software Foundation, Inc., 00016 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 */ 00018 00019 00020 #include "dosbox.h" 00021 00022 #include "parport.h" 00023 #include "filelpt.h" 00024 #include "callback.h" 00025 #include "pic.h" 00026 #include "hardware.h" //OpenCaptureFile 00027 #include <stdio.h> 00028 00029 #include "printer_charmaps.h" 00030 00031 CFileLPT::CFileLPT (Bitu nr, Bit8u initIrq, CommandLine* cmd) 00032 :CParallel (cmd, nr,initIrq) { 00033 bool is_file = false; 00034 InstallationSuccessful = false; 00035 fileOpen = false; 00036 controlreg = 0; 00037 timeout = ~0u; 00038 std::string str; 00039 ack = false; 00040 00041 // add a formfeed when closing? 00042 if(cmd->FindStringBegin("addFF",str,false)) addFF = true; 00043 else addFF = false; 00044 00045 // add a formfeed when closing? 00046 if(cmd->FindStringBegin("addLF",str,false)) addLF = true; 00047 else addLF = false; 00048 00049 // find the codepage 00050 unsigned int temp=0; 00051 codepage_ptr = NULL; 00052 if(cmd->FindStringBegin("cp:",str,false)) { 00053 if(sscanf(str.c_str(), "%u",&temp)!=1) { 00054 LOG_MSG("parallel%d: Invalid codepage parameter.",(int)nr+1); 00055 return; 00056 } else { 00057 Bitu i = 0; 00058 while(charmap[i].codepage!=0) { 00059 if(charmap[i].codepage==temp) { 00060 codepage_ptr = charmap[i].map; 00061 break; 00062 } 00063 i++; 00064 } 00065 } 00066 } 00067 temp=0; 00068 00069 if(cmd->FindStringBegin("dev:",str,false)) { 00070 name = str.c_str(); 00071 filetype = FILE_DEV; 00072 } else if(cmd->FindStringBegin("file:",str,false)) { 00073 name = str.c_str(); 00074 filetype = FILE_DEV; 00075 is_file = true; 00076 } else if(cmd->FindStringBegin("append:",str,false)) { 00077 name = str.c_str(); 00078 filetype = FILE_APPEND; 00079 } else filetype = FILE_CAPTURE; 00080 00081 if (cmd->FindStringBegin("timeout:",str,false)) { 00082 if(sscanf(str.c_str(), "%u",&timeout)!=1) { 00083 LOG_MSG("parallel%d: Invalid timeout parameter.",(int)nr+1); 00084 return; 00085 } 00086 } 00087 00088 if (timeout == ~0u) 00089 timeout = is_file ? 0 : 500; 00090 00091 InstallationSuccessful = true; 00092 } 00093 00094 CFileLPT::~CFileLPT () { 00095 // close file 00096 if(fileOpen) 00097 fclose(file); 00098 // remove tick handler 00099 removeEvent(0); 00100 } 00101 00102 bool CFileLPT::OpenFile() { 00103 switch(filetype) { 00104 case FILE_DEV: 00105 file = fopen(name.c_str(),"wb"); 00106 if (file != NULL) setbuf(file,NULL); // disable buffering 00107 break; 00108 case FILE_CAPTURE: 00109 file = OpenCaptureFile("Parallel Port Stream",".prt"); 00110 if (file != NULL) setbuf(file,NULL); // disable buffering 00111 break; 00112 case FILE_APPEND: 00113 file = fopen(name.c_str(),"ab"); 00114 if (file != NULL) setbuf(file,NULL); // disable buffering 00115 break; 00116 } 00117 00118 if(timeout != 0) setEvent(0, (float)(timeout + 1)); 00119 00120 if(file==NULL) { 00121 LOG_MSG("Parallel %d: Failed to open %s",(int)port_nr+1,name.c_str()); 00122 fileOpen = false; 00123 return false; 00124 } else { 00125 fileOpen = true; 00126 return true; 00127 } 00128 } 00129 00130 bool CFileLPT::Putchar(Bit8u val) 00131 { 00132 #if PARALLEL_DEBUG 00133 log_par(dbg_putchar,"putchar 0x%2x",val); 00134 if(dbg_plainputchar) fprintf(debugfp,"%c",val); 00135 #endif 00136 00137 // write to file (or not) 00138 lastUsedTick = PIC_Ticks; 00139 if(!fileOpen) if(!OpenFile()) return false; 00140 00141 if(codepage_ptr!=NULL) { 00142 Bit16u extchar = codepage_ptr[val]; 00143 if(extchar & 0xFF00) fputc((int)((Bit8u)(extchar >> 8)),file); 00144 fputc((Bitu)(extchar & 0xFF),file); 00145 00146 } else fputc((Bitu)val,file); 00147 if(addLF) { 00148 if((lastChar == 0x0d) && (val != 0x0a)) { 00149 fputc(0xa,file); 00150 } 00151 lastChar = val; 00152 } 00153 00154 return true; 00155 } 00156 Bitu CFileLPT::Read_PR() { 00157 return datareg; 00158 } 00159 Bitu CFileLPT::Read_COM() { 00160 return controlreg; 00161 } 00162 Bitu CFileLPT::Read_SR() { 00163 Bit8u status =0x9f; 00164 if(!ack) status |= 0x40; 00165 ack=false; 00166 return status; 00167 } 00168 00169 void CFileLPT::Write_PR(Bitu val) { 00170 datareg = (Bit8u)val; 00171 } 00172 void CFileLPT::Write_CON(Bitu val) { 00173 // init printer if bit 4 is switched on 00174 // ... 00175 autofeed = ((val & 0x02)!=0); // autofeed adds 0xa if 0xd is sent 00176 00177 // data is strobed to the parallel printer on the falling edge of strobe bit 00178 if((!(val&0x1)) && (controlreg & 0x1)) { 00179 Putchar(datareg); 00180 if(autofeed && (datareg==0xd)) Putchar(0xa); 00181 ack = true; 00182 } 00183 controlreg=val&0xF; /* do NOT store bit 5, we do not emulate bidirectional LPT ports, yet */ 00184 } 00185 void CFileLPT::Write_IOSEL(Bitu val) { 00186 (void)val;//UNUSED 00187 // not needed for file printing functionality 00188 } 00189 void CFileLPT::handleUpperEvent(Bit16u type) { 00190 (void)type;//UNUSED 00191 if(fileOpen && timeout != 0) { 00192 if(lastUsedTick + timeout < PIC_Ticks) { 00193 if(addFF) { 00194 fputc(12,file); 00195 } 00196 fclose(file); 00197 lastChar = 0; 00198 fileOpen=false; 00199 LOG_MSG("Parallel %d: File closed.",(int)port_nr+1); 00200 } else { 00201 // Port has been touched in the meantime, try again later 00202 float new_delay = (float)((timeout + 1) - (PIC_Ticks - lastUsedTick)); 00203 setEvent(0, new_delay); 00204 } 00205 } 00206 } 00207