diff --git a/Makefile b/Makefile index b32946f..83335b6 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,7 @@ SOURCES := source DATA := data INCLUDES := include -ICON := resources/icon48.png +ICON := resources/icon.png #--------------------------------------------------------------------------------- # options for code generation @@ -62,9 +62,8 @@ LIBS := -lctru -lm #--------------------------------------------------------------------------------- LIBDIRS := $(CTRULIB) ./lib -MAKEROM = $(TOPDIR)/tools/makerom -BANNER_TOOL = $(TOPDIR)/tools/banner -CREATE_BANNER = python create.py +MAKEROM = $(TOPDIR)/tools/makerom +BANNERTOOL = $(TOPDIR)/tools/bannertool #--------------------------------------------------------------------------------- @@ -148,22 +147,20 @@ $(OUTPUT_D) : $(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).elf : $(OFILES) -banner.bnr: $(TOPDIR)/resources/icon24.png $(TOPDIR)/resources/icon48.png $(TOPDIR)/resources/banner.png - cd $(BANNER_TOOL); $(CREATE_BANNER) "$(APP_TITLE)" "$(APP_TITLE)" "$(APP_AUTHOR)" $(TOPDIR)/resources/icon24.png $(TOPDIR)/resources/icon48.png $(TOPDIR)/resources/banner.png $(TOPDIR)/$(BUILD)/icon.icn $(TOPDIR)/$(BUILD)/banner.bnr - @echo "built ... banner files" - -icon.icn: banner.bnr +banner.bnr: $(TOPDIR)/resources/banner.png $(TOPDIR)/resources/audio.bcwav + $(BANNERTOOL) $(TOPDIR)/resources/banner.png $(TOPDIR)/resources/audio.bcwav $(TOPDIR)/$(BUILD)/banner.bnr + @echo "built ... banner" stripped.elf: $(OUTPUT).elf @cp $(OUTPUT).elf stripped.elf @$(PREFIX)strip stripped.elf -$(OUTPUT).cia: stripped.elf $(TOPDIR)/resources/cia.rsf banner.bnr icon.icn - $(MAKEROM) -f cia -o $(OUTPUT).cia -rsf $(TOPDIR)/resources/cia.rsf -target t -exefslogo -elf stripped.elf -icon icon.icn -banner banner.bnr +$(OUTPUT).cia: stripped.elf $(TOPDIR)/resources/cia.rsf banner.bnr $(OUTPUT).smdh + $(MAKEROM) -f cia -o $(OUTPUT).cia -rsf $(TOPDIR)/resources/cia.rsf -target t -exefslogo -elf stripped.elf -icon $(OUTPUT).smdh -banner banner.bnr @echo "built ... $(notdir $@)" -$(OUTPUT).3ds: stripped.elf $(TOPDIR)/resources/3ds.rsf banner.bnr icon.icn - $(MAKEROM) -f cci -o $(OUTPUT).3ds -rsf $(TOPDIR)/resources/3ds.rsf -target d -exefslogo -elf stripped.elf -icon icon.icn -banner banner.bnr +$(OUTPUT).3ds: stripped.elf $(TOPDIR)/resources/3ds.rsf banner.bnr $(OUTPUT).smdh + $(MAKEROM) -f cci -o $(OUTPUT).3ds -rsf $(TOPDIR)/resources/3ds.rsf -target d -exefslogo -elf stripped.elf -icon $(OUTPUT).smdh -banner banner.bnr @echo "built ... $(notdir $@)" #--------------------------------------------------------------------------------- diff --git a/tools/banner/audio.bcwav b/resources/audio.bcwav similarity index 100% rename from tools/banner/audio.bcwav rename to resources/audio.bcwav diff --git a/resources/icon48.png b/resources/icon.png similarity index 100% rename from resources/icon48.png rename to resources/icon.png diff --git a/resources/icon24.png b/resources/icon24.png deleted file mode 100644 index 80cc816..0000000 Binary files a/resources/icon24.png and /dev/null differ diff --git a/tools/banner/.gitignore b/tools/banner/.gitignore deleted file mode 100644 index ed8ebf5..0000000 --- a/tools/banner/.gitignore +++ /dev/null @@ -1 +0,0 @@ -__pycache__ \ No newline at end of file diff --git a/tools/banner/LICENSE.txt b/tools/banner/LICENSE.txt deleted file mode 100644 index 3ae15f9..0000000 --- a/tools/banner/LICENSE.txt +++ /dev/null @@ -1,26 +0,0 @@ -Copyright (c) 2013, Snailface -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. -* Neither the name of the darm developer(s) nor the names of its - contributors may be used to endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. diff --git a/tools/banner/compress.py b/tools/banner/compress.py deleted file mode 100644 index 46f1895..0000000 --- a/tools/banner/compress.py +++ /dev/null @@ -1,255 +0,0 @@ -# used http://code.google.com/p/u-lzss/source/browse/trunk/js/lib/ulzss.js as -# a guide -from sys import stderr - -from collections import defaultdict -from operator import itemgetter -from struct import pack, unpack - -class SlidingWindow: - # The size of the sliding window - size = 4096 - - # The minimum displacement. - disp_min = 2 - - # The hard minimum — a disp less than this can't be represented in the - # compressed stream. - disp_start = 1 - - # The minimum length for a successful match in the window - match_min = 1 - - # The maximum length of a successful match, inclusive. - match_max = None - - def __init__(self, buf): - self.data = buf - self.hash = defaultdict(list) - self.full = False - - self.start = 0 - self.stop = 0 - #self.index = self.disp_min - 1 - self.index = 0 - - assert self.match_max is not None - - def next(self): - if self.index < self.disp_start - 1: - self.index += 1 - return - - if self.full: - olditem = self.data[self.start] - assert self.hash[olditem][0] == self.start - self.hash[olditem].pop(0) - - item = self.data[self.stop] - self.hash[item].append(self.stop) - self.stop += 1 - self.index += 1 - - if self.full: - self.start += 1 - else: - if self.size <= self.stop: - self.full = True - - def advance(self, n=1): - """Advance the window by n bytes""" - for _ in range(n): - self.next() - - def search(self): - match_max = self.match_max - match_min = self.match_min - - counts = [] - indices = self.hash[self.data[self.index]] - for i in indices: - matchlen = self.match(i, self.index) - if matchlen >= match_min: - disp = self.index - i - #assert self.index - disp >= 0 - #assert self.disp_min <= disp < self.size + self.disp_min - if self.disp_min <= disp: - counts.append((matchlen, -disp)) - if matchlen >= match_max: - #assert matchlen == match_max - return counts[-1] - - if counts: - match = max(counts, key=itemgetter(0)) - return match - - return None - - def match(self, start, bufstart): - size = self.index - start - - if size == 0: - return 0 - - matchlen = 0 - it = range(min(len(self.data) - bufstart, self.match_max)) - for i in it: - if self.data[start + (i % size)] == self.data[bufstart + i]: - matchlen += 1 - else: - break - return matchlen - -class NLZ10Window(SlidingWindow): - size = 4096 - - match_min = 3 - match_max = 3 + 0xf - -class NLZ11Window(SlidingWindow): - size = 4096 - - match_min = 3 - match_max = 0x111 + 0xFFFF - -class NOverlayWindow(NLZ10Window): - disp_min = 3 - -def _compress(input, windowclass=NLZ10Window): - """Generates a stream of tokens. Either a byte (int) or a tuple of (count, - displacement).""" - - window = windowclass(input) - - i = 0 - while True: - if len(input) <= i: - break - match = window.search() - if match: - yield match - #if match[1] == -283: - # raise Exception(match, i) - window.advance(match[0]) - i += match[0] - else: - yield input[i] - window.next() - i += 1 - -def packflags(flags): - n = 0 - for i in range(8): - n <<= 1 - try: - if flags[i]: - n |= 1 - except IndexError: - pass - return n - -def chunkit(it, n): - buf = [] - for x in it: - buf.append(x) - if n <= len(buf): - yield buf - buf = [] - if buf: - yield buf - -def compress(input, out): - # header - out.write(pack("B", packflags(flags))) - - for t in tokens: - if type(t) == tuple: - count, disp = t - count -= 3 - disp = (-disp) - 1 - assert 0 <= disp < 4096 - sh = (count << 12) | disp - out.write(pack(">H", sh)) - else: - out.write(pack(">B", t)) - - length += 1 - length += sum(2 if f else 1 for f in flags) - - # padding - padding = 4 - (length % 4 or 4) - if padding: - out.write(b'\xff' * padding) - -def compress_nlz11(input, out): - # header - out.write(pack("B", packflags(flags))) - length += 1 - - for t in tokens: - if type(t) == tuple: - count, disp = t - disp = (-disp) - 1 - #if disp == 282: - # raise Exception - assert 0 <= disp <= 0xFFF - if count <= 1 + 0xF: - count -= 1 - assert 2 <= count <= 0xF - sh = (count << 12) | disp - out.write(pack(">H", sh)) - length += 2 - elif count <= 0x11 + 0xFF: - count -= 0x11 - assert 0 <= count <= 0xFF - b = count >> 4 - sh = ((count & 0xF) << 12) | disp - out.write(pack(">BH", b, sh)) - length += 3 - elif count <= 0x111 + 0xFFFF: - count -= 0x111 - assert 0 <= count <= 0xFFFF - l = (1 << 28) | (count << 12) | disp - out.write(pack(">L", l)) - length += 4 - else: - raise ValueError(count) - else: - out.write(pack(">B", t)) - length += 1 - - # padding - padding = 4 - (length % 4 or 4) - if padding: - out.write(b'\xff' * padding) - -def dump_compress_nlz11(input, out): - # body - length = 0 - def dump(): - for t in _compress(input, windowclass=NLZ11Window): - if type(t) == tuple: - yield t - from pprint import pprint - pprint(list(dump())) - -if __name__ == '__main__': - from sys import stdout, argv - data = open(argv[1], "rb").read() - stdout = stdout.detach() - #compress(data, stdout) - compress_nlz11(data, stdout) - - #dump_compress_nlz11(data, stdout) \ No newline at end of file diff --git a/tools/banner/create.py b/tools/banner/create.py deleted file mode 100644 index ea39d22..0000000 --- a/tools/banner/create.py +++ /dev/null @@ -1,163 +0,0 @@ -from PIL import Image, ImageDraw -from io import BytesIO -from compress import compress_nlz11 -from struct import pack -import sys - -longtitle=sys.argv[1] -shortitle=sys.argv[2] -publisher=sys.argv[3] - -# fixed variables; not likely these will be used in this context, but here just in case. -visibility =1 -autoBoot =0 -use3D =1 -requireEULA =0 -autoSaveOnExit=0 -extendedBanner=0 -gameRatings =0 -useSaveData =1 -recordAppUsage=0 -disableSaveBU =0 - -def make_icon(file, size): - f=open(file,'rb') - image=Image.open(f) - posit=open('map' + str(size) + 'x' + str(size) + '.bin','rb') - - w=image.size[0] - h=image.size[1] - n=w*w - i=[0]*(n*2) - - if w != h: - print("width, height unequal") - f.close() - sys.exit(1) - if w != size: - print("sides need to be " + str(size) + " pixels") - f.close() - sys.exit(1) - - dump=list(image.getdata()) - - - pos=0 - - for x in range(n): - p1=ord(posit.read(1)) - p2=ord(posit.read(1)) - pos=p1+(p2<<8) - - r=dump[x][0]>>3 - g=dump[x][1]>>2 - b=dump[x][2]>>3 - - i[pos<<1]=(g&7)<<5| b - i[(pos<<1)+1]=(r)<<3 | g>>3 - - f.close() - posit.close() - return bytearray(i) - -def make_banner(file): - f=open(file,'rb') - image=Image.open(f) - if image.size[0] != 256 or image.size[1] != 128: - f.close() - print("ERROR: Image must be exactly 256 x 128. Abort.") - sys.exit(4) - - hdr=open("header.bin","rb") - - posit=open('map256x128.bin','rb') - n=256*128 - i=[0]*(n*2) - cbmdhdr=bytearray(b"\x43\x42\x4D\x44\x00\x00\x00\x00\x88"+(b"\x00"*0x7B)) - - dump=list(image.getdata()) - pos=0 - - for x in range(n): - p1=ord(posit.read(1)) - p2=ord(posit.read(1)) - pos=p1+(p2<<8) - - r=dump[x][0]>>4 - g=dump[x][1]>>4 - b=dump[x][2]>>4 - a=dump[x][3]>>4 - - i[pos<<1]= (b<<4) | a - i[(pos<<1)+1]= (r<<4) | g - - - buf=hdr.read() - hdr.close() - - out = BytesIO() - compress_nlz11(buf+bytearray(i), out) - l=bytearray(out.getvalue()) - length=len(l)+136 - - pad=16-(length%16) - l+=bytearray([0]*pad) - length+=pad - - for c in range(4): - cbmdhdr+=pack("B", length & 255) - length=length>>8 - - cbmdhdr+=l - - f.close() - posit.close() - return bytearray(cbmdhdr) - -def make_audio(): - # TODO: Convert WAV file. - bcwav1=open("audio.bcwav","rb") - bcwav=bcwav1.read() - bcwav1.close() - return bytearray(bcwav) - -ctp1=make_icon(sys.argv[4], 24) -ctp2=make_icon(sys.argv[5], 48) -bcwav=make_audio() -cbmd=make_banner(sys.argv[6]) - -icn=open(sys.argv[7],"wb") -bnr=open(sys.argv[8],"wb") - -header=bytearray(b"\x53\x4D\x44\x48\x00\x00\x00\x00")+bytearray(b"\x00"*0x1FF8)+bytearray(b"\x00\x00\x00\x00\x00\x00\x00\x00\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x00\x00\x00\x00\xFF\xFF\xFF\x7F\x31\x48\x62\x64\x99\x99\x99\x19\x91\x18\x62\x64\xA5\x01\x00\x00\x00\x01\x00\x00\x00\x00\x80\x3F\x32\x41\x79\x24\x00\x00\x00\x00\x00\x00\x00\x00") - -header[0x2028]=(visibility | autoBoot<<1 | use3D<<2 | requireEULA<<3 | autoSaveOnExit<<4 | extendedBanner<<5 | gameRatings<<6 | useSaveData<<7) -header[0x2029]=(recordAppUsage | disableSaveBU<<2) - -offset=8 -pos=0 - -for x in range(11): - for c in longtitle: - header[offset+pos*2]=ord(longtitle[pos]) - pos+=1 - pos=0 - offset+=0x80 - for c in shortitle: - header[offset+pos*2]=ord(shortitle[pos]) - pos+=1 - pos=0 - offset+=0x100 - for c in publisher: - header[offset+pos*2]=ord(publisher[pos]) - pos+=1 - pos=0 - offset+=0x80 - -header+=(ctp1+ctp2) - -icn.write(header) -bnr.write(cbmd+bcwav) - -bnr.close() -icn.close() \ No newline at end of file diff --git a/tools/banner/header.bin b/tools/banner/header.bin deleted file mode 100644 index 64cfb76..0000000 Binary files a/tools/banner/header.bin and /dev/null differ diff --git a/tools/banner/map24x24.bin b/tools/banner/map24x24.bin deleted file mode 100644 index 8960b2c..0000000 Binary files a/tools/banner/map24x24.bin and /dev/null differ diff --git a/tools/banner/map256x128.bin b/tools/banner/map256x128.bin deleted file mode 100644 index 69a6934..0000000 Binary files a/tools/banner/map256x128.bin and /dev/null differ diff --git a/tools/banner/map48x48.bin b/tools/banner/map48x48.bin deleted file mode 100644 index 225d53e..0000000 Binary files a/tools/banner/map48x48.bin and /dev/null differ diff --git a/tools/bannertool b/tools/bannertool new file mode 100755 index 0000000..f882b20 Binary files /dev/null and b/tools/bannertool differ