DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/hardware/parport/filelpt.cpp
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