summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSolomon Peachy <pizza@shaftnet.org>2016-01-27 08:00:02 -0500
committerSolomon Peachy <pizza@shaftnet.org>2016-01-27 08:00:02 -0500
commit46726e1dd2b7e9dc173ab7457a025ca1bc5a28cd (patch)
tree30916f812dfc47e243f55d75a8ea281bff29bb3a
parent624cdf263846d7fc14e4f08d1ef3d0bd3856db1a (diff)
downloadselphy_print-46726e1dd2b7e9dc173ab7457a025ca1bc5a28cd.tar.gz
selphy_print-46726e1dd2b7e9dc173ab7457a025ca1bc5a28cd.tar.bz2
selphy_print-46726e1dd2b7e9dc173ab7457a025ca1bc5a28cd.zip
s6145: Bundle libS6145ImageReProcess!
Yep, the s6145 is now fully usable with Free Software!
-rw-r--r--README46
-rw-r--r--lib6145/Makefile40
-rw-r--r--lib6145/libS6145ImageReProcess.c1791
3 files changed, 1862 insertions, 15 deletions
diff --git a/README b/README
index a5e438d..141fd4a 100644
--- a/README
+++ b/README
@@ -381,21 +381,40 @@
*** VERY IMPORTANT ***
- The Sinfonia CHC-S6145 printer (and its siblings) require the input
- data to be transformed using a proprietary library in order to generate
- usable output.
+ In order to generate usable output, the Sinfonia CHC-S6145 printer
+ (and its siblings) require the input data to be transformed using
+ specific image processing algorithms.
- This library (libS6145ImageProcess) was provided to the authors of
- selphy_print in binary form, without redistribution permissions. It was
- also only made available for x86 and x86_64 platdorms.
+ The library that implements this processing is dynamically loaded
+ at runtime. There are three options:
- Work is under way to reverse-engineer and re-implement this library.
- the replacement is called libS6145ImageReProcess, and is not yet
- publicly released.
+ * libS6145ImageProcess -- Supported by Sinfonia, this is a proprietary
+ library only available for x86 and x86_64 linux targets. It can be
+ obtained by politely contacting your local Sinfonia distributor.
- The backend will automatically attempt to load one of these libraries
- at runtime. If neither is available, it will default to a very crude
- algorithm that generates poor results not suable for photographic output.
+ If you have the appropriate permission fron Sinfonia and its
+ technical and legal limitations are acceptible to you, we recommend
+ you use the supported libS6145ImageProcess library, as it will
+ generate the highest quality output.
+
+ * libS6145ImageReProcess -- GPL'd re-implementation of the Sinfonia
+ algorithms, available as source. It is a drop-in replacement
+ that appears to generate identical output to the proprietary
+ Sinfonia library.
+
+ DISCLAIMER: Sinfonia Inc was not involved in the creation of
+ libS6145ImageReProcess and is not responsible in any way for any
+ deficiencies in its output. They will provide no support if it is
+ used.
+
+ Do *NOT* contact Sinfonia for support if you are using
+ libS6146ImageReProcess.
+
+ (Please see the full disclaimer in libS6145ImageReProcess.c)
+
+ * If neither of the above libraries are found, the backend will
+ fall back to a very crude algorithm that generates low-quality
+ results not suitable for photographic output
As selphy_print is released under the terms of the GPL, it cannot
normally be combined with proprietary libraries.
@@ -405,9 +424,6 @@
it with the libS6145ImageProcess library. For the full text of this
license exception, please see the header of backend_shinkos6145.c
- If you own a S6145 printer, libS6145ImageProcess may be obtained by
- politely contacting your local Sinfonia distributor.
-
Valid commands:
-c filename Query User tone curve from flash [1]
diff --git a/lib6145/Makefile b/lib6145/Makefile
new file mode 100644
index 0000000..3a5cb1b
--- /dev/null
+++ b/lib6145/Makefile
@@ -0,0 +1,40 @@
+# Basic stuff
+LIBS6145_NAME ?= S6145ImageReProcess
+
+# Destination directories
+DESTDIR ?=
+LIBDIR ?= $(DESTDIR)/usr/local/lib
+
+# Tools
+CC ?= $(CROSS_COMPILE)gcc
+CPPCHECK ?= cppcheck
+MKDIR ?= mkdir
+INSTALL ?= install
+RM ?= rm
+
+# Flags
+CFLAGS += -Wall -Wextra -g -Os -std=c99 -fPIC --no-strict-overflow # -Wconversion
+#LDFLAGS +=
+#CPPFLAGS +=
+
+# Build stuff
+SOURCES = libS6145ImageReProcess.c
+
+# And now the rules!
+.PHONY: clean all install cppcheck
+
+all: lib$(LIBS6145_NAME).so
+
+cppcheck:
+ $(CPPCHECK) -q -v --std=c99 --enable=all -I/usr/include $(CPPFLAGS) $(SOURCES)
+
+install:
+ $(INSTALL) -o root -m 755 lib$(LIBS6145_NAME).so $(LIBDIR)
+clean:
+ $(RM) -f lib$(LIBS6145_NAME).so *.o
+
+lib$(LIBS6145_NAME).so: $(SOURCES:.c=.o)
+ $(CC) $(LDFLAGS) -g -shared -o $@ $^
+
+%.o: %.c
+ $(CC) -c $(CFLAGS) -o $@ $<
diff --git a/lib6145/libS6145ImageReProcess.c b/lib6145/libS6145ImageReProcess.c
new file mode 100644
index 0000000..ebc2279
--- /dev/null
+++ b/lib6145/libS6145ImageReProcess.c
@@ -0,0 +1,1791 @@
+/*
+ libS6145ImageReProcess -- Re-implemented Image Processing library for
+ the Sinfonia CHC-S6145 printer family
+
+ Copyright (c) 2015-2016 Solomon Peachy <pizza@shaftnet.org>
+
+ ** ** ** ** Do NOT contact Sinfonia about this library! ** ** ** **
+
+ This is intended to be a drop-in replacement for Sinfonia's proprietary
+ libS6145ImageProcess library, which is necessary in order to utilize
+ their CHC-S6145 printer family.
+
+ Sinfonia Inc was not involved in the creation of this library, and
+ is not responsible in any way for the library or any deficiencies in
+ its output. They will provide no support if it is used.
+
+ If you have the appropriate permission fron Sinfonia, we recommend
+ you use their official libS6145ImageProcess library instead, as it
+ will generate the highest quality output. However, it is only
+ available for x86/x86_64 targets on Linux. Please contact your local
+ Sinfonia distributor to obtain the official library.
+
+ ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ [http://www.gnu.org/licenses/gpl-3.0.html]
+
+*/
+
+//#define S6145_UNUSED
+
+#define LIB_VERSION "0.4"
+
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <math.h>
+
+//-------------------------------------------------------------------------
+// Structures
+
+struct tankParam {
+ int32_t trdTankSize;
+ int32_t sndTankSize;
+ int32_t fstTankSize;
+ int32_t trdTankIniEnergy;
+ int32_t sndTankIniEnergy;
+ int32_t fstTankIniEnergy;
+ int32_t trdTrdConductivity;
+ int32_t sndSndConductivity;
+ int32_t fstFstConductivity;
+ int32_t outTrdConductivity;
+ int32_t trdSndConductivity;
+ int32_t sndFstConductivity;
+ int32_t fstOutConductivity;
+ int32_t plusMaxEnergy;
+ int32_t minusMaxEnergy;
+ int32_t plusMaxEnergyPreRead;
+ int32_t minusMaxEnergyPreRead;
+ int32_t preReadLevelDiff;
+ int32_t rsvd[14]; // null or unused?
+} __attribute__((packed));
+
+struct imageCorrParam {
+ uint16_t pulseTransTable_Y[256]; // @0
+ uint16_t pulseTransTable_M[256]; // @512
+ uint16_t pulseTransTable_C[256]; // @1024
+ uint16_t pulseTransTable_O[256]; // @1536
+
+ uint16_t lineHistCoefTable_Y[256]; // @2048
+ uint16_t lineHistCoefTable_M[256]; // @2560
+ uint16_t lineHistCoefTable_C[256]; // @3072
+ uint16_t lineHistCoefTable_O[256]; // @3584
+
+ uint16_t lineCorrectEnvA_Y; // @4096
+ uint16_t lineCorrectEnvA_M; // @4098
+ uint16_t lineCorrectEnvA_C; // @4100
+ uint16_t lineCorrectEnvA_O; // @4102
+
+ uint16_t lineCorrectEnvB_Y; // @4104
+ uint16_t lineCorrectEnvB_M; // @4106
+ uint16_t lineCorrectEnvB_C; // @4108
+ uint16_t lineCorrectEnvB_O; // @4110
+
+ uint16_t lineCorrectEnvC_Y; // @4112
+ uint16_t lineCorrectEnvC_M; // @4114
+ uint16_t lineCorrectEnvC_C; // @4116
+ uint16_t lineCorrectEnvC_O; // @4118
+
+ uint32_t lineCorrectSlice_Y; // @4120
+ uint32_t lineCorrectSlice_M; // @4124
+ uint32_t lineCorrectSlice_C; // @4128
+ uint32_t lineCorrectSlice_O; // @4132
+
+ uint32_t lineCorrectSlice1Line_Y; // @4136
+ uint32_t lineCorrectSlice1Line_M; // @4140
+ uint32_t lineCorrectSlice1Line_C; // @4144
+ uint32_t lineCorrectSlice1Line_O; // @4148
+
+ int32_t lineCorrectPulseMax_Y; // @4152
+ int32_t lineCorrectPulseMax_M; // @4156
+ int32_t lineCorrectPulseMax_C; // @4160
+ int32_t lineCorrectPulseMax_O; // @4164
+
+ struct tankParam tableTankParam_Y; // @4168
+ struct tankParam tableTankParam_M; // @4296
+ struct tankParam tableTankParam_C; // @4424
+ struct tankParam tableTankParam_O; // @4552
+
+ uint16_t tankPlusMaxEnergyTable_Y[256]; // @4680
+ uint16_t tankPlusMaxEnergyTable_M[256]; // @5192
+ uint16_t tankPlusMaxEnergyTable_C[256]; // @5704
+ uint16_t tankPlusMaxEnergyTable_O[256]; // @6216
+
+ uint16_t tankMinusMaxEnergy_Y[256]; // @6728
+ uint16_t tankMinusMaxEnergy_M[256]; // @7240
+ uint16_t tankMinusMaxEnergy_C[256]; // @7752
+ uint16_t tankMinusMaxEnergy_O[256]; // @8264
+
+ uint16_t printMaxPulse_Y; // @8776
+ uint16_t printMaxPulse_M; // @8778
+ uint16_t printMaxPulse_C; // @8780
+ uint16_t printMaxPulse_O; // @8782
+
+ uint16_t mtfWeightH_Y; // @8784
+ uint16_t mtfWeightH_M; // @8786
+ uint16_t mtfWeightH_C; // @8788
+ uint16_t mtfWeightH_O; // @8790
+
+ uint16_t mtfWeightV_Y; // @8792
+ uint16_t mtfWeightV_M; // @8794
+ uint16_t mtfWeightV_C; // @8796
+ uint16_t mtfWeightV_O; // @8798
+
+ uint16_t mtfSlice_Y; // @8800
+ uint16_t mtfSlice_M; // @8802
+ uint16_t mtfSlice_C; // @8804
+ uint16_t mtfSlice_O; // @8806
+
+ uint16_t val_1; // @8808 // 1 enables linepreprintprocess
+ uint16_t val_2; // @8810 // 1 enables ctankprocess
+ uint16_t printOpLevel; // @8812
+ uint16_t matteMode; // @8814 // 1 for matte
+
+ uint16_t randomBase[4]; // @8816 [use lower byte of each]
+
+ uint16_t matteSize; // @8824
+ uint16_t matteGloss; // @8826
+ uint16_t matteDeglossBlk; // @8828
+ uint16_t matteDeglossWht; // @8830
+
+ int16_t printSideOffset; // @8832
+ uint16_t headDots; // @8834 [always 0x0780, ie 1920. print width
+
+ uint16_t SideEdgeCoefTable[128]; // @8836
+ uint8_t rsvd_2[256]; // @9092, null?
+ uint16_t SideEdgeLvCoefTable[256]; // @9348
+ uint8_t rsvd_3[2572]; // @9860, null?
+
+ /* User-supplied data */
+ uint16_t width; // @12432
+ uint16_t height; // @12434
+ uint8_t pad[3948]; // @12436, null.
+} __attribute__((packed)); /* 16384 bytes */
+
+//-------------------------------------------------------------------------
+// Function declarations
+
+#define ASSERT(__COND, __TXT) if ((!__COND)) { printf(__TXT " @ %d\n", __LINE__); exit(1); }
+
+static void SetTableData(void *src, void *dest, uint16_t words);
+static int32_t CheckPrintParam(uint8_t *corrdata);
+static uint16_t LinePrintCalcBit(uint16_t val);
+
+static void GetInfo(void);
+static void Global_Init(void);
+static void SetTableColor(uint8_t plane);
+static void LinePrintPreProcess(void);
+static void CTankResetParameter(int32_t *params);
+static void CTankResetTank(void);
+static void PagePrintPreProcess(void);
+static void PagePrintProcess(void);
+static void CTankProcess(void);
+static void SendData(void);
+static void PulseTrans(void);
+static void CTankUpdateTankVolumeInterDot(uint8_t tank);
+static void CTankUpdateTankVolumeInterRay(void);
+static void CTankHoseiPreread(void);
+static void CTankHosei(void);
+static void LineCorrection(void);
+
+static void PulseTransPreReadOP(void);
+static void PulseTransPreReadYMC(void);
+static void CTankProcessPreRead(void);
+static void CTankProcessPreReadDummy(void);
+static void RecieveDataOP_GLOSS(void);
+static void RecieveDataYMC(void);
+static void RecieveDataOP_MATTE(void);
+
+#ifdef S6145_UNUSED
+static void SetTable(void);
+static void ImageLevelAddition(void);
+static void ImageLevelAdditionEx(uint32_t *a1, uint32_t a2, int32_t a3);
+static void RecieveDataOP_Post(void);
+static void RecieveDataYMC_Post(void);
+static void RecieveDataOPLevel_Post(void);
+static void RecieveDataOPMatte_Post(void);
+static void SideEdgeCorrection(void);
+static void LeadEdgeCorrection(void);
+#endif
+
+//-------------------------------------------------------------------------
+// Endian Manipulation macros
+
+#if (__BYTE_ORDER == __LITTLE_ENDIAN)
+#define le32_to_cpu(__x) __x
+#define le16_to_cpu(__x) __x
+#define be16_to_cpu(__x) ntohs(__x)
+#define be32_to_cpu(__x) ntohl(__x)
+#else
+#define le32_to_cpu(x) \
+ ({ \
+ uint32_t __x = (x); \
+ ((uint32_t)( \
+ (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
+ (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
+ (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
+ (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
+ })
+#define le16_to_cpu(x) \
+ ({ \
+ uint16_t __x = (x); \
+ ((uint16_t)( \
+ (((uint16_t)(__x) & (uint16_t)0x00ff) << 8) | \
+ (((uint16_t)(__x) & (uint16_t)0xff00) >> 8))); \
+ })
+#define be32_to_cpu(__x) __x
+#define be16_to_cpu(__x) __x
+#endif
+
+#define cpu_to_le16 le16_to_cpu
+#define cpu_to_le32 le32_to_cpu
+#define cpu_to_be16 be16_to_cpu
+#define cpu_to_be32 be32_to_cpu
+
+//-------------------------------------------------------------------------
+// Data declarations
+
+#define BUF_SIZE 2048
+#define TANK_SIZE 2052
+#define MAX_PULSE 1023
+#define MIN_ROWS 100
+#define MIN_COLS 100
+#define MAX_ROWS 2492
+#define MAX_COLS 1844
+
+static void (*g_pfRecieveData)(void);
+static void (*g_pfPulseTransPreRead)(void);
+static void (*g_pfTankProcessPreRead)(void);
+
+static uint8_t g_pusInLineBuf0[BUF_SIZE];
+static uint8_t g_pusInLineBuf1[BUF_SIZE];
+static uint8_t g_pusInLineBuf2[BUF_SIZE];
+static uint8_t g_pusInLineBuf3[BUF_SIZE];
+static uint8_t g_pusInLineBuf4[BUF_SIZE];
+static uint8_t g_pusInLineBuf5[BUF_SIZE];
+static uint8_t g_pusInLineBuf6[BUF_SIZE];
+static uint8_t g_pusInLineBuf7[BUF_SIZE];
+static uint8_t g_pusInLineBuf8[BUF_SIZE];
+static uint8_t g_pusInLineBuf9[BUF_SIZE];
+static uint8_t g_pusInLineBufA[BUF_SIZE];
+
+static uint16_t g_pusOutLineBuf1[BUF_SIZE];
+static uint16_t *g_pusOutLineBufTab[2]; // XXX actually [1]
+
+static uint8_t *g_pusPreReadLineBufTab[12]; // XXX actually [11]
+static uint8_t *g_pusPulseTransLineBufTab[4];
+
+static uint16_t g_pusPreReadOutLineBuf[BUF_SIZE];
+
+static int32_t m_piTrdTankArray[TANK_SIZE];
+static int32_t m_piFstTankArray[TANK_SIZE];
+static int32_t m_piSndTankArray[TANK_SIZE];
+
+static int16_t g_psMtfPreCalcTable[512];
+static uint16_t g_pusTankMinusMaxEnegyTable[256];
+static uint16_t g_pusTankPlusMaxEnegyTable[256];
+static uint16_t g_pusPulseTransTable[256];
+static uint16_t g_pusLineHistCoefTable[256];
+
+static int32_t g_piTankParam[128]; // should be struct tankParam[4]
+static int32_t g_pulRandomTable[32]; // should be u32
+
+static uint8_t *g_pucInputImageBuf;
+struct imageCorrParam *g_pSPrintParam;
+static uint16_t *g_pusOutputImageBuf;
+
+static uint8_t g_ucRandomBaseLevel[4];
+static int16_t g_sPrintSideOffset;
+static uint16_t g_usHeadDots;
+static int32_t g_iLineCorrectPulse;
+static uint32_t g_uiMtfSlice; // really u16?
+static uint32_t g_uiMtfWeightV; // really u16?
+static uint32_t g_uiMtfWeightH; // really u16?
+static uint16_t g_usLineCorrect_Env_A;
+static uint16_t g_usLineCorrect_Env_B;
+static uint16_t g_usLineCorrect_Env_C;
+
+static uint32_t g_uiOutputImageIndex;
+static uint32_t g_uiInputImageIndex;
+
+static int32_t g_iMaxPulseValue;
+static uint32_t g_uiMaxPulseBit;
+
+static uint16_t g_usPrintMaxPulse;
+static uint16_t g_usPrintOpLevel;
+static uint16_t g_usMatteSize;
+static uint32_t g_uiLineCorrectSlice;
+static uint32_t g_uiLineCorrectSlice1Line;
+static uint16_t g_usPrintSizeHeight;
+static uint32_t g_uiLineCorrectBase1Line;
+static uint32_t g_uiLineCorrectSum;
+static uint32_t g_uiLineCorrectBase;
+static int16_t g_sCorrectSw;
+static uint16_t g_usMatteMode;
+static int32_t g_iLineCorrectPulseMax;
+static uint16_t g_usSheetSizeWidth;
+static uint16_t g_usPrintSizeWidth;
+static uint16_t g_usPrintColor;
+static uint32_t g_uiSendToHeadCounter;
+static uint32_t g_uiLineCopyCounter;
+
+static int32_t m_iTrdTankSize;
+static int32_t m_iTrdSndConductivity;
+static int32_t m_iSndTankSize;
+static int32_t m_iTankKeisuSndFstDivFst;
+static int32_t m_iSndSndConductivity;
+static int32_t m_iTrdTrdConductivity;
+static int32_t m_iTankKeisuTrdSndDivSnd;
+static int32_t m_iTankKeisuTrdSndDivTrd;
+static int32_t m_iSndFstConductivity;
+static int32_t m_iFstTankSize;
+static int32_t m_iTrdTankIniEnergy;
+static int32_t m_iFstTankIniEnergy;
+static int32_t m_iTankKeisuSndFstDivSnd;
+static int32_t m_iSndTankIniEnergy;
+static int32_t m_iPreReadLevelDiff;
+static int32_t m_iMinusMaxEnergyPreRead;
+static int32_t m_iOutTrdConductivity;
+static int32_t m_iFstOutConductivity;
+static int32_t m_iFstFstConductivity;
+static int32_t m_iTankKeisuFstOutDivFst;
+static int32_t m_iTankKeisuOutTrdDivTrd;
+
+#ifdef S6145_UNUSED
+
+static void (*g_pfRecieveData_Post)(void); /* all users are no-ops */
+
+/* Set but never referenced */
+static uint32_t g_uiDataTransCounter;
+static uint32_t g_uiTudenLineCounter;
+
+/* Only ever set to 0 */
+static uint16_t g_usPrintDummyLevel;
+static uint16_t g_usPrintDummyLine;
+static uint16_t g_usRearDummyPrintLine;
+static uint16_t g_usRearDeleteLine;
+
+/* Appear unused */
+static uint16_t g_usCancelCheckLinesForPRec;
+
+static uint16_t g_usPrintSizeLHeight;
+static uint16_t g_usPrintSizeLWidth;
+
+static uint16_t g_pusSideEdgeLvCoefTable[256];
+static uint16_t g_pusSideEdgeCoefTable[128];
+static int32_t g_iLeadEdgeCorrectPulse;
+
+static int32_t m_iMinusMaxEnergy;
+static int32_t m_iPlusMaxEnergy;
+static int32_t m_iPlusMaxEnergyPreRead;
+
+static uint16_t g_usCenterHeadToColSen;
+static uint16_t g_usThearmEnv;
+static uint16_t g_usThearmHead;
+static uint16_t g_usMatteGloss;
+static uint16_t g_usMatteDeglossBlk;
+static uint16_t g_usMatteDeglossWht;
+static uint16_t g_usPrintOffsetWidth;
+static uint16_t g_usCancelCheckDotsForPRec;
+static uint32_t g_uiOffsetCancelCheckPRec;
+static uint32_t g_uiLevelAveCounter;
+static uint32_t g_uiLevelAveCounter2;
+static uint32_t g_uiLevelAveAddtion;
+static uint32_t g_uiLevelAveAddtion2;
+static uint32_t g_uiDummyPrintCounter;
+static uint16_t g_usRearDummyPrintLevel;
+static uint16_t g_usLastPrintSizeHeight;
+static uint16_t g_usLastPrintSizeWidth;
+static uint16_t g_usLastSheetSizeWidth;
+
+uint16_t g_pusOutLineBuf2[BUF_SIZE];
+uint16_t *g_pusLamiCompInLineBufTab[4];
+#endif
+
+/* **************************** */
+
+int ImageAvrCalc(uint8_t *input, uint16_t cols, uint16_t rows, uint8_t *avg)
+{
+ uint64_t sum;
+ uint32_t offset;
+ uint32_t planesize;
+ uint32_t j;
+ uint8_t plane;
+
+ if ( !input )
+ return 1;
+ if ( !avg )
+ return 4;
+ if ( cols <= MIN_COLS || cols > MAX_COLS )
+ return 2;
+ if ( rows <= MIN_COLS || cols > MAX_ROWS )
+ return 3;
+
+ planesize = rows * cols;
+ offset = 0;
+
+ for ( plane = 0; plane < 3; plane++ )
+ {
+ sum = 0;
+ for ( j = 0; j < planesize; ++j )
+ sum += input[offset++];
+ avg[plane] = sum / planesize;
+ }
+
+ return 0;
+}
+
+int ImageProcessing(unsigned char *in, unsigned short *out, void *corrdata)
+{
+ uint8_t i;
+
+ fprintf(stderr, "INFO: libS6145ImageReProcess version '%s'\n", LIB_VERSION);
+ fprintf(stderr, "INFO: Copyright (c) 2015-2016 Solomon Peachy\n");
+ fprintf(stderr, "INFO: This free software comes with ABSOLUTELY NO WARRANTY!\n");
+ fprintf(stderr, "INFO: Licensed under the GNU GPL.\n");
+ fprintf(stderr, "INFO: *** This code is NOT supported or endorsed by Sinfonia! ***\n");
+
+ if (!in)
+ return 1;
+ if (!out)
+ return 2;
+ if (!corrdata)
+ return 3;
+
+ g_pucInputImageBuf = in;
+ g_pusOutputImageBuf = out;
+ g_pSPrintParam = (struct imageCorrParam *) corrdata;
+
+ i = CheckPrintParam(corrdata);
+ if (i)
+ return i;
+
+ Global_Init();
+#ifdef S6145_UNUSED
+ SetTable();
+#endif
+
+ for ( i = 0; i < 4; i++ ) { /* Full YMCO */
+ int32_t lines;
+ SetTableColor(i);
+ LinePrintPreProcess();
+ PagePrintPreProcess();
+ lines = g_usPrintSizeHeight;
+ while ( lines-- ) {
+ PagePrintProcess();
+ }
+ g_usPrintColor++;
+ }
+
+ return 0;
+}
+
+/* **************************** */
+
+static void SetTableData(void *src, void *dest, uint16_t words)
+{
+ uint16_t *in = src;
+ uint16_t *out = dest;
+ while (words--) {
+ out[words] = le16_to_cpu(in[words]);
+ }
+}
+
+static void GetInfo(void)
+{
+ uint32_t tmp;
+
+#ifdef S6145_UNUSED
+ g_usLastPrintSizeWidth = g_usPrintSizeWidth;
+ g_usLastPrintSizeHeight = g_usPrintSizeHeight;
+ g_usLastSheetSizeWidth = g_usSheetSizeWidth;
+ g_usPrintOffsetWidth = 0;
+#endif
+
+ g_usPrintSizeWidth = le16_to_cpu(g_pSPrintParam->width);
+ g_usPrintSizeHeight = le16_to_cpu(g_pSPrintParam->height);
+ g_usSheetSizeWidth = g_usPrintSizeWidth;
+
+ g_sPrintSideOffset = le16_to_cpu(g_pSPrintParam->printSideOffset);
+
+ if ( g_pSPrintParam->val_1 )
+ g_sCorrectSw |= 1;
+ if ( g_pSPrintParam->val_2 )
+ g_sCorrectSw |= 2;
+
+ g_usPrintOpLevel = le16_to_cpu(g_pSPrintParam->printOpLevel);
+
+ tmp = le16_to_cpu(g_pSPrintParam->randomBase[0]);
+ g_ucRandomBaseLevel[0] = tmp & 0xff;
+ tmp = le16_to_cpu(g_pSPrintParam->randomBase[1]);
+ g_ucRandomBaseLevel[1] = tmp & 0xff;
+ tmp = le16_to_cpu(g_pSPrintParam->randomBase[2]);
+ g_ucRandomBaseLevel[2] = tmp & 0xff;
+ tmp = le16_to_cpu(g_pSPrintParam->randomBase[3]);
+ g_ucRandomBaseLevel[3] = tmp & 0xff;
+
+ g_usMatteSize = le16_to_cpu(g_pSPrintParam->matteSize);
+ g_usMatteMode = le16_to_cpu(g_pSPrintParam->matteMode);
+
+#ifdef S6145_UNUSED
+ g_usMatteGloss = le16_to_cpu(g_pSPrintParam->matteGloss);
+ g_usMatteDeglossBlk = le16_to_cpu(g_pSPrintParam->matteDeglossBlk);
+ g_usMatteDeglossWht = le16_to_cpu(g_pSPrintParam->matteDeglossWht);
+#endif
+
+ switch (g_usPrintColor) {
+ case 0:
+ g_usPrintMaxPulse = le16_to_cpu(g_pSPrintParam->printMaxPulse_Y);
+ g_uiMtfWeightH = le16_to_cpu(g_pSPrintParam->mtfWeightH_Y);
+ g_uiMtfWeightV = le16_to_cpu(g_pSPrintParam->mtfWeightV_Y);
+ g_uiMtfSlice = le16_to_cpu(g_pSPrintParam->mtfSlice_Y);
+ g_usLineCorrect_Env_A = le16_to_cpu(g_pSPrintParam->lineCorrectEnvA_Y);
+ g_usLineCorrect_Env_B = le16_to_cpu(g_pSPrintParam->lineCorrectEnvB_Y);
+ g_usLineCorrect_Env_C = le16_to_cpu(g_pSPrintParam->lineCorrectEnvC_Y);
+ g_uiLineCorrectSlice = le32_to_cpu(g_pSPrintParam->lineCorrectSlice_Y);
+ g_uiLineCorrectSlice1Line = le32_to_cpu(g_pSPrintParam->lineCorrectSlice1Line_Y);
+ g_iLineCorrectPulseMax = le32_to_cpu(g_pSPrintParam->lineCorrectPulseMax_Y);
+ break;
+ case 1:
+ g_usPrintMaxPulse = le16_to_cpu(g_pSPrintParam->printMaxPulse_M);
+ g_uiMtfWeightH = le16_to_cpu(g_pSPrintParam->mtfWeightH_M);
+ g_uiMtfWeightV = le16_to_cpu(g_pSPrintParam->mtfWeightV_M);
+ g_uiMtfSlice = le16_to_cpu(g_pSPrintParam->mtfSlice_M);
+ g_usLineCorrect_Env_A = le16_to_cpu(g_pSPrintParam->lineCorrectEnvA_M);
+ g_usLineCorrect_Env_B = le16_to_cpu(g_pSPrintParam->lineCorrectEnvB_M);
+ g_usLineCorrect_Env_C = le16_to_cpu(g_pSPrintParam->lineCorrectEnvC_M);
+ g_uiLineCorrectSlice = le32_to_cpu(g_pSPrintParam->lineCorrectSlice_M);
+ g_uiLineCorrectSlice1Line = le32_to_cpu(g_pSPrintParam->lineCorrectSlice1Line_M);
+ g_iLineCorrectPulseMax = le32_to_cpu(g_pSPrintParam->lineCorrectPulseMax_M);
+ break;
+ case 2:
+ g_usPrintMaxPulse = le16_to_cpu(g_pSPrintParam->printMaxPulse_C);
+ g_uiMtfWeightH = le16_to_cpu(g_pSPrintParam->mtfWeightH_C);
+ g_uiMtfWeightV = le16_to_cpu(g_pSPrintParam->mtfWeightV_C);
+ g_uiMtfSlice = le16_to_cpu(g_pSPrintParam->mtfSlice_C);
+ g_usLineCorrect_Env_A = le16_to_cpu(g_pSPrintParam->lineCorrectEnvA_C);
+ g_usLineCorrect_Env_B = le16_to_cpu(g_pSPrintParam->lineCorrectEnvB_C);
+ g_usLineCorrect_Env_C = le16_to_cpu(g_pSPrintParam->lineCorrectEnvC_C);
+ g_uiLineCorrectSlice = le32_to_cpu(g_pSPrintParam->lineCorrectSlice_C);
+ g_uiLineCorrectSlice1Line = le32_to_cpu(g_pSPrintParam->lineCorrectSlice1Line_C);
+ g_iLineCorrectPulseMax = le32_to_cpu(g_pSPrintParam->lineCorrectPulseMax_C);
+ break;
+ case 3:
+ g_usPrintMaxPulse = le16_to_cpu(g_pSPrintParam->printMaxPulse_O);
+ g_uiMtfWeightH = le16_to_cpu(g_pSPrintParam->mtfWeightH_O);
+ g_uiMtfWeightV = le16_to_cpu(g_pSPrintParam->mtfWeightV_O);
+ g_uiMtfSlice = le16_to_cpu(g_pSPrintParam->mtfSlice_O);;
+ g_usLineCorrect_Env_A = le16_to_cpu(g_pSPrintParam->lineCorrectEnvA_O);
+ g_usLineCorrect_Env_B = le16_to_cpu(g_pSPrintParam->lineCorrectEnvB_O);
+ g_usLineCorrect_Env_C = le16_to_cpu(g_pSPrintParam->lineCorrectEnvC_O);
+ g_uiLineCorrectSlice = le32_to_cpu(g_pSPrintParam->lineCorrectSlice_O);
+ g_uiLineCorrectSlice1Line = le32_to_cpu(g_pSPrintParam->lineCorrectSlice1Line_O);
+ g_iLineCorrectPulseMax = le32_to_cpu(g_pSPrintParam->lineCorrectPulseMax_O);
+ break;
+ default:
+ printf("ERROR: bad g_usPrintColor %d\n", g_usPrintColor);
+ break;
+ }
+
+ g_usHeadDots = le16_to_cpu(g_pSPrintParam->headDots);
+}
+
+static void Global_Init(void)
+{
+ g_usPrintColor = 0;
+ g_usPrintSizeWidth = 0;
+ g_usPrintSizeHeight = 0;
+ g_usSheetSizeWidth = 0;
+ g_sPrintSideOffset = 0;
+ g_sCorrectSw = 0;
+ g_usPrintOpLevel = 0;
+ g_uiMtfWeightH = 0;
+ g_uiMtfWeightV = 0;
+ g_uiMtfSlice = 0;
+ g_usPrintMaxPulse = MAX_PULSE;
+ g_usMatteMode = 0;
+ g_usLineCorrect_Env_A = 0;
+ g_usLineCorrect_Env_B = 0;
+ g_usLineCorrect_Env_C = 0;
+ g_uiLineCorrectSum = 0;
+ g_uiLineCorrectBase = 0;
+ g_uiLineCorrectBase1Line = 0;
+ g_iLineCorrectPulse = 0;
+ g_iLineCorrectPulseMax = MAX_PULSE;
+ g_pulRandomTable[0] = 3;
+ g_pulRandomTable[1] = -1708027847;
+ g_pulRandomTable[2] = 853131300;
+ g_pulRandomTable[3] = -1687801470;
+ g_pulRandomTable[4] = 1570894658;
+ g_pulRandomTable[5] = -566525472;
+ g_pulRandomTable[6] = -552964171;
+ g_pulRandomTable[7] = -251413502;
+ g_pulRandomTable[8] = 1223901435;
+ g_pulRandomTable[9] = 1950999915;
+ g_pulRandomTable[10] = -1095640144;
+ g_pulRandomTable[11] = -1420011240;
+ g_pulRandomTable[12] = -1805298435;
+ g_pulRandomTable[13] = -1943115761;
+ g_pulRandomTable[14] = -348292705;
+ g_pulRandomTable[15] = -1323376457;
+ g_pulRandomTable[16] = 759393158;
+ g_pulRandomTable[17] = -630772182;
+ g_pulRandomTable[18] = 361286280;
+ g_pulRandomTable[19] = -479628451;
+ g_pulRandomTable[20] = -1873857033;
+ g_pulRandomTable[21] = -686452778;
+ g_pulRandomTable[22] = 1873211473;
+ g_pulRandomTable[23] = 1634626454;
+ g_pulRandomTable[24] = -1399525412;
+ g_pulRandomTable[25] = 910245779;
+ g_pulRandomTable[26] = -970800488;
+ g_pulRandomTable[27] = -173790536;
+ g_pulRandomTable[28] = -1970743429;
+ g_pulRandomTable[29] = -173171442;
+ g_pulRandomTable[30] = -1986452981;
+ g_pulRandomTable[31] = 670779321;
+ g_uiInputImageIndex = 0;
+ g_uiOutputImageIndex = 0;
+ g_usHeadDots = 0;
+
+#ifdef S6145_UNUSED
+
+ g_usPrintDummyLevel = 0;
+ g_usPrintDummyLine = 0;
+ g_usRearDummyPrintLine = 0;
+ g_usRearDeleteLine = 0;
+
+ g_usPrintSizeLWidth = 0;
+ g_usPrintSizeLHeight = 0;
+
+ g_usThearmHead = 0;
+ g_usThearmEnv = 0;
+ g_usRearDummyPrintLevel = 0;
+
+ g_usLastPrintSizeWidth = 0;
+ g_usLastPrintSizeHeight = 0;
+ g_usLastSheetSizeWidth = 0;
+
+ g_iLeadEdgeCorrectPulse = 0;
+
+ g_usCancelCheckLinesForPRec = 118;
+
+ g_pusLamiCompInLineBufTab[0] = (uint16_t*)g_pusInLineBuf0;
+ g_pusLamiCompInLineBufTab[1] = (uint16_t*)g_pusInLineBuf2;
+ g_pusLamiCompInLineBufTab[2] = g_pusOutLineBuf1;
+ g_pusLamiCompInLineBufTab[3] = g_pusOutLineBuf2;
+
+ g_usMatteGloss = 105;
+ g_usMatteDeglossBlk = 150;
+ g_usMatteDeglossWht = 175;
+
+ g_usPrintOffsetWidth = 0;
+ g_usCenterHeadToColSen = 268;
+
+ g_uiLevelAveAddtion = 0;
+ g_uiLevelAveCounter = 0;
+ g_uiLevelAveCounter2 = 0;
+ g_uiLevelAveAddtion2 = 0;
+ g_usCancelCheckDotsForPRec = 236;
+#endif
+}
+
+#ifdef S6145_UNUSED
+static void SetTable(void)
+{
+ SetTableData(g_pSPrintParam->SideEdgeCoefTable, g_pusSideEdgeCoefTable, 128);
+ SetTableData(g_pSPrintParam->SideEdgeLvCoefTable, g_pusSideEdgeLvCoefTable, 256);
+}
+#endif
+
+static void SetTableColor(uint8_t plane)
+{
+ switch (plane) {
+ case 0:
+ SetTableData(g_pSPrintParam->pulseTransTable_Y, g_pusPulseTransTable, 256);
+ SetTableData(g_pSPrintParam->lineHistCoefTable_Y, g_pusLineHistCoefTable, 256);
+ SetTableData(g_pSPrintParam->tankPlusMaxEnergyTable_Y, g_pusTankPlusMaxEnegyTable, 256);
+ SetTableData(g_pSPrintParam->tankMinusMaxEnergy_Y, g_pusTankMinusMaxEnegyTable, 256);
+ memcpy(g_piTankParam, &g_pSPrintParam->tableTankParam_Y, 128);
+ break;
+ case 1:
+ SetTableData(g_pSPrintParam->pulseTransTable_M, g_pusPulseTransTable, 256);
+ SetTableData(g_pSPrintParam->lineHistCoefTable_M, g_pusLineHistCoefTable, 256);
+ SetTableData(g_pSPrintParam->tankPlusMaxEnergyTable_M, g_pusTankPlusMaxEnegyTable, 256);
+ SetTableData(g_pSPrintParam->tankMinusMaxEnergy_M, g_pusTankMinusMaxEnegyTable, 256);
+ memcpy(&g_piTankParam[32], &g_pSPrintParam->tableTankParam_M, 128);
+ break;
+ case 2:
+ SetTableData(g_pSPrintParam->pulseTransTable_C, g_pusPulseTransTable, 256);
+ SetTableData(g_pSPrintParam->lineHistCoefTable_C, g_pusLineHistCoefTable, 256);
+ SetTableData(g_pSPrintParam->tankPlusMaxEnergyTable_C, g_pusTankPlusMaxEnegyTable, 256);
+ SetTableData(g_pSPrintParam->tankMinusMaxEnergy_C, g_pusTankMinusMaxEnegyTable, 256);
+ memcpy(&g_piTankParam[64], &g_pSPrintParam->tableTankParam_C, 128);
+ break;
+ case 3:
+ SetTableData(g_pSPrintParam->pulseTransTable_O, g_pusPulseTransTable, 256);
+ SetTableData(g_pSPrintParam->lineHistCoefTable_O, g_pusLineHistCoefTable, 256);
+ SetTableData(g_pSPrintParam->tankPlusMaxEnergyTable_O, g_pusTankPlusMaxEnegyTable, 256);
+ SetTableData(g_pSPrintParam->tankMinusMaxEnergy_O, g_pusTankMinusMaxEnegyTable, 256);
+ memcpy(&g_piTankParam[96], &g_pSPrintParam->tableTankParam_O, 128);
+ break;
+ default:
+ printf("ERROR: Bad plane in SetTableColor (%d)\n", plane);
+ break;
+ }
+}
+
+static int32_t CheckPrintParam(uint8_t *corrdataraw)
+{
+ int i;
+ struct imageCorrParam *corrdata = (struct imageCorrParam *) corrdataraw;
+
+ for (i = 0 ; i < 256 ; i++) {
+ if (le16_to_cpu(corrdata->pulseTransTable_Y[i]) > le16_to_cpu(corrdata->printMaxPulse_Y) ||
+ le16_to_cpu(corrdata->pulseTransTable_M[i]) > le16_to_cpu(corrdata->printMaxPulse_M) ||
+ le16_to_cpu(corrdata->pulseTransTable_C[i]) > le16_to_cpu(corrdata->printMaxPulse_C) ||
+ le16_to_cpu(corrdata->pulseTransTable_O[i]) > le16_to_cpu(corrdata->printMaxPulse_O)) {
+ return 10;
+ }
+ }
+
+ if (!corrdata->tableTankParam_Y.trdTankSize ||
+ !corrdata->tableTankParam_M.trdTankSize ||
+ !corrdata->tableTankParam_C.trdTankSize ||
+ !corrdata->tableTankParam_O.trdTankSize) {
+ return 14;
+ }
+ if (!corrdata->tableTankParam_Y.sndTankSize ||
+ !corrdata->tableTankParam_M.sndTankSize ||
+ !corrdata->tableTankParam_C.sndTankSize ||
+ !corrdata->tableTankParam_O.sndTankSize) {
+ return 15;
+ }
+ if (!corrdata->tableTankParam_Y.fstTankSize ||
+ !corrdata->tableTankParam_M.fstTankSize ||
+ !corrdata->tableTankParam_C.fstTankSize ||
+ !corrdata->tableTankParam_O.fstTankSize) {
+ return 16;
+ }
+ if (le16_to_cpu(corrdata->val_1) > 1 ||
+ le16_to_cpu(corrdata->val_2) > 1 ||
+ le16_to_cpu(corrdata->printOpLevel) > 0xff ||
+ le16_to_cpu(corrdata->matteMode) > 1) {
+ return 17;
+ }
+ if (le16_to_cpu(corrdata->randomBase[0]) > 0xff ||
+ le16_to_cpu(corrdata->randomBase[1]) > 0xff ||
+ le16_to_cpu(corrdata->randomBase[2]) > 0xff ||
+ le16_to_cpu(corrdata->randomBase[3]) > 0xff) {
+ return 18;
+ }
+ if (!corrdata->matteSize ||
+ corrdata->matteSize > 2) {
+ return 19;
+ }
+
+ if ( le16_to_cpu(corrdata->width) <= MIN_ROWS ||
+ le16_to_cpu(corrdata->width) > MAX_ROWS )
+ return 20;
+
+ if ( le16_to_cpu(corrdata->height) <= MIN_ROWS ||
+ le16_to_cpu(corrdata->height) > MAX_ROWS )
+ return 21;
+
+ return 0;
+}
+
+/* This resets the preprocess pipeline at the start of a new image
+ plane. */
+static void LinePrintPreProcess(void)
+{
+ int16_t i;
+
+ GetInfo();
+
+ if ( !(g_sCorrectSw & 1) )
+ {
+ g_uiMtfWeightH = 0;
+ g_uiMtfWeightV = 0;
+ g_uiMtfSlice = 0;
+ }
+
+ for ( i = -256; i < 256; i++ )
+ {
+ if ( (uint32_t)(i * i) >= (uint32_t)(g_uiMtfSlice * g_uiMtfSlice) )
+ g_psMtfPreCalcTable[i+256] = i;
+ else
+ g_psMtfPreCalcTable[i+256] = -i;
+ }
+
+ g_pusPreReadLineBufTab[0] = g_pusInLineBuf0;
+ g_pusPreReadLineBufTab[1] = g_pusInLineBuf1;
+ g_pusPreReadLineBufTab[2] = g_pusInLineBuf2;
+ g_pusPreReadLineBufTab[3] = g_pusInLineBuf3;
+ g_pusPreReadLineBufTab[4] = g_pusInLineBuf4;
+ g_pusPreReadLineBufTab[5] = g_pusInLineBuf5;
+ g_pusPreReadLineBufTab[6] = g_pusInLineBuf6;
+ g_pusPreReadLineBufTab[7] = g_pusInLineBuf7;
+ g_pusPreReadLineBufTab[8] = g_pusInLineBuf8;
+ g_pusPreReadLineBufTab[9] = g_pusInLineBuf9;
+ g_pusPreReadLineBufTab[10] = g_pusInLineBufA;
+
+ memset(g_pusInLineBuf0, 0, sizeof(g_pusInLineBuf0));
+ memset(g_pusInLineBuf1, 0, sizeof(g_pusInLineBuf1));
+ memset(g_pusInLineBuf2, 0, sizeof(g_pusInLineBuf2));
+ memset(g_pusInLineBuf3, 0, sizeof(g_pusInLineBuf3));
+ memset(g_pusInLineBuf4, 0, sizeof(g_pusInLineBuf4));
+ memset(g_pusInLineBuf5, 0, sizeof(g_pusInLineBuf5));
+ memset(g_pusInLineBuf6, 0, sizeof(g_pusInLineBuf6));
+ memset(g_pusInLineBuf7, 0, sizeof(g_pusInLineBuf7));
+ memset(g_pusInLineBuf8, 0, sizeof(g_pusInLineBuf8));
+ memset(g_pusInLineBuf9, 0, sizeof(g_pusInLineBuf9));
+ memset(g_pusInLineBufA, 0, sizeof(g_pusInLineBufA));
+
+ g_pusPulseTransLineBufTab[0] = g_pusInLineBuf0;
+ g_pusPulseTransLineBufTab[1] = g_pusInLineBuf1;
+ g_pusPulseTransLineBufTab[2] = g_pusInLineBuf2;
+ g_pusPulseTransLineBufTab[3] = g_pusInLineBuf3;
+
+ memset(g_pusOutLineBuf1, 0, sizeof(g_pusOutLineBuf1));
+ g_pusOutLineBufTab[0] = g_pusOutLineBuf1;
+
+#ifdef S6145_UNUSED
+ memset(g_pusInLineBuf3, g_usPrintDummyLevel, sizeof(g_pusInLineBuf3)); // XXX redundant with memset above, printDummyLevel is always 0 anyway.
+#endif
+
+ g_uiSendToHeadCounter = g_usPrintSizeHeight;
+ g_uiLineCopyCounter = g_usPrintSizeHeight;
+
+#ifdef S6145_UNUSED
+ g_uiDataTransCounter = g_usPrintSizeHeight;
+ g_uiDataTransCounter += g_usPrintDummyLine;
+ g_uiDataTransCounter -= g_usRearDeleteLine;
+ g_uiDataTransCounter += g_usRearDummyPrintLine;
+
+ g_uiSendToHeadCounter += g_usPrintDummyLine;
+ g_uiSendToHeadCounter -= g_usRearDeleteLine;
+ g_uiSendToHeadCounter += g_usRearDummyPrintLine;
+
+ g_uiTudenLineCounter = g_usPrintSizeHeight;
+ g_uiTudenLineCounter += g_usRearDummyPrintLine;
+ g_uiTudenLineCounter -= g_usRearDeleteLine;
+
+ g_uiLineCopyCounter -= g_usRearDeleteLine;
+
+ if ( g_usPrintColor != 3 )
+ g_usRearDummyPrintLevel = 255;
+
+ g_iLeadEdgeCorrectPulse = 0;
+#endif
+
+ switch (g_usPrintColor) {
+ case 0:
+ CTankResetParameter(&g_piTankParam[0]);
+ g_iMaxPulseValue = g_usPrintMaxPulse;
+ g_uiMaxPulseBit = LinePrintCalcBit(g_usPrintMaxPulse);
+ g_pfRecieveData = RecieveDataYMC;
+#ifdef S6145_UNUSED
+ g_pfRecieveData_Post = RecieveDataYMC_Post;
+#endif
+ g_pfPulseTransPreRead = PulseTransPreReadYMC;
+ g_pfTankProcessPreRead = CTankProcessPreRead;
+ break;
+ case 1:
+ CTankResetParameter(&g_piTankParam[32]);
+ g_iMaxPulseValue = g_usPrintMaxPulse;
+ g_uiMaxPulseBit = LinePrintCalcBit(g_usPrintMaxPulse);
+ g_pfRecieveData = RecieveDataYMC;
+#ifdef S6145_UNUSED
+ g_pfRecieveData_Post = RecieveDataYMC_Post;
+#endif
+ g_pfPulseTransPreRead = PulseTransPreReadYMC;
+ g_pfTankProcessPreRead = CTankProcessPreRead;
+ break;
+ case 2:
+ CTankResetParameter(&g_piTankParam[64]);
+ g_iMaxPulseValue = g_usPrintMaxPulse;
+ g_uiMaxPulseBit = LinePrintCalcBit(g_usPrintMaxPulse);
+ g_pfRecieveData = RecieveDataYMC;
+#ifdef S6145_UNUSED
+ g_pfRecieveData_Post = RecieveDataYMC_Post;
+#endif
+ g_pfPulseTransPreRead = PulseTransPreReadYMC;
+ g_pfTankProcessPreRead = CTankProcessPreRead;
+ break;
+ case 3:
+ CTankResetParameter(&g_piTankParam[96]);
+ g_iMaxPulseValue = g_usPrintMaxPulse;
+ g_uiMaxPulseBit = LinePrintCalcBit(g_usPrintMaxPulse);
+ if ( g_usMatteMode ) {
+ g_pfRecieveData = RecieveDataOP_MATTE;
+#ifdef S6145_UNUSED
+ g_pfRecieveData_Post = RecieveDataOPMatte_Post;
+#endif
+ } else {
+ g_pfRecieveData = RecieveDataOP_GLOSS;
+#ifdef S6145_UNUSED
+ g_pfRecieveData_Post = RecieveDataOPLevel_Post;
+#endif
+ }
+ g_pfPulseTransPreRead = PulseTransPreReadOP;
+ g_pfTankProcessPreRead = CTankProcessPreReadDummy;
+#ifdef S6145_UNUSED
+ if ( g_usMatteMode )
+ g_iLeadEdgeCorrectPulse = 120;
+#endif
+ break;
+ default:
+ printf("ERROR: Bad g_usPrintColor %d\n", g_usPrintColor);
+ return;
+ }
+
+ g_uiLineCorrectSum = 0;
+ g_iLineCorrectPulse = 0;
+
+ if ( g_uiLineCorrectSlice ) {
+ g_uiLineCorrectBase = g_uiLineCorrectSlice * g_usLineCorrect_Env_A;
+ g_uiLineCorrectBase >>= 15;
+ g_uiLineCorrectBase *= g_usSheetSizeWidth;
+ } else {
+ g_uiLineCorrectBase = -1;
+ }
+
+ if ( g_uiLineCorrectSlice1Line ) {
+ g_uiLineCorrectBase1Line = g_uiLineCorrectSlice1Line * g_usLineCorrect_Env_B;
+ g_uiLineCorrectBase1Line >>= 15;
+ g_uiLineCorrectBase1Line *= g_usSheetSizeWidth;
+ }
+
+ if ( g_iLineCorrectPulseMax ) {
+ g_iLineCorrectPulseMax *= g_usLineCorrect_Env_C;
+ g_iLineCorrectPulseMax /= 1024;
+ } else {
+ g_iLineCorrectPulseMax = MAX_PULSE;
+ }
+
+ CTankResetTank();
+
+#ifdef S6145_UNUSED
+ g_uiDummyPrintCounter = 0;
+#endif
+}
+
+static void CTankResetParameter(int32_t *params)
+{
+ m_iTrdTankSize = le32_to_cpu(params[0]);
+ m_iSndTankSize = le32_to_cpu(params[1]);
+ m_iFstTankSize = le32_to_cpu(params[2]);
+ m_iTrdTankIniEnergy = le32_to_cpu(params[3]);
+ m_iSndTankIniEnergy = le32_to_cpu(params[4]);
+ m_iFstTankIniEnergy = le32_to_cpu(params[5]);
+ m_iTrdTrdConductivity = le32_to_cpu(params[6]);
+ m_iSndSndConductivity = le32_to_cpu(params[7]);
+ m_iFstFstConductivity = le32_to_cpu(params[8]);
+ m_iOutTrdConductivity = le32_to_cpu(params[9]);
+ m_iTrdSndConductivity = le32_to_cpu(params[10]);
+ m_iSndFstConductivity = le32_to_cpu(params[11]);
+ m_iFstOutConductivity = le32_to_cpu(params[12]);
+#ifdef S6145_UNUSED
+ m_iPlusMaxEnergy = le32_to_cpu(params[13]);
+ m_iMinusMaxEnergy = le32_to_cpu(params[14]);
+ m_iPlusMaxEnergyPreRead = le32_to_cpu(params[15]);
+#endif
+
+ m_iMinusMaxEnergyPreRead = le32_to_cpu(params[16]);
+ m_iPreReadLevelDiff = le32_to_cpu(params[17]);
+
+ m_iTankKeisuOutTrdDivTrd = (int64_t)m_iOutTrdConductivity * (int64_t)0x10000 / (int64_t)m_iTrdTankSize;
+ m_iTankKeisuTrdSndDivTrd = (int64_t)m_iTrdSndConductivity * (int64_t)0x10000 / (int64_t)m_iTrdTankSize;
+ m_iTankKeisuTrdSndDivSnd = (int64_t)m_iTrdSndConductivity * (int64_t)0x10000 / (int64_t)m_iSndTankSize;
+ m_iTankKeisuSndFstDivSnd = (int64_t)m_iSndFstConductivity * (int64_t)0x10000 / (int64_t)m_iSndTankSize;
+ m_iTankKeisuSndFstDivFst = (int64_t)m_iSndFstConductivity * (int64_t)0x10000 / (int64_t)m_iFstTankSize;
+ m_iTankKeisuFstOutDivFst = (int64_t)m_iFstOutConductivity * (int64_t)0x10000 / (int64_t)m_iFstTankSize;
+
+ return;
+}
+
+static void CTankResetTank(void)
+{
+ int i;
+
+ for (i = 0 ; i < TANK_SIZE; i++) {
+ m_piTrdTankArray[i] = m_iTrdTankIniEnergy;
+ m_piSndTankArray[i] = m_iSndTankIniEnergy;
+ m_piFstTankArray[i] = m_iFstTankIniEnergy;
+ }
+}
+
+/* This primes the preprocessing pipeline prior to starting the first
+ actual row of image data */
+static void PagePrintPreProcess(void)
+{
+ uint32_t i;
+
+ g_pusPulseTransLineBufTab[3] = g_pusPreReadLineBufTab[1];
+ g_pfRecieveData();
+ g_pusPulseTransLineBufTab[1] = g_pusPulseTransLineBufTab[3];
+ g_uiLineCopyCounter++;
+ g_uiInputImageIndex -= g_usPrintSizeWidth;
+ g_pusPulseTransLineBufTab[3] = g_pusPreReadLineBufTab[2];
+ g_pfRecieveData();
+ g_pusPulseTransLineBufTab[2] = g_pusPulseTransLineBufTab[3];
+ g_pusPulseTransLineBufTab[3] = g_pusPreReadLineBufTab[3];
+ g_pfRecieveData();
+ for ( i = 0; i < 7; i++ )
+ {
+ g_pusPulseTransLineBufTab[3] = g_pusPreReadLineBufTab[i + 4];
+ g_pfRecieveData();
+ }
+ g_pusPulseTransLineBufTab[0] = g_pusPreReadLineBufTab[0];
+}
+
+/* Process a single scanline,
+ From reading the input data to writing the output.
+ */
+static void PagePrintProcess(void)
+{
+ uint32_t i;
+
+ /* First, rotate the input buffers... */
+ if ( g_usPrintColor != 3 || g_usMatteMode != 1 || g_usMatteSize != 2 ) {
+ /* If we're not printing a matte layer... */
+ uint8_t *v4 = g_pusPreReadLineBufTab[0];
+ for ( i = 0; i < 10; i++ )
+ g_pusPreReadLineBufTab[i] = g_pusPreReadLineBufTab[i + 1];
+ g_pusPreReadLineBufTab[10] = v4;
+ g_pusPulseTransLineBufTab[0] = g_pusPreReadLineBufTab[0];
+ g_pusPulseTransLineBufTab[1] = g_pusPreReadLineBufTab[1];
+ g_pusPulseTransLineBufTab[2] = g_pusPreReadLineBufTab[2];
+ g_pusPulseTransLineBufTab[3] = g_pusPreReadLineBufTab[10];
+ } else if ( g_uiLineCopyCounter & 1 ) {
+ /* in other words, every other line when printing a matte layer.. */
+ uint8_t *v4 = g_pusPreReadLineBufTab[0];
+ for ( i = 0; i < 10; i++ )
+ g_pusPreReadLineBufTab[i] = g_pusPreReadLineBufTab[i + 1];
+ g_pusPreReadLineBufTab[10] = v4;
+ g_pusPulseTransLineBufTab[0] = g_pusPreReadLineBufTab[0];
+ g_pusPulseTransLineBufTab[1] = g_pusPreReadLineBufTab[1];
+ g_pusPulseTransLineBufTab[2] = g_pusPreReadLineBufTab[2];
+ g_pusPulseTransLineBufTab[3] = g_pusPreReadLineBufTab[10];
+ }
+
+#ifdef S6145_UNUSED
+ g_uiTudenLineCounter--;
+#endif
+ g_pfRecieveData(); /* Read another scanline */
+ PulseTrans();
+ g_pfPulseTransPreRead();
+#ifdef S6145_UNUSED
+ g_pfRecieveData_Post(); /* Clean up after the receive */
+#endif
+ CTankProcess(); /* Update thermal tank state */
+ g_pfTankProcessPreRead();
+ LineCorrection(); /* Final output compensation */
+ SendData(); /* Write scanline output */
+ return;
+}
+
+static uint16_t LinePrintCalcBit(uint16_t val)
+{
+ uint16_t bit = 0;
+ while (val) {
+ val >>= 1;
+ bit++;
+ }
+ return bit;
+}
+
+/* Update thermal tank state */
+static void CTankProcess(void)
+{
+ if ( g_sCorrectSw & 2 ) {
+ CTankHosei();
+ CTankUpdateTankVolumeInterRay();
+ CTankUpdateTankVolumeInterDot(0);
+ CTankUpdateTankVolumeInterDot(1);
+ CTankUpdateTankVolumeInterDot(2);
+ }
+ return;
+}
+
+static void CTankProcessPreRead(void)
+{
+ if (g_sCorrectSw & 2)
+ CTankHoseiPreread();
+}
+
+static void CTankProcessPreReadDummy(void)
+{
+ return;
+}
+
+/* This will generate one line worth of "gloss" OC data.
+ It only covers the imageable area, rather than the head width */
+static void RecieveDataOP_GLOSS(void)
+{
+ if ( g_uiLineCopyCounter ) {
+ memset(g_pusPulseTransLineBufTab[3] + ((g_usHeadDots - g_usSheetSizeWidth) / 2),
+ g_usPrintOpLevel,
+ g_usSheetSizeWidth);
+
+ g_uiLineCopyCounter--;
+ }
+
+ return;
+}
+
+/* This reads a single line worth of input image data.
+ */
+static void RecieveDataYMC(void)
+{
+ uint8_t *v1;
+ int16_t i;
+
+ v1 = g_pusPulseTransLineBufTab[3] + ((g_usHeadDots - g_usSheetSizeWidth) / 2);
+
+ if ( g_uiLineCopyCounter ) {
+ /* Read the next line */
+ for ( i = 0; i < g_usPrintSizeWidth; i++ )
+ v1[i] = g_pucInputImageBuf[g_uiInputImageIndex++];
+ --g_uiLineCopyCounter;
+ } else {
+ /* Re-read the previous line */
+ g_uiInputImageIndex -= g_usPrintSizeWidth;
+ for ( i = 0; i < g_usPrintSizeWidth ; i++ )
+ v1[i] = g_pucInputImageBuf[g_uiInputImageIndex++];
+ }
+}
+
+/* this will generate one scanline (ie 16b * BUF_SIZE) worth of
+ "random" data for the matte overcoat */
+static void RecieveDataOP_MATTE(void)
+{
+ if ( g_uiLineCopyCounter ) {
+ int32_t v1;
+ uint32_t v5;
+ int32_t v6;
+
+ int16_t matteCtr;
+ uint8_t *outPtr = g_pusPulseTransLineBufTab[3];
+
+ if ( g_usMatteSize == 2 )
+ matteCtr = 256;
+ else
+ matteCtr = 512;
+
+ while ( matteCtr-- ) {
+ if ( g_pulRandomTable[0] >= 31 )
+ v6 = 1;
+ else
+ v6 = g_pulRandomTable[0] + 1;
+ g_pulRandomTable[0] = v6;
+ if ( v6 <= 3 )
+ v1 = g_pulRandomTable[v6 + 28];
+ else
+ v1 = g_pulRandomTable[v6 - 3];
+ g_pulRandomTable[v6] += v1;
+
+ v5 = (uint32_t)g_pulRandomTable[v6] >> 1;
+ if ( g_usMatteSize == 2 ) {
+ *outPtr++ = g_ucRandomBaseLevel[(v5 >> 1) & 3];
+ *outPtr++ = g_ucRandomBaseLevel[(v5 >> 1) & 3];
+ *outPtr++ = g_ucRandomBaseLevel[(v5 >> 5) & 3];
+ *outPtr++ = g_ucRandomBaseLevel[(v5 >> 5) & 3];
+ *outPtr++ = g_ucRandomBaseLevel[(v5 >> 9) & 3];
+ *outPtr++ = g_ucRandomBaseLevel[(v5 >> 9) & 3];
+ *outPtr++ = g_ucRandomBaseLevel[(v5 >> 13) & 3];
+ *outPtr++ = g_ucRandomBaseLevel[(v5 >> 13) & 3];
+ } else {
+ *outPtr++ = g_ucRandomBaseLevel[(v5 >> 1) & 3];
+ *outPtr++ = g_ucRandomBaseLevel[(v5 >> 5) & 3];
+ *outPtr++ = g_ucRandomBaseLevel[(v5 >> 9) & 3];
+ *outPtr++ = g_ucRandomBaseLevel[(v5 >> 13) & 3];
+ }
+ }
+ --g_uiLineCopyCounter;
+ }
+}
+
+/* This writes a single scanline to the output buffer */
+static void SendData(void)
+{
+ uint16_t i;
+
+ if ( g_uiSendToHeadCounter ) {
+ for ( i = 0; i < g_usHeadDots; i++ )
+ g_pusOutputImageBuf[g_uiOutputImageIndex++] = cpu_to_le16(g_pusOutLineBufTab[0][i]);
+ --g_uiSendToHeadCounter;
+ }
+}
+
+/* Use the previous two rows to generate the needed impulse for
+ the current row. */
+static void PulseTrans(void)
+{
+ int32_t overHang;
+ int32_t sheetSizeWidth;
+
+ uint8_t *prevPrevRow;
+ uint8_t *prevRow;
+ uint8_t *currentRow;
+
+ uint16_t *out;
+
+ sheetSizeWidth = g_usSheetSizeWidth;
+ overHang = (g_usHeadDots - g_usSheetSizeWidth) / 2;
+
+ currentRow = g_pusPulseTransLineBufTab[0] + overHang;
+ prevRow = g_pusPulseTransLineBufTab[1] + overHang;
+ prevPrevRow = g_pusPulseTransLineBufTab[2] + overHang;
+ out = g_pusOutLineBufTab[0] + g_sPrintSideOffset + overHang;
+
+ if ( out >= g_pusOutLineBufTab[0] ) {
+ int32_t offset = g_sPrintSideOffset
+ + g_usSheetSizeWidth
+ + overHang;
+ if ( offset > BUF_SIZE )
+ sheetSizeWidth = g_usSheetSizeWidth - (offset - BUF_SIZE);
+ } else {
+ int32_t offset = (g_pusOutLineBufTab[0] - out);
+ out = g_pusOutLineBufTab[0];
+ sheetSizeWidth = g_usSheetSizeWidth - offset;
+ currentRow += offset;
+ prevRow += offset;
+ prevPrevRow += offset;
+ printf("WARN: PulseTrans() alt path\n");
+ }
+
+ while ( sheetSizeWidth-- ) {
+ int32_t tableOffset;
+ uint16_t compVal;
+
+ uint8_t *v2;
+ int32_t v3;
+ int32_t v4;
+ int32_t v6;
+ int32_t v12;
+
+ v2 = prevRow - 1;
+ v3 = *v2++;
+ v12 = *v2;
+ prevRow = v2 + 1;
+ v4 = g_psMtfPreCalcTable[256 + v12 - *prevRow] + g_psMtfPreCalcTable[256 + v12 - v3];
+ v6 = g_psMtfPreCalcTable[256 + v12 - *currentRow++];
+
+ tableOffset = v12 + ((v4 * g_uiMtfWeightH + (g_psMtfPreCalcTable[256 + v12 - *prevPrevRow++] + v6) * g_uiMtfWeightV) >> 7);
+ if ( tableOffset > 255 )
+ tableOffset = 255;
+ if ( tableOffset <= 0 )
+ tableOffset = 1;
+ if ( !v12 )
+ tableOffset = 0;
+
+ compVal = g_pusPulseTransTable[tableOffset];
+ if ( compVal > MAX_PULSE )
+ compVal = MAX_PULSE;
+
+ *out++ = compVal;
+ }
+
+#ifdef S6145_UNUSED
+ g_uiDataTransCounter--;
+#endif
+}
+
+static void PulseTransPreReadOP(void)
+{
+
+}
+
+static void PulseTransPreReadYMC(void)
+{
+ uint16_t overHang;
+ uint16_t printSizeWidth;
+ uint16_t *out;
+
+#ifdef S6145_UNUSED
+ uint8_t *v1;
+ uint8_t *v2;
+ uint8_t *v3;
+ uint8_t *v4;
+#endif
+
+ uint8_t *v14;
+ uint8_t *v15;
+ uint8_t *v16;
+ uint8_t *v17;
+
+ printSizeWidth = g_usPrintSizeWidth;
+ overHang = (g_usHeadDots - g_usPrintSizeWidth) / 2;
+ v17 = g_pusPreReadLineBufTab[2] + overHang;
+ v16 = g_pusPreReadLineBufTab[3] + overHang;
+ v15 = g_pusPreReadLineBufTab[4] + overHang;
+ v14 = g_pusPreReadLineBufTab[5] + overHang;
+
+#ifdef S6145_UNUSED
+ v1 = g_pusPreReadLineBufTab[6] + overHang;
+ v2 = g_pusPreReadLineBufTab[7] + overHang;
+ v3 = g_pusPreReadLineBufTab[8] + overHang;
+ v4 = g_pusPreReadLineBufTab[9] + overHang;
+#endif
+
+ out = g_pusPreReadOutLineBuf + overHang + g_sPrintSideOffset;
+
+ if ( out < g_pusPreReadOutLineBuf ) {
+ int32_t offset = (g_pusPreReadOutLineBuf - out);
+ out = g_pusPreReadOutLineBuf;
+ printSizeWidth = g_usPrintSizeWidth - offset;
+ v17 += offset;
+ v16 += offset;
+ v15 += offset;
+ v14 += offset;
+ printf("WARN: PulseTransPreReadYMC alt path!\n");
+ }
+
+ while ( printSizeWidth-- ) {
+ int32_t v6 = *v17++;
+ int32_t v7 = *v16++ + v6;
+ int32_t v8 = *v15++ + v7;
+ int32_t v9 = *v14++ + v8;
+ int32_t pixel = g_pusPulseTransTable[v9 / 4];
+ if ( pixel > MAX_PULSE )
+ pixel = MAX_PULSE;
+ *out++ = pixel;
+ }
+}
+
+static void CTankUpdateTankVolumeInterDot(uint8_t tank)
+{
+ int32_t *tankIn;
+ int32_t *tankOut;
+ int32_t conductivity;
+ uint16_t sheetSizeWidth;
+
+ uint16_t v1;
+ int32_t v2;
+ int32_t v4;
+ int32_t v5;
+ int32_t v8;
+ int32_t v17;
+ int32_t v18;
+ int32_t v19;
+ int32_t v20;
+
+ switch (tank) {
+ case 0:
+ tankIn = m_piFstTankArray;
+ tankOut = m_piFstTankArray + 2;
+ conductivity = m_iFstFstConductivity / 2;
+ break;
+ case 1:
+ tankIn = m_piSndTankArray;
+ tankOut = m_piSndTankArray + 2;
+ conductivity = m_iSndSndConductivity / 2;
+ break;
+ case 2:
+ tankIn = m_piTrdTankArray;
+ tankOut = m_piTrdTankArray + 2;
+ conductivity = m_iTrdTrdConductivity / 2;
+ break;
+ default:
+ printf("ERROR: Bad Tank %d in CTankUpdateVolumeInterDot\n", tank);
+ return;
+ }
+
+ /* This code basically takes a running average of three running
+ averages, and uses that as the basis for the output */
+
+ tankIn[0] = tankIn[1] = tankIn[2];
+ v1 = g_usSheetSizeWidth + 1;
+ tankIn[v1+1] = tankIn[v1+2] = tankIn[v1];
+ v2 = *tankIn++;
+ v4 = *tankIn++;
+ v5 = *tankIn++;
+ v8 = *tankIn++;
+ v20 = *tankIn++;
+
+ v19 = conductivity * (v5 + v2 - 2 * v4);
+ v18 = conductivity * (v8 + v4 - 2 * v5);
+ v17 = conductivity * (v20 + v5 - 2 * v8);
+ sheetSizeWidth = g_usSheetSizeWidth;
+
+ while ( sheetSizeWidth-- ) {
+ int32_t pixel = (v18 >> 6) + v5 - (conductivity * ((2 * v18 - v19 - v17) >> 7) >> 7);
+ if ( pixel < 0 )
+ pixel = 0;
+ *tankOut++ = pixel;
+ v5 = v8;
+ v8 = v20;
+ v20 = *tankIn++;
+ v19 = v18;
+ v18 = v17;
+ v17 = conductivity * (v20 + v5 - 2 * v8);
+ }
+}
+
+static void CTankUpdateTankVolumeInterRay(void)
+{
+ uint16_t sheetWidth = g_usSheetSizeWidth;
+ int32_t *fstTankPtr = m_piFstTankArray + 2;
+ int32_t *sndTankPtr = m_piSndTankArray + 2;
+ int32_t *trdTankPtr = m_piTrdTankArray + 2;
+
+ while ( sheetWidth-- ) {
+ int32_t v2, v3;
+
+ v2 = (*sndTankPtr * m_iTankKeisuSndFstDivSnd - *fstTankPtr * m_iTankKeisuSndFstDivFst) >> 17;
+ *fstTankPtr = v2 + *fstTankPtr - (*fstTankPtr * m_iTankKeisuFstOutDivFst >> 17);
+ fstTankPtr++;
+
+ v3 = (*trdTankPtr * m_iTankKeisuTrdSndDivTrd - *sndTankPtr * m_iTankKeisuTrdSndDivSnd) >> 17;
+ *sndTankPtr = v3 + *sndTankPtr - v2;
+ sndTankPtr++;
+
+ *trdTankPtr = *trdTankPtr - v3 - (*trdTankPtr * m_iTankKeisuOutTrdDivTrd >> 17);
+ trdTankPtr++;
+ }
+}
+
+static void CTankHoseiPreread(void)
+{
+ uint16_t sheetWidth;
+ int16_t overHang;
+ int32_t *fstTankPtr;
+ uint16_t *outPtr;
+ int16_t *inPtr; /* Must treat this as SIGNED! */
+
+ int32_t v4;
+
+ overHang = (g_usHeadDots - g_usSheetSizeWidth) / 2;
+ inPtr = (int16_t*)g_pusPreReadOutLineBuf + overHang + g_sPrintSideOffset;
+ outPtr = g_pusOutLineBufTab[0] + overHang + g_sPrintSideOffset;
+ if ( outPtr < g_pusOutLineBufTab[0] )
+ outPtr = g_pusOutLineBufTab[0];
+ fstTankPtr = m_piFstTankArray + 2;
+ v4 = (1 << (g_uiMaxPulseBit + 20)) / m_iFstTankSize;
+
+ /* Walk forward through the line to compute the necessary delta */
+ sheetWidth = g_usSheetSizeWidth;
+ while ( sheetWidth-- ) {
+ int32_t v5 = *inPtr - (v4 * (*inPtr + *fstTankPtr++) >> 20);
+ int32_t v6 = 0;
+ if ( v5 < m_iPreReadLevelDiff )
+ v6 = -(m_iMinusMaxEnergyPreRead * v5 * v5) >> g_uiMaxPulseBit;
+ *inPtr++ = v6;
+ }
+
+ /* Now walk backwards through the line to derive the desired pixel
+ values, adding the actual value with the necessary delta.. */
+ outPtr += g_usSheetSizeWidth;
+
+ sheetWidth = g_usSheetSizeWidth;
+ while ( sheetWidth-- ) {
+ int32_t pixel;
+
+ inPtr--;
+ outPtr--;
+
+ pixel = *inPtr + *outPtr;
+ if ( pixel < 0 )
+ pixel = 0;
+ if ( pixel > g_iMaxPulseValue )
+ pixel = g_iMaxPulseValue;
+ *outPtr = pixel;
+ }
+}
+
+/* Apply the correction needed based on the thermal tanks */
+static void CTankHosei(void)
+{
+ uint16_t overHang;
+ uint16_t sheetSizeWidth;
+ int32_t *tankPtr;
+ uint8_t *in;
+ uint16_t *out;
+
+ int32_t v4;
+#ifdef S6145_UNUSED
+ int32_t v2;
+ int32_t *v12;
+#endif
+
+ sheetSizeWidth = g_usSheetSizeWidth;
+ overHang = (g_usHeadDots - g_usSheetSizeWidth) / 2;
+ out = g_pusOutLineBufTab[0] + (overHang + g_sPrintSideOffset);
+ in = g_pusPulseTransLineBufTab[1] + overHang;
+
+ if ( out >= g_pusOutLineBufTab[0] ) {
+ int32_t offset = g_sPrintSideOffset + sheetSizeWidth + overHang;
+ if ( offset > BUF_SIZE ) {
+ offset -= BUF_SIZE;
+ sheetSizeWidth -= offset;
+ }
+ } else {
+ int32_t offset = (g_pusOutLineBufTab[0] - out);
+ sheetSizeWidth -= offset;
+ in += (out - g_pusOutLineBufTab[0]); // XXX was: in += out;
+ out = g_pusOutLineBufTab[0];
+ printf("WARN: CTankHosei() alt path\n");
+ }
+ tankPtr = m_piFstTankArray + 2;
+
+#ifdef S6145_UNUSED
+ v2 = m_iPlusMaxEnergy;
+ v12 = &v2;
+#endif
+
+ v4 = (1 << (g_uiMaxPulseBit + 20)) / m_iFstTankSize;
+
+ while ( sheetSizeWidth-- ) {
+ int32_t v5;
+ int32_t v8;
+ uint16_t v11;
+ uint32_t v3 = *in++;
+ v5 = *out - ((v4 * (*out + *tankPtr)) >> 20);
+ if ( v5 < 0 )
+ v11 = g_pusTankMinusMaxEnegyTable[v3];
+ else
+ v11 = g_pusTankPlusMaxEnegyTable[v3];
+ v8 = *out + ((v5 * v11) >> g_uiMaxPulseBit);
+ if ( v8 < 0 )
+ v8 = 0;
+ if ( v8 > g_iMaxPulseValue )
+ v8 = g_iMaxPulseValue;
+ *out++ = v8;
+ *tankPtr++ += v8;
+ }
+}
+
+/* Apply final corrections to the output. */
+#define LINECORR_BUCKETS 4
+static void LineCorrection(void)
+{
+ uint16_t sheetSizeWidth;
+ uint16_t overHang;
+ uint8_t *in;
+ uint16_t *out;
+ uint32_t bucket[LINECORR_BUCKETS];
+ uint32_t correct;
+ uint8_t i;
+
+ sheetSizeWidth = g_usSheetSizeWidth;
+ overHang = (g_usHeadDots - g_usSheetSizeWidth) / 2;
+ in = g_pusPulseTransLineBufTab[1] + overHang;
+ out = g_pusOutLineBufTab[0] + overHang + g_sPrintSideOffset;
+ if ( out >= g_pusOutLineBufTab[0] ) {
+ uint32_t tmp = g_sPrintSideOffset + sheetSizeWidth + overHang;
+ if ( tmp > BUF_SIZE ) {
+ tmp -= BUF_SIZE;
+ sheetSizeWidth -= tmp;
+ }
+ } else {
+ uint32_t tmp = g_pusOutLineBufTab[0] - out;
+ sheetSizeWidth -= tmp;
+ in += (out - g_pusOutLineBufTab[0]); // XXX was: in += out;
+ out = g_pusOutLineBufTab[0];
+ printf("WARN: LineCorrection() alt path\n");
+ }
+
+ /* Apply the correction compensation */
+ bucket[0] = bucket[1] = bucket[2] = bucket[3] = 0;
+ for ( i = 0; i < LINECORR_BUCKETS; i++ ) {
+ uint16_t j = sheetSizeWidth / LINECORR_BUCKETS;
+ while ( j-- ) {
+ int32_t pixel = *out;
+ bucket[i] += pixel;
+ pixel -= g_pusLineHistCoefTable[*in++] * g_iLineCorrectPulse / 1024;
+ if ( pixel < 0 )
+ pixel = 0;
+ *out++ = pixel;
+ }
+ }
+
+ /* See if we need to increase the correction compensation */
+ correct = 0;
+ for ( i = 0; i < LINECORR_BUCKETS; i++ ) {
+ if ( g_uiLineCorrectBase1Line / LINECORR_BUCKETS <= bucket[i] )
+ correct++;
+ }
+ if ( correct ) {
+ for ( i = 0; i < LINECORR_BUCKETS; i++ )
+ g_uiLineCorrectSum += bucket[i];
+ }
+ if ( g_uiLineCorrectSum > g_uiLineCorrectBase ) {
+ g_uiLineCorrectSum -= g_uiLineCorrectBase;
+ if ( g_iLineCorrectPulse < g_iLineCorrectPulseMax )
+ g_iLineCorrectPulse++;
+ }
+
+}
+
+#ifdef S6145_UNUSED
+/* XXX all of these functions are present in the library, but not actually
+ referenced by anything, so there's no point in worrying about them. */
+static void SideEdgeCorrection(void)
+{
+ int32_t v0;
+ uint32_t v1;
+ uint8_t *v4;
+ uint16_t *v5;
+ uint8_t *v6;
+ uint8_t *v7;
+ uint16_t *out;
+ uint16_t *v9;
+ uint32_t v10;
+ uint32_t v11;
+ int32_t v12;
+ int32_t v13;
+ int32_t v14;
+ int32_t v15;
+ int32_t v16;
+
+ v16 = g_usSheetSizeWidth;
+ v0 = (g_usHeadDots - g_usSheetSizeWidth) / 2;
+ v6 = g_pusPulseTransLineBufTab[1] + v0;
+ out = g_pusOutLineBufTab[0] + g_sPrintSideOffset + v0;
+ v11 = 0;
+ if ( out >= g_pusOutLineBufTab[0] ) {
+ v10 = g_sPrintSideOffset
+ + g_usSheetSizeWidth
+ + v0;
+ if ( v10 > BUF_SIZE )
+ {
+ v10 -= BUF_SIZE;
+ v16 = g_usSheetSizeWidth - v10;
+ }
+ } else {
+ v1 = g_pusOutLineBufTab[0] - out;
+ out = g_pusOutLineBufTab[0];
+ v16 = g_usSheetSizeWidth - v1;
+ v10 = v11;
+ }
+ v5 = out + 2 * v16;
+ v4 = v16 + v6;
+ v14 = 128 - v11;
+
+ while ( v14 ) {
+ v12 = (((1024 - g_pusSideEdgeLvCoefTable[*v6++] * (uint32_t)g_pusSideEdgeCoefTable[128 - v14--]) >> 10) * *out) >> 10;
+ if ( v12 > g_iMaxPulseValue )
+ v12 = g_iMaxPulseValue;
+ *out++ = v12;
+ }
+
+ v9 = v5;
+ v7 = v4;
+ v15 = 128 - v10;
+
+ while ( v15 ) {
+ v9--;
+ --v7;
+ v13 = ((1024 - (g_pusSideEdgeLvCoefTable[*v7] * (uint32_t)g_pusSideEdgeCoefTable[128 - v15--]) >> 10) * *v9) >> 10;
+ if ( g_iMaxPulseValue < v13 )
+ v13 = g_iMaxPulseValue;
+ *v9 = v13;
+ }
+}
+
+static void LeadEdgeCorrection(void)
+{
+ uint32_t v0;
+ uint16_t *out;
+ int32_t v4;
+ uint32_t v5;
+ int32_t v6;
+
+ if ( g_iLeadEdgeCorrectPulse ) {
+ v6 = g_usSheetSizeWidth;
+ out = g_pusOutLineBufTab[0] + g_sPrintSideOffset
+ + ((g_usHeadDots - g_usSheetSizeWidth) / 2);
+ if ( out >= g_pusOutLineBufTab[0] ) {
+ v5 = g_sPrintSideOffset
+ + g_usSheetSizeWidth
+ + ((g_usHeadDots - g_usSheetSizeWidth) / 2);
+ if ( v5 > BUF_SIZE )
+ v6 = g_usSheetSizeWidth - (v5 - BUF_SIZE);
+ } else {
+ v0 = g_pusOutLineBufTab[0] - out;
+ out = g_pusOutLineBufTab[0];
+ v6 = g_usSheetSizeWidth - v0;
+ }
+
+ while ( v6-- ) {
+ v4 = (g_iLeadEdgeCorrectPulse / 4) + *out;
+ if ( v4 > g_iMaxPulseValue )
+ v4 = g_iMaxPulseValue;
+ *out++ = v4;
+ }
+ --g_iLeadEdgeCorrectPulse;
+ }
+}
+
+static void RecieveDataOP_Post(void)
+{
+ return;
+}
+
+static void RecieveDataYMC_Post(void)
+{
+ return;
+}
+
+static void RecieveDataOPLevel_Post(void)
+{
+ return;
+}
+
+static void RecieveDataOPMatte_Post(void)
+{
+ return;
+}
+
+static void ImageLevelAddition(void)
+{
+ if ( g_uiLevelAveCounter < g_usPrintSizeHeight )
+ {
+ ImageLevelAdditionEx(&g_uiLevelAveAddtion, 0, g_usSheetSizeWidth);
+ g_uiLevelAveCounter++;
+ if ( g_uiLevelAveCounter2-- == 0 )
+ {
+ ImageLevelAdditionEx(
+ &g_uiLevelAveAddtion2,
+ g_uiOffsetCancelCheckPRec,
+ g_usCancelCheckDotsForPRec);
+ ++g_uiLevelAveCounter2;
+ }
+ }
+}
+
+static void ImageLevelAdditionEx(uint32_t *a1, uint32_t a2, int32_t a3)
+{
+ int32_t v3;
+ uint8_t *v6;
+ int32_t i;
+ int32_t v8;
+
+ v6 = g_pusPulseTransLineBufTab[1] + a2 +
+ ((g_usHeadDots - g_usSheetSizeWidth) / 2);
+ v8 = a3;
+ for ( i = 0; v8-- ; i += v3 ) {
+ v3 = *v6++;
+ }
+ *a1 += i;
+}
+
+#endif /* S6145_UNUSED */