DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/hardware/parport/filelpt.cpp
00001 /*
00002  *  Copyright (C) 2002-2013  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
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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         InstallationSuccessful = false;
00034         fileOpen = false;
00035         controlreg = 0;
00036         std::string str;
00037         ack = false;
00038 
00039         // add a formfeed when closing?
00040         if(cmd->FindStringBegin("addFF",str,false))     addFF = true;
00041         else addFF = false;
00042 
00043         // add a formfeed when closing?
00044         if(cmd->FindStringBegin("addLF",str,false))     addLF = true;
00045         else addLF = false;
00046 
00047         // find the codepage
00048         unsigned int temp=0;
00049         codepage_ptr = NULL;
00050         if(cmd->FindStringBegin("cp:",str,false)) {
00051                 if(sscanf(str.c_str(), "%u",&temp)!=1) {
00052                         LOG_MSG("parallel%d: Invalid codepage parameter.",(int)nr+1);
00053                         return;
00054                 } else {
00055                         Bitu i = 0;
00056                         while(charmap[i].codepage!=0) {
00057                                 if(charmap[i].codepage==temp) {
00058                                         codepage_ptr = charmap[i].map;
00059                                         break;
00060                                 }
00061                                 i++;
00062                         }
00063                 }
00064         }
00065         
00066         temp=0;
00067         if(cmd->FindStringBegin("timeout:",str,false)) {
00068                 if(sscanf(str.c_str(), "%u",&timeout)!=1) {
00069                         LOG_MSG("parallel%d: Invalid timeout parameter.",(int)nr+1);
00070                         return;
00071                 }
00072         } else timeout = 500;
00073 
00074         if(cmd->FindStringBegin("dev:",str,false)) {
00075                 name = str.c_str();
00076                 filetype = FILE_DEV;
00077         } else if(cmd->FindStringBegin("append:",str,false)) {
00078                 name = str.c_str();
00079                 filetype = FILE_APPEND;
00080         } else filetype = FILE_CAPTURE;
00081 
00082         InstallationSuccessful = true;
00083 }
00084 
00085 CFileLPT::~CFileLPT () {
00086         // close file
00087         if(fileOpen)
00088                 fclose(file);
00089         // remove tick handler
00090         removeEvent(0);
00091 }
00092 
00093 bool CFileLPT::OpenFile() {
00094         switch(filetype) {
00095         case FILE_DEV:
00096                 file = fopen(name.c_str(),"wb");
00097                 break;
00098         case FILE_CAPTURE:
00099                 file = OpenCaptureFile("Parallel Port Stream",".prt");
00100                 break;
00101         case FILE_APPEND:
00102                 file = fopen(name.c_str(),"ab");
00103                 break;
00104         }
00105 
00106         if(timeout != 0) setEvent(0, (float)(timeout + 1));
00107 
00108         if(file==NULL) {
00109                 LOG_MSG("Parallel %d: Failed to open %s",(int)port_nr+1,name.c_str());
00110                 fileOpen = false;
00111                 return false;
00112         } else {
00113                 fileOpen = true;
00114                 return true;
00115         }
00116 }
00117 
00118 bool CFileLPT::Putchar(Bit8u val)
00119 {       
00120 #if PARALLEL_DEBUG
00121         log_par(dbg_putchar,"putchar  0x%2x",val);
00122         if(dbg_plainputchar) fprintf(debugfp,"%c",val);
00123 #endif
00124         
00125         // write to file (or not)
00126         lastUsedTick = PIC_Ticks;
00127         if(!fileOpen) if(!OpenFile()) return false;
00128 
00129         if(codepage_ptr!=NULL) {
00130                 Bit16u extchar = codepage_ptr[val];
00131                 if(extchar & 0xFF00) fputc((Bitu)(extchar >> 8),file);
00132                 fputc((Bitu)(extchar & 0xFF),file);
00133 
00134         } else fputc((Bitu)val,file);
00135         if(addLF) {
00136                 if((lastChar == 0x0d) && (val != 0x0a)) {
00137                         fputc(0xa,file);
00138                 }
00139                 lastChar = val;
00140         }
00141 
00142         return true;
00143 }
00144 Bitu CFileLPT::Read_PR() {
00145         return datareg;
00146 }
00147 Bitu CFileLPT::Read_COM() {
00148         return controlreg;
00149 }
00150 Bitu CFileLPT::Read_SR() {
00151         Bit8u status =0x9f;
00152         if(!ack) status |= 0x40;
00153         ack=false;
00154         return status;
00155 }
00156 
00157 void CFileLPT::Write_PR(Bitu val) {
00158         datareg = (Bit8u)val;
00159 }
00160 void CFileLPT::Write_CON(Bitu val) {
00161         // init printer if bit 4 is switched on
00162         // ...
00163         autofeed = ((val & 0x02)!=0); // autofeed adds 0xa if 0xd is sent
00164 
00165         // data is strobed to the parallel printer on the falling edge of strobe bit
00166         if((!(val&0x1)) && (controlreg & 0x1)) {
00167                 Putchar(datareg);
00168                 if(autofeed && (datareg==0xd)) Putchar(0xa);
00169                 ack = true;
00170         }
00171         controlreg=val&0xF; /* do NOT store bit 5, we do not emulate bidirectional LPT ports, yet */
00172 }
00173 void CFileLPT::Write_IOSEL(Bitu val) {
00174     (void)val;//UNUSED
00175         // not needed for file printing functionality
00176 }
00177 void CFileLPT::handleUpperEvent(Bit16u type) {
00178     (void)type;//UNUSED
00179         if(fileOpen) {
00180                 if(lastUsedTick + timeout < PIC_Ticks) {
00181                         if(addFF) {
00182                                 fputc(12,file);
00183                         }
00184                         fclose(file);
00185                         lastChar = 0;
00186                         fileOpen=false;
00187                         LOG_MSG("Parallel %d: File closed.",(int)port_nr+1);
00188                 } else {
00189                         // Port has been touched in the meantime, try again later
00190                         float new_delay = (float)((timeout + 1) - (PIC_Ticks - lastUsedTick));
00191                         setEvent(0, new_delay);
00192                 }
00193         }
00194 }
00195