mirror of
https://gitlab.com/octospacc/MultiSpaccSDK
synced 2025-03-01 10:17:53 +01:00
Update scripts and NES compatibility, add PNG to NES CHR convert
This commit is contained in:
parent
9be90d7629
commit
fa7bc447fc
@ -51,12 +51,8 @@ else ifeq ($(MultiSpacc_Target), NES)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
CC = $(ToolsPrefix)gcc $(CFlags) $(Defines)
|
CC = $(ToolsPrefix)gcc $(CFlags) $(Defines)
|
||||||
Shell = $(shell echo $$SHELL)
|
BuildSources = $(AppSources) $(SpaccSources)
|
||||||
AppObjects = $(AppSources:.c=.o)
|
BuildObjects = $(BuildSources:.c=.o)
|
||||||
SpaccObjects = $(SpaccSources:.c=.o)
|
|
||||||
BuildObjects = $(AppObjects) $(SpaccObjects)
|
|
||||||
#BuildSources = $(AppSources) $(SpaccSources)
|
|
||||||
#Objects = $(BuildSources:.c=.o)
|
|
||||||
|
|
||||||
All all: $(BuildProcess)
|
All all: $(BuildProcess)
|
||||||
|
|
||||||
@ -73,9 +69,9 @@ __NDS__:
|
|||||||
cp $(SpaccSources) $(SpaccHeaders) $(VirtualBuildDir)/source/.tmp/
|
cp $(SpaccSources) $(SpaccHeaders) $(VirtualBuildDir)/source/.tmp/
|
||||||
cd $(VirtualBuildDir)/source/.tmp; for i in *; do mv ./$$i ../LibMultiSpacc_$$i; done
|
cd $(VirtualBuildDir)/source/.tmp; for i in *; do mv ./$$i ../LibMultiSpacc_$$i; done
|
||||||
cp $(AppSources) $(AppHeaders) $(VirtualBuildDir)/source/
|
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/*.c $(VirtualBuildDir)/source/*.h; 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/*.c $(VirtualBuildDir)/source/*.h; 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]"./|#include "LibMultiSpacc_|g' $$i; done
|
||||||
cd $(VirtualBuildDir); make
|
cd $(VirtualBuildDir); make
|
||||||
|
|
||||||
__NES__:
|
__NES__:
|
||||||
@ -85,13 +81,14 @@ __NES__:
|
|||||||
cp $(SpaccSources) $(SpaccHeaders) $(VirtualBuildDir)/.tmp/
|
cp $(SpaccSources) $(SpaccHeaders) $(VirtualBuildDir)/.tmp/
|
||||||
cd $(VirtualBuildDir)/.tmp; for i in *; do mv ./$$i ../LibMultiSpacc_$$i; done
|
cd $(VirtualBuildDir)/.tmp; for i in *; do mv ./$$i ../LibMultiSpacc_$$i; done
|
||||||
cp $(AppSources) $(AppHeaders) $(VirtualBuildDir)/
|
cp $(AppSources) $(AppHeaders) $(VirtualBuildDir)/
|
||||||
for i in $(VirtualBuildDir)/*; 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]"../../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)/*.c $(VirtualBuildDir)/*.h; 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
|
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/chr_generic.o ../../neslib/*.lib ../../neslib/*.h $(VirtualBuildDir)/
|
cp ../../neslib/*.cfg ../../neslib/crt0.o ../../neslib/*.lib ../../neslib/*.h $(VirtualBuildDir)/
|
||||||
echo "AppName='$(AppName)'; Defines='$(Defines)'; AppSources='$(AppSources)'; SpaccSources='$(SpaccSources)'; AppObjects='$(AppObjects)'; BuildObjects='$(BuildObjects)';" > $(VirtualBuildDir)/Make.sh
|
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
|
cat ../NES.mk.sh >> $(VirtualBuildDir)/Make.sh
|
||||||
cd $(VirtualBuildDir); $(Shell) ./Make.sh
|
cd $(VirtualBuildDir); sh ./Make.sh
|
||||||
|
|
||||||
Run run: All
|
Run run: All
|
||||||
./$(AppName)$(ExeSuffix)
|
./$(AppName)$(ExeSuffix)
|
||||||
|
BIN
LibMultiSpacc/Examples/HelloWorld/CHARS.png
Normal file
BIN
LibMultiSpacc/Examples/HelloWorld/CHARS.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 773 B |
@ -27,7 +27,7 @@ int main( int argc, char *argv[] )
|
|||||||
MultiSpacc_Surface *Screen;
|
MultiSpacc_Surface *Screen;
|
||||||
MultiSpacc_Surface *TilesImg;
|
MultiSpacc_Surface *TilesImg;
|
||||||
|
|
||||||
WindowConfig.Width = 256;
|
WindowConfig.Width = 320;
|
||||||
WindowConfig.Height = 240;
|
WindowConfig.Height = 240;
|
||||||
WindowConfig.Bits = 16;
|
WindowConfig.Bits = 16;
|
||||||
memcpy( WindowConfig.Palette, PALETTE, 32 );
|
memcpy( WindowConfig.Palette, PALETTE, 32 );
|
||||||
@ -45,13 +45,13 @@ int main( int argc, char *argv[] )
|
|||||||
|
|
||||||
// Bitmap font borrowed from: <https://github.com/nesdoug/01_Hello/blob/master/Alpha.chr>
|
// Bitmap font borrowed from: <https://github.com/nesdoug/01_Hello/blob/master/Alpha.chr>
|
||||||
// Copyright (c) 2018 Doug Fraker www.nesdoug.com (MIT)
|
// 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_PrintText( "Hello, World!", Screen, &WindowConfig, 2, 2, TilesImg );
|
||||||
MultiSpacc_PrintDebug("[I] Ready!\n");
|
MultiSpacc_PrintDebug("[I] Ready!\n");
|
||||||
|
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
MultiSpacc_Sprite( 0, spriteX, spriteY, 20/*128*/, TilesImg, Screen );
|
MultiSpacc_Sprite( 0, spriteX, spriteY, 1, TilesImg, Screen );
|
||||||
//scroll(spriteX,0);
|
//scroll(spriteX,0);
|
||||||
|
|
||||||
spriteX += accelX;
|
spriteX += accelX;
|
||||||
@ -74,7 +74,7 @@ int main( int argc, char *argv[] )
|
|||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Implement cross-platform vblank-wait
|
// TODO: Implement cross-platform vblank-wait
|
||||||
//MultiSpacc_Sleep(16);
|
MultiSpacc_Sleep(16);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 664 B |
@ -1,7 +1,8 @@
|
|||||||
#!/dev/null
|
#!/dev/null
|
||||||
set -e
|
set -e
|
||||||
|
SdkRoot="${ProjectRoot}/../../.."
|
||||||
|
|
||||||
# ${SpaccSources} ${AppSources} ${SpaccObjects} ${AppObjects} chr_generic.s chr_generic.o crt0.o
|
sh "${SdkRoot}/Tools/python3.sh" "${SdkRoot}/Tools/pilbmp2nes.py" -i "${ProjectRoot}/CHARS.png" -o ./CHARS.chr
|
||||||
|
|
||||||
for File in *.c
|
for File in *.c
|
||||||
do cc65 -Oirs --target nes ${File} ${Defines}
|
do cc65 -Oirs --target nes ${File} ${Defines}
|
||||||
|
@ -98,4 +98,11 @@ void MultiSpacc_Sprite( int id, int x, int y, int sprite, MultiSpacc_Surface *Ti
|
|||||||
ppu_wait_frame();
|
ppu_wait_frame();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MultiSpacc_Sleep( int milliseconds ){}
|
||||||
|
|
||||||
|
MultiSpacc_Surface *MultiSpacc_LoadImage( char FilePath[], MultiSpacc_Surface *Screen, Uint32 *ColorKey )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
@ -64,6 +64,7 @@
|
|||||||
#define MultiSpacc_Surface int
|
#define MultiSpacc_Surface int
|
||||||
#define MultiSpacc_Event int
|
#define MultiSpacc_Event int
|
||||||
int MultiSpacc_UpdateWindowSurface( MultiSpacc_Window *Window );
|
int MultiSpacc_UpdateWindowSurface( MultiSpacc_Window *Window );
|
||||||
|
void MultiSpacc_Sleep( int milliseconds );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct MultiSpacc_SurfaceConfig {
|
typedef struct MultiSpacc_SurfaceConfig {
|
||||||
|
@ -22,6 +22,8 @@ MultiSpacc_Window *MultiSpacc_SetWindow( MultiSpacc_SurfaceConfig *WindowConfig
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MultiSpacc_Target_NES
|
#ifdef MultiSpacc_Target_NES
|
||||||
|
WindowConfig->Width = 256;
|
||||||
|
WindowConfig->Height = 240;
|
||||||
oam_clear();
|
oam_clear();
|
||||||
pal_all(WindowConfig->Palette);
|
pal_all(WindowConfig->Palette);
|
||||||
ppu_on_all();
|
ppu_on_all();
|
||||||
|
5
LibMultiSpacc/neslib/.gitignore
vendored
5
LibMultiSpacc/neslib/.gitignore
vendored
@ -1,5 +0,0 @@
|
|||||||
*.o
|
|
||||||
*.lst
|
|
||||||
*~
|
|
||||||
crt0.lst
|
|
||||||
neslib2.lib
|
|
@ -300,8 +300,12 @@ void __fastcall__ nmi_set_callback(void (*callback)(void));
|
|||||||
#ifndef NULL
|
#ifndef NULL
|
||||||
#define NULL 0
|
#define NULL 0
|
||||||
#endif
|
#endif
|
||||||
#define TRUE 1
|
#ifndef TRUE
|
||||||
#define FALSE 0
|
#define TRUE 1
|
||||||
|
#endif
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#define NT_UPD_HORZ 0x40
|
#define NT_UPD_HORZ 0x40
|
||||||
#define NT_UPD_VERT 0x80
|
#define NT_UPD_VERT 0x80
|
||||||
|
130
Tools/WindowsRefreshEnv.cmd
Normal file
130
Tools/WindowsRefreshEnv.cmd
Normal file
@ -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 .
|
209
Tools/pilbmp2nes.py
Normal file
209
Tools/pilbmp2nes.py
Normal file
@ -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()
|
5
Tools/python3.sh
Normal file
5
Tools/python3.sh
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
[ "$(shell uname --operating-system)" = "Msys" ] \
|
||||||
|
&& cmd //c "$(cygpath --windows "$(dirname "$(realpath "$0")")/WindowsRefreshEnv.cmd") && python3 $@" \
|
||||||
|
|| python3 $@ \
|
||||||
|
;
|
Loading…
x
Reference in New Issue
Block a user