From fa7bc447fc127a291b2a6f36b16293eb5cbc0032 Mon Sep 17 00:00:00 2001 From: OctoSpacc Date: Wed, 1 Nov 2023 23:22:11 +0100 Subject: [PATCH] Update scripts and NES compatibility, add PNG to NES CHR convert --- LibMultiSpacc/Examples/Common.mk | 27 +-- LibMultiSpacc/Examples/HelloWorld/CHARS.png | Bin 0 -> 773 bytes .../Examples/HelloWorld/HelloWorld.c | 8 +- LibMultiSpacc/Examples/HelloWorld/Makefile | 2 +- LibMultiSpacc/Examples/HelloWorld/Tiles.png | Bin 664 -> 0 bytes LibMultiSpacc/Examples/NES.mk.sh | 3 +- LibMultiSpacc/LibMultiSpacc/MultiSpacc.c | 7 + LibMultiSpacc/LibMultiSpacc/MultiSpacc.h | 1 + LibMultiSpacc/LibMultiSpacc/Setup.c | 2 + LibMultiSpacc/neslib/.gitignore | 5 - LibMultiSpacc/neslib/neslib.h | 8 +- Tools/WindowsRefreshEnv.cmd | 130 +++++++++++ Tools/pilbmp2nes.py | 209 ++++++++++++++++++ Tools/python3.sh | 5 + 14 files changed, 379 insertions(+), 28 deletions(-) create mode 100644 LibMultiSpacc/Examples/HelloWorld/CHARS.png delete mode 100644 LibMultiSpacc/Examples/HelloWorld/Tiles.png delete mode 100644 LibMultiSpacc/neslib/.gitignore create mode 100644 Tools/WindowsRefreshEnv.cmd create mode 100644 Tools/pilbmp2nes.py create mode 100644 Tools/python3.sh diff --git a/LibMultiSpacc/Examples/Common.mk b/LibMultiSpacc/Examples/Common.mk index 0d0460b..d8cbaf1 100644 --- a/LibMultiSpacc/Examples/Common.mk +++ b/LibMultiSpacc/Examples/Common.mk @@ -51,12 +51,8 @@ else ifeq ($(MultiSpacc_Target), NES) endif CC = $(ToolsPrefix)gcc $(CFlags) $(Defines) -Shell = $(shell echo $$SHELL) -AppObjects = $(AppSources:.c=.o) -SpaccObjects = $(SpaccSources:.c=.o) -BuildObjects = $(AppObjects) $(SpaccObjects) -#BuildSources = $(AppSources) $(SpaccSources) -#Objects = $(BuildSources:.c=.o) +BuildSources = $(AppSources) $(SpaccSources) +BuildObjects = $(BuildSources:.c=.o) All all: $(BuildProcess) @@ -73,9 +69,9 @@ __NDS__: cp $(SpaccSources) $(SpaccHeaders) $(VirtualBuildDir)/source/.tmp/ cd $(VirtualBuildDir)/source/.tmp; for i in *; do mv ./$$i ../LibMultiSpacc_$$i; done cp $(AppSources) $(AppHeaders) $(VirtualBuildDir)/source/ - for i in $(VirtualBuildDir)/source/*; do sed -i 's|#include[ \t]"../../LibMultiSpacc/|#include "LibMultiSpacc_|g' $$i; done - for i in $(VirtualBuildDir)/source/*; do sed -i 's|#include[ \t]"../MultiSpacc|#include "LibMultiSpacc_MultiSpacc|g' $$i; done - for i in $(VirtualBuildDir)/source/*; do sed -i 's|#include[ \t]"./|#include "./LibMultiSpacc_|g' $$i; done + for i in $(VirtualBuildDir)/source/*.c $(VirtualBuildDir)/source/*.h; do sed -i 's|#include[ \t]"../../LibMultiSpacc/|#include "LibMultiSpacc_|g' $$i; done + for i in $(VirtualBuildDir)/source/*.c $(VirtualBuildDir)/source/*.h; do sed -i 's|#include[ \t]"../MultiSpacc|#include "LibMultiSpacc_MultiSpacc|g' $$i; done + for i in $(VirtualBuildDir)/source/*.c $(VirtualBuildDir)/source/*.h; do sed -i 's|#include[ \t]"./|#include "LibMultiSpacc_|g' $$i; done cd $(VirtualBuildDir); make __NES__: @@ -85,13 +81,14 @@ __NES__: cp $(SpaccSources) $(SpaccHeaders) $(VirtualBuildDir)/.tmp/ cd $(VirtualBuildDir)/.tmp; for i in *; do mv ./$$i ../LibMultiSpacc_$$i; done cp $(AppSources) $(AppHeaders) $(VirtualBuildDir)/ - for i in $(VirtualBuildDir)/*; do sed -i 's|#include[ \t]"../../LibMultiSpacc/|#include "LibMultiSpacc_|g' $$i; done - for i in $(VirtualBuildDir)/*; do sed -i 's|#include[ \t]"../MultiSpacc|#include "LibMultiSpacc_MultiSpacc|g' $$i; done - for i in $(VirtualBuildDir)/*; do sed -i 's|#include[ \t]"./|#include "./LibMultiSpacc_|g' $$i; done - cp ../../neslib/*.cfg ../../neslib/crt0.o ../../neslib/chr_generic.o ../../neslib/*.lib ../../neslib/*.h $(VirtualBuildDir)/ - echo "AppName='$(AppName)'; Defines='$(Defines)'; AppSources='$(AppSources)'; SpaccSources='$(SpaccSources)'; AppObjects='$(AppObjects)'; BuildObjects='$(BuildObjects)';" > $(VirtualBuildDir)/Make.sh + for i in $(VirtualBuildDir)/*.c $(VirtualBuildDir)/*.h; do sed -i 's|#include[ \t]"../../LibMultiSpacc/|#include "LibMultiSpacc_|g' $$i; done + for i in $(VirtualBuildDir)/*.c $(VirtualBuildDir)/*.h; do sed -i 's|#include[ \t]"../MultiSpacc|#include "LibMultiSpacc_MultiSpacc|g' $$i; done + for i in $(VirtualBuildDir)/*.c $(VirtualBuildDir)/*.h; do sed -i 's|#include[ \t]"./|#include "LibMultiSpacc_|g' $$i; done + cp ../../neslib/*.cfg ../../neslib/crt0.o ../../neslib/*.lib ../../neslib/*.h $(VirtualBuildDir)/ + printf ".segment \"CHARS\"\n\t.incbin \"CHARS.chr\"" > $(VirtualBuildDir)/CHARS.s + echo "AppName='$(AppName)'; Defines='$(Defines)'; ProjectRoot=../..;" > $(VirtualBuildDir)/Make.sh cat ../NES.mk.sh >> $(VirtualBuildDir)/Make.sh - cd $(VirtualBuildDir); $(Shell) ./Make.sh + cd $(VirtualBuildDir); sh ./Make.sh Run run: All ./$(AppName)$(ExeSuffix) diff --git a/LibMultiSpacc/Examples/HelloWorld/CHARS.png b/LibMultiSpacc/Examples/HelloWorld/CHARS.png new file mode 100644 index 0000000000000000000000000000000000000000..d7b9c364e773712c994df845fb475977000d45cd GIT binary patch literal 773 zcmeAS@N?(olHy`uVBq!ia0vp^4Gav73{1>G7Tfe`CP0d@ILO_JVcj{Imp~3nx}&cn z1H;CC?mvmFKt5-HPl)S(hW|hSzQ+mzEwcsp2(R4fzkUky7S)>hmcPPG)y|#Cd360^S5Z>pk302w0uxi_fBMx_ zH1+$cpG-UM>oItXA9!2G7{fNx$L?OteDUl57xi~{w+0=L&C(5eblIj>#=arv=)17B z1%i*+lNg`e+T*oVdfG*quUjUv1?V2%ZK+o>!E{F6!-!+N{2Pj$KMOvH;p9%;b;x?s z`>RabIYmyYPo2qn`#Xoh(XM@Z=NC_wK6E>G`;*<`e`XghYgv5e#vSR?jjqcbmvgA- zs1;7-?O!o{_4{WYGY=eYWqk1@(AtMtv*0FE$J;RBSeG^X%4dZuMkqO6YrFRG#lt7s z6Z%3jFO^9wZ%&gszd7dTnkT2V7DRDy-TZvN@Su0%sZ~Bcg6?Z&J_Jcl{&7Um_r0ut z(dUS1%o7-MI?~=(Gl(*`@fDxlzOS6g`ho9uzXSUsE?j0h#$xin=b*c5QkcZYGfbf! zI#O%4)uj}!e4Hzv-=cljT1x)f;w!~gH#s}p^A`vEJE$FyFXL)3YWT}Bso~eM7rgq% zzpc#SN_X@rVc>P!Aj+N~sKW3}*5ROD@5LK-!U^w6F4iz9bAJ>3#Z$G}I^~VF>@t@8 z#Fz?&IeU-Ho5yhMAM=Clhn3%X1YEE+T)o2SxcNbwC~0P&9iJo~s^~u0cXz9ncH{O{ zkM7yTgfRK;W6tsYW!s=H_Cks4jIG-Np;)QLr2CWmI=`)wTQ219UCk~t+y7C^LGctB zo@<-6K1(+AO-fi~#LRSi?}M4V%nSaVWIy2L$8dbr^p}U0b3dHfz*_U^jq0thg3RKT zS}NKZMqgLG=~=E*BJ // Copyright (c) 2018 Doug Fraker www.nesdoug.com (MIT) - //TilesImg = MultiSpacc_LoadImage( "Tiles.png", Screen, NULL ); + TilesImg = MultiSpacc_LoadImage( "CHARS.png", Screen, NULL ); MultiSpacc_PrintText( "Hello, World!", Screen, &WindowConfig, 2, 2, TilesImg ); MultiSpacc_PrintDebug("[I] Ready!\n"); while(true) { - MultiSpacc_Sprite( 0, spriteX, spriteY, 20/*128*/, TilesImg, Screen ); + MultiSpacc_Sprite( 0, spriteX, spriteY, 1, TilesImg, Screen ); //scroll(spriteX,0); spriteX += accelX; @@ -74,7 +74,7 @@ int main( int argc, char *argv[] ) }; // TODO: Implement cross-platform vblank-wait - //MultiSpacc_Sleep(16); + MultiSpacc_Sleep(16); } return 0; diff --git a/LibMultiSpacc/Examples/HelloWorld/Makefile b/LibMultiSpacc/Examples/HelloWorld/Makefile index 9d63a36..636699b 100644 --- a/LibMultiSpacc/Examples/HelloWorld/Makefile +++ b/LibMultiSpacc/Examples/HelloWorld/Makefile @@ -1 +1 @@ -include ../Common.mk +include ../Common.mk \ No newline at end of file diff --git a/LibMultiSpacc/Examples/HelloWorld/Tiles.png b/LibMultiSpacc/Examples/HelloWorld/Tiles.png deleted file mode 100644 index 80c3c5acccdb8be51066ef930f067ab943f5df92..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 664 zcmV;J0%!e+P)Px#1ZP1_K>z@;j|==^1poj522e~?MgIW*|NsA=7&71h000SaNLh0L01m6=Nb%nAv+0-m96fzG#peLoxQ5CUfb9iiI@VOtVihbW^=@B@Wt`c`#a-cl#HM`JqC zV~7A(P|cu25(m*yClGb4kwq)SgOE9B2tzOWKq2I88qZ>Yi9;N=+nB6Plv0FcVu+WD z8~ys3;A2WHiaC7R>b$m}?Q=URRC8TYh zat8k%w|U$8U}nV8^IDBU=t|E=(Pq)Cm9CJ*z)e+ZcE%!~)e@lH?JrowMv<=g+@Rfe z+`}|UwYsXah$*U=1y2!h0JxasKp_4oWJ#3258ynxh}NUpJPPj!g+Eo;V64T)8|BTdH;>bKv3Z*1_{B=~Tu7PUCD_IW=fAC8 zWRcUj&xFq3E}YV``jQ2iER;j85P1s;bSA#CbnHQbf?CMtt%}DfBpya>&X4FHn5lR@ y6*p7yZYthP#fz!1P$(1%g+ifFC=?3+0pKrLUESe@KQn;<0000Width = 256; + WindowConfig->Height = 240; oam_clear(); pal_all(WindowConfig->Palette); ppu_on_all(); diff --git a/LibMultiSpacc/neslib/.gitignore b/LibMultiSpacc/neslib/.gitignore deleted file mode 100644 index 4c1aeeb..0000000 --- a/LibMultiSpacc/neslib/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -*.o -*.lst -*~ -crt0.lst -neslib2.lib diff --git a/LibMultiSpacc/neslib/neslib.h b/LibMultiSpacc/neslib/neslib.h index b048654..478f140 100644 --- a/LibMultiSpacc/neslib/neslib.h +++ b/LibMultiSpacc/neslib/neslib.h @@ -300,8 +300,12 @@ void __fastcall__ nmi_set_callback(void (*callback)(void)); #ifndef NULL #define NULL 0 #endif -#define TRUE 1 -#define FALSE 0 +#ifndef TRUE + #define TRUE 1 +#endif +#ifndef FALSE + #define FALSE 0 +#endif #define NT_UPD_HORZ 0x40 #define NT_UPD_VERT 0x80 diff --git a/Tools/WindowsRefreshEnv.cmd b/Tools/WindowsRefreshEnv.cmd new file mode 100644 index 0000000..c42cf90 --- /dev/null +++ b/Tools/WindowsRefreshEnv.cmd @@ -0,0 +1,130 @@ +:: Code generously provided by @beatcracker: https://github.com/beatcracker/detect-batch-subshell +@echo off + +setlocal EnableDelayedExpansion + +:: Dequote path to command processor and this script path +set ScriptPath=%~0 +set CmdPath=%COMSPEC:"=% + +:: Get command processor filename and filename with extension +for %%c in (!CmdPath!) do ( + set CmdExeName=%%~nxc + set CmdName=%%~nc +) + +:: Get this process' PID +:: Adapted from: http://www.dostips.com/forum/viewtopic.php?p=22675#p22675 +set "uid=" +for /l %%i in (1 1 128) do ( + set /a "bit=!random!&1" + set "uid=!uid!!bit!" +) + +for /f "tokens=2 delims==" %%i in ( + 'wmic Process WHERE "Name='!CmdExeName!' AND CommandLine LIKE '%%!uid!%%'" GET ParentProcessID /value' +) do ( + rem Get commandline of parent + for /f "tokens=1,2,*" %%j in ( + 'wmic Process WHERE "Handle='%%i'" GET CommandLine /value' + ) do ( + + rem Strip extra CR's from wmic output + rem http://www.dostips.com/forum/viewtopic.php?t=4266 + for /f "delims=" %%x in ("%%l") do ( + rem Dequote path to batch file, if any (3rd argument) + set ParentScriptPath=%%x + set ParentScriptPath=!ParentScriptPath:"=! + ) + + rem Get parent process path + for /f "tokens=2 delims==" %%y in ("%%j") do ( + rem Dequote parent path + set ParentPath=%%y + set ParentPath=!ParentPath:"=! + + rem Handle different invocations: C:\Windows\system32\cmd.exe , cmd.exe , cmd + for %%p in (!CmdPath! !CmdExeName! !CmdName!) do ( + if !ParentPath!==%%p set IsCmdParent=1 + ) + + rem Check if we're running in cmd.exe with /c switch and this script path as argument + if !IsCmdParent!==1 if %%k==/c if "!ParentScriptPath!"=="%ScriptPath%" set IsExternal=1 + ) + ) +) + +if !IsExternal!==1 ( + echo %~nx0 does not work when run from this process. If you're in PowerShell, please 'Import-Module $env:ChocolateyInstall\helpers\chocolateyProfile.psm1' and try again. + exit 1 +) + +endlocal +:: End code from @beatcracker +@echo off +:: +:: RefreshEnv.cmd +:: +:: Batch file to read environment variables from registry and +:: set session variables to these values. +:: +:: With this batch file, there should be no need to reload command +:: environment every time you want environment changes to propagate + +::echo "RefreshEnv.cmd only works from cmd.exe, please install the Chocolatey Profile to take advantage of refreshenv from PowerShell" +echo | set /p dummy="Refreshing environment variables from registry for cmd.exe. Please wait..." + +goto main + +:: Set one environment variable from registry key +:SetFromReg + "%WinDir%\System32\Reg" QUERY "%~1" /v "%~2" > "%TEMP%\_envset.tmp" 2>NUL + for /f "usebackq skip=2 tokens=2,*" %%A IN ("%TEMP%\_envset.tmp") do ( + echo/set "%~3=%%B" + ) + goto :EOF + +:: Get a list of environment variables from registry +:GetRegEnv + "%WinDir%\System32\Reg" QUERY "%~1" > "%TEMP%\_envget.tmp" + for /f "usebackq skip=2" %%A IN ("%TEMP%\_envget.tmp") do ( + if /I not "%%~A"=="Path" ( + call :SetFromReg "%~1" "%%~A" "%%~A" + ) + ) + goto :EOF + +:main + echo/@echo off >"%TEMP%\_env.cmd" + + :: Slowly generating final file + call :GetRegEnv "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" >> "%TEMP%\_env.cmd" + call :GetRegEnv "HKCU\Environment">>"%TEMP%\_env.cmd" >> "%TEMP%\_env.cmd" + + :: Special handling for PATH - mix both User and System + call :SetFromReg "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" Path Path_HKLM >> "%TEMP%\_env.cmd" + call :SetFromReg "HKCU\Environment" Path Path_HKCU >> "%TEMP%\_env.cmd" + + :: Caution: do not insert space-chars before >> redirection sign + echo/set "Path=%%Path_HKLM%%;%%Path_HKCU%%" >> "%TEMP%\_env.cmd" + + :: Cleanup + del /f /q "%TEMP%\_envset.tmp" 2>nul + del /f /q "%TEMP%\_envget.tmp" 2>nul + + :: capture user / architecture + SET "OriginalUserName=%USERNAME%" + SET "OriginalArchitecture=%PROCESSOR_ARCHITECTURE%" + + :: Set these variables + call "%TEMP%\_env.cmd" + + :: Cleanup + del /f /q "%TEMP%\_env.cmd" 2>nul + + :: reset user / architecture + SET "USERNAME=%OriginalUserName%" + SET "PROCESSOR_ARCHITECTURE=%OriginalArchitecture%" + + echo | set /p dummy="Finished." + echo . diff --git a/Tools/pilbmp2nes.py b/Tools/pilbmp2nes.py new file mode 100644 index 0000000..1478274 --- /dev/null +++ b/Tools/pilbmp2nes.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python3 +# +# Bitmap to multi-console CHR converter using Pillow, the +# Python Imaging Library +# +# Copyright 2014-2015 Damian Yerrick +# Copying and distribution of this file, with or without +# modification, are permitted in any medium without royalty +# provided the copyright notice and this notice are preserved. +# This file is offered as-is, without any warranty. +# +from __future__ import with_statement, print_function, unicode_literals +from PIL import Image +from time import sleep + +def formatTilePlanar(tile, planemap, hflip=False, little=False): + """Turn a tile into bitplanes. + +Planemap opcodes: +10 -- bit 1 then bit 0 of each tile +0,1 -- planar interleaved by rows +0;1 -- planar interlaved by planes +0,1;2,3 -- SNES/PCE format + +""" + hflip = 7 if hflip else 0 + if (tile.size != (8, 8)): + return None + pixels = list(tile.getdata()) + pixelrows = [pixels[i:i + 8] for i in range(0, 64, 8)] + if hflip: + for row in pixelrows: + row.reverse() + out = bytearray() + + planemap = [[[int(c) for c in row] + for row in plane.split(',')] + for plane in planemap.split(';')] + # format: [tile-plane number][plane-within-row number][bit number] + + # we have five (!) nested loops + # outermost: separate planes + # within separate planes: pixel rows + # within pixel rows: row planes + # within row planes: pixels + # within pixels: bits + for plane in planemap: + for pxrow in pixelrows: + for rowplane in plane: + rowbits = 1 + thisrow = bytearray() + for px in pxrow: + for bitnum in rowplane: + rowbits = (rowbits << 1) | ((px >> bitnum) & 1) + if rowbits >= 0x100: + thisrow.append(rowbits & 0xFF) + rowbits = 1 + out.extend(thisrow[::-1] if little else thisrow) + return bytes(out) + +def pilbmp2chr(im, tileWidth=8, tileHeight=8, + formatTile=lambda im: formatTilePlanar(im, "0;1")): + """Convert a bitmap image into a list of byte strings representing tiles.""" + im.load() + (w, h) = im.size + outdata = [] + for mt_y in range(0, h, tileHeight): + for mt_x in range(0, w, tileWidth): + metatile = im.crop((mt_x, mt_y, + mt_x + tileWidth, mt_y + tileHeight)) + for tile_y in range(0, tileHeight, 8): + for tile_x in range(0, tileWidth, 8): + tile = metatile.crop((tile_x, tile_y, + tile_x + 8, tile_y + 8)) + data = formatTile(tile) + outdata.append(data) + return outdata + +def parse_argv(argv): + from optparse import OptionParser + parser = OptionParser(usage="usage: %prog [options] [-i] INFILE [-o] OUTFILE") + parser.add_option("-i", "--image", dest="infilename", + help="read image from INFILE", metavar="INFILE") + parser.add_option("-o", "--output", dest="outfilename", + help="write CHR data to OUTFILE", metavar="OUTFILE") + parser.add_option("-W", "--tile-width", dest="tileWidth", + help="set width of metatiles", metavar="HEIGHT", + type="int", default=8) + parser.add_option("--packbits", dest="packbits", + help="use PackBits RLE compression", + action="store_true", default=False) + parser.add_option("-H", "--tile-height", dest="tileHeight", + help="set height of metatiles", metavar="HEIGHT", + type="int", default=8) + parser.add_option("-1", dest="planes", + help="set 1bpp mode (default: 2bpp NES)", + action="store_const", const="0", default="0;1") + parser.add_option("--planes", dest="planes", + help="set the plane map (1bpp: 0) (NES: 0;1) (GB: 0,1) (SMS:0,1,2,3) (TG16/SNES: 0,1;2,3) (MD: 3210)") + parser.add_option("--hflip", dest="hflip", + help="horizontally flip all tiles (most significant pixel on right)", + action="store_true", default=False) + parser.add_option("--little", dest="little", + help="reverse the bytes within each row-plane (needed for GBA and a few others)", + action="store_true", default=False) + parser.add_option("--add", dest="addamt", + help="value to add to each pixel", + type="int", default=0) + parser.add_option("--add0", dest="addamt0", + help="value to add to pixels of color 0 (if different)", + type="int", default=None) + (options, args) = parser.parse_args(argv[1:]) + + tileWidth = int(options.tileWidth) + if tileWidth <= 0: + raise ValueError("tile width '%d' must be positive" % tileWidth) + + tileHeight = int(options.tileHeight) + if tileHeight <= 0: + raise ValueError("tile height '%d' must be positive" % tileHeight) + + # Fill unfilled roles with positional arguments + argsreader = iter(args) + try: + infilename = options.infilename + if infilename is None: + infilename = next(argsreader) + except StopIteration: + raise ValueError("not enough filenames") + + outfilename = options.outfilename + if outfilename is None: + try: + outfilename = next(argsreader) + except StopIteration: + outfilename = '-' + if outfilename == '-': + import sys + if sys.stdout.isatty(): + raise ValueError("cannot write CHR to terminal") + + addamt, addamt0 = options.addamt, options.addamt0 + if addamt0 is None: addamt0 = addamt + + return (infilename, outfilename, tileWidth, tileHeight, + options.packbits, options.planes, options.hflip, options.little, + addamt, addamt0) + +argvTestingMode = True + +def make_stdout_binary(): + """Ensure that sys.stdout is in binary mode, with no newline translation.""" + + # Recipe from + # http://code.activestate.com/recipes/65443-sending-binary-data-to-stdout-under-windows/ + # via http://stackoverflow.com/a/2374507/2738262 + if sys.platform == "win32": + import os, msvcrt + msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) + +def main(argv=None): + import sys + if argv is None: + argv = sys.argv + if (argvTestingMode and len(argv) < 2 + and sys.stdin.isatty() and sys.stdout.isatty()): + argv.extend(input('args:').split()) + try: + (infilename, outfilename, tileWidth, tileHeight, + usePackBits, planes, hflip, little, + addamt, addamt0) = parse_argv(argv) + except Exception as e: + sys.stderr.write("%s: %s\n" % (argv[0], str(e))) + sys.exit(1) + + im = Image.open(infilename) + + # Subpalette shift + if addamt or addamt0: + px = bytearray(im.getdata()) + for i in range(len(px)): + thispixel = px[i] + px[i] = thispixel + (addamt if thispixel else addamt0) + im.putdata(px) + + outdata = pilbmp2chr(im, tileWidth, tileHeight, + lambda im: formatTilePlanar(im, planes, hflip, little)) + outdata = b''.join(outdata) + if usePackBits: + from packbits import PackBits + sz = len(outdata) % 0x10000 + outdata = PackBits(outdata).flush().tostring() + outdata = b''.join([chr(sz >> 8), chr(sz & 0xFF), outdata]) + + # Write output file + outfp = None + try: + if outfilename != '-': + outfp = open(outfilename, 'wb') + else: + outfp = sys.stdout + make_stdout_binary() + outfp.write(outdata) + finally: + if outfp and outfilename != '-': + outfp.close() + +if __name__=='__main__': + main() diff --git a/Tools/python3.sh b/Tools/python3.sh new file mode 100644 index 0000000..779423a --- /dev/null +++ b/Tools/python3.sh @@ -0,0 +1,5 @@ +#!/bin/sh +[ "$(shell uname --operating-system)" = "Msys" ] \ +&& cmd //c "$(cygpath --windows "$(dirname "$(realpath "$0")")/WindowsRefreshEnv.cmd") && python3 $@" \ +|| python3 $@ \ +; \ No newline at end of file