crabb

aya

Oct 27th, 2020
934
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --[[
  2. *********************************************
  3. * AYA CHARACTER CONVERTER                   *
  4.                                             *
  5. * for use on nintendo GBA and DS            *
  6. * by suwacrab                               *
  7. *********************************************
  8. --]]
  9.  
  10. local aya = {}
  11. aya.__index = aya
  12.  
  13. local printf = function(str,...) print(str:format(...)) end
  14. --|==== lookup tables
  15. aya.pal_formats = {
  16.     -- h == hex,b == binary
  17.     -- > AGB palette formats
  18.     rgb5a1  = 0;        -- | AGGGGGRRRRRBBBBB   : 16-bit    : direct    : 65536-color
  19.     -- > NTR palette formats
  20.     a3i5        = 1;        -- | IIIAAAAA                   : 5-bit     : indexed   : 32-color w/ alpha
  21.     a5i3        = 2;        -- | IIIIIAAA                   : 3-bit     : indexed   : 8-color w/ alpha
  22. }
  23. aya.clr_formats = {
  24. --                              -- | bit format : bit cnt   : type      : color count
  25.     pal2        = 0;        -- | 76543210       : 1-bit     : indexed   : 2-color
  26.     pal4        = 1;        -- | 33221100       : 2-bit     : indexed   : 4-color
  27.     pal16   = 2;        -- | 11110000       : 4-bit     : indexed   : 16-color
  28.     pal256  = 3;        -- | 00000000       : 8-bit     :   indexed : 256-color
  29.     rgb16   = 4;        -- | 16-bit RGB : 16-bit    : direct    : 65536-color
  30. }
  31.  
  32. local fwrite = function(fname,str,mode)
  33.     assert(str,("attempted to write nil to file %s"):format(fname))
  34.     local f = io.open(fname,mode or "wb")
  35.     f:write(str); f:close();
  36.     printf("\t* FWRITE [%08XH] (%-32s)",#str,fname)
  37. end
  38. --|==== misc functions
  39. local strclamp = function(str,len,fill)
  40.     return (
  41.         #str < len and
  42.             str..(fill or " "):rep(len-#str)
  43.         or #str > len and
  44.             str:sub(1,len)
  45.         or str
  46.     )
  47. end
  48. local strwrite = function(str,fname,mode)
  49.     fwrite(fname,str,mode)
  50. end
  51. string.clamp = strclamp
  52. string.write = strwrite
  53. --|==== byte functions
  54. local tochr = string.char
  55.  
  56. local function chrtonum_a16(a,i)
  57.     return a[i] | (a[i+1]<<8)
  58. end
  59. local function chrtonum_a32(a,i)
  60.     return chrtonum_a16(a,i) | (chrtonum_a16(a,i+2)<<16)
  61. end
  62.  
  63. local tochr_8 = function(n)
  64.     return tochr(n&0xFF) end
  65. local tochr_16 = function(n)
  66.     return tochr_8(n)..tochr_8(n>>8) end
  67. local tochr_32 = function(n)
  68.     return tochr_16(n)..tochr_16(n>>16) end
  69.  
  70. --|==== read functions
  71. aya.new = function(name)
  72.     local bun = setmetatable({},aya)
  73.     bun:set_name(name)
  74.     return bun
  75. end
  76. aya.set_name = function(bun,name)
  77.     name = name or "sadza"
  78.     bun.name = name:clamp(7,' ').."\0"
  79.     return bun
  80. end
  81. aya.load_new = function(name,fname)
  82.     local bun = aya.new(name)
  83.     bun:load_file(fname)
  84.     return bun
  85. end
  86. aya.load_str = function(bun,str)
  87.     -- read bytes
  88.     local bytes = {} do
  89.         local barray = { str:byte(1,#str) }
  90.         for i = 1,#str do bytes[i-1] = barray[i] end
  91.     end
  92.     -- read bitmap file header
  93.     local header = {} do
  94.         header.type = string.char(bytes[0],bytes[1]) -- 2
  95.         header.size = chrtonum_a32(bytes,0x0002) -- 4
  96.         header.res0 = chrtonum_a16(bytes,0x0006) -- 2
  97.         header.res1 = chrtonum_a16(bytes,0x0008) -- 2
  98.         header.data = chrtonum_a32(bytes,0x000A) -- 2
  99.     end
  100.     -- read DIB header
  101.     local dibheader = {} do
  102.         local dib_offset = 0x000E
  103.         dibheader.headsize = chrtonum_a32(bytes,dib_offset+0x0000) -- 4
  104.         dibheader.width =    chrtonum_a32(bytes,dib_offset+0x0004) -- 4
  105.         dibheader.height =   chrtonum_a32(bytes,dib_offset+0x0008) -- 4
  106.         dibheader.planes =   chrtonum_a16(bytes,dib_offset+0x000C) -- 2
  107.         dibheader.bpp =      chrtonum_a16(bytes,dib_offset+0x000E) -- 2
  108.         dibheader.compress = chrtonum_a32(bytes,dib_offset+0x0010) -- 4
  109.         dibheader.size =     chrtonum_a32(bytes,dib_offset+0x0014) -- 4
  110.         dibheader.resW =     chrtonum_a32(bytes,dib_offset+0x0018) -- 4
  111.         dibheader.resH =     chrtonum_a32(bytes,dib_offset+0x001C) -- 4
  112.         dibheader.clrcnt =   chrtonum_a32(bytes,dib_offset+0x0020) -- 4
  113.         -- > fix dummy 0
  114.         if dibheader.size == 0 then
  115.             local width = dibheader.width
  116.             local height = dibheader.height
  117.             dibheader.size = (dibheader.bpp * width*height)>>3
  118.             print("new size: ",dibheader.size)
  119.         end
  120.     end
  121.     -- read color table
  122.     local palette = {} do
  123.         if dibheader.bpp <= 8 then
  124.             local pal_offset = 0x000E + dibheader.headsize
  125.             for i = 0,(2^dibheader.bpp)-1 do
  126.                 local clr = {};
  127.                 -- > keep in mind: colors are stored in BGRX format.
  128.                 -- > B,G,R,X are 1 byte long, respectively.
  129.                 -- > X is unused and is (probably) 0.
  130.                 clr[1] = bytes[pal_offset + (i*4) + 0x0002]
  131.                 clr[2] = bytes[pal_offset + (i*4) + 0x0001]
  132.                 clr[3] = bytes[pal_offset + (i*4) + 0x0000]
  133.                 clr[4] = bytes[pal_offset + (i*4) + 0x0003]
  134.                 palette[i] = clr
  135.                 --print(i,table.unpack(clr))
  136.             end
  137.         end
  138.     end
  139.     -- read pixel data
  140.     local bmpdata_pix = {}
  141.     local bmpdata_chr = {} do
  142.         local bmp_offset = header.data
  143.         local bmp_size = dibheader.size
  144.         -- > write char data
  145.         for i = 0,bmp_size-1 do
  146.             local chr = bytes[bmp_offset + i]
  147.             assert(chr,"BMP character data is nil...")
  148.             bmpdata_chr[i] = chr
  149.         end
  150.         -- read the pixel data
  151.         -- > 1bpp
  152.         if dibheader.bpp == 1 then
  153.             -- > read the (flipped) pixel data
  154.             local pixdat_flip = {} do
  155.                 local index = 0
  156.                 for i = 0,bmp_size-1 do
  157.                     local chr = bmpdata_chr[i]
  158.                     for c = 0,7 do
  159.                         local p = ((chr>>c)&1)
  160.                         pixdat_flip[index] = p; index = index + 1
  161.                     end
  162.                 end
  163.             end
  164.             -- > read the unflipped pixel data
  165.             local width = dibheader.width
  166.             local height = dibheader.height
  167.             for y = 0,height-1 do
  168.                 for x = 0,width-1 do
  169.                     -- > read pixel from flipped bitmap
  170.                     local py = (height - y)-1
  171.                     local pix = pixdat_flip[x + py*width]
  172.                     -- > write to real bitmap
  173.                     bmpdata_pix[x + y*width] = pix
  174.                 end
  175.             end
  176.         end
  177.         -- > 4bpp
  178.         if dibheader.bpp == 4 then
  179.             -- > read the (flipped) pixel data
  180.             local pixdat_flip = {} do
  181.                 local index = 0
  182.                 for i = 0,bmp_size-1 do
  183.                     local chr = bmpdata_chr[i]
  184.                     local p0 = chr>>4;  -- 1st pixel is in high nybble, for some reason
  185.                     local p1 = chr&0xF; -- 2nd pixel is in low nybble
  186.                     pixdat_flip[index] = p0; index = index+1;
  187.                     pixdat_flip[index] = p1; index = index+1;
  188.                 end
  189.             end
  190.             -- > read the unflipped pixel data
  191.             local width = dibheader.width
  192.             local height = dibheader.height
  193.             for y = 0,height-1 do
  194.                 for x = 0,width-1 do
  195.                     -- > read pixel from flipped bitmap
  196.                     local py = (height - y)-1
  197.                     local pix = pixdat_flip[x + py*width]
  198.                     -- > write to real bitmap
  199.                     bmpdata_pix[x + y*width] = pix
  200.                 end
  201.             end
  202.         end
  203.     end
  204.     -- return
  205.     bun.bmpdata_pix = bmpdata_pix
  206.     bun.bmpdata_chr = bmpdata_chr
  207.     bun.palette = palette
  208.     bun.dibheader = dibheader
  209.     bun.header = header
  210.     bun.bmpbytes = bytes
  211.     return bun
  212. end
  213. aya.load_file = function(bun,fname)
  214.     local f = io.open(fname,"rb")
  215.     local str = f:read("*all")
  216.     f:close();
  217.     bun:load_str(str)
  218.     return bun
  219. end
  220.  
  221. --|==== pixel functions
  222. aya.pix = function(bun,x,y,c)
  223.     local ind = x + y * bun:width()
  224.     if c then bun.bmpdata_pix[ind] = c end
  225.     return bun.bmpdata_pix[ind]
  226. end
  227.  
  228. aya.width = function(bun) return bun.dibheader.width end
  229. aya.height = function(bun) return bun.dibheader.height end
  230. aya.dimensions = function(bun) return bun:width(),bun:height() end
  231.  
  232. --|==== write functions
  233. local rgb5a1 = function(r,g,b,a)
  234.     return r | (g<<5) | (b<<10) | (a * 0x8000) end
  235. local rgba4 = function(r,g,b,a)
  236.     return (a<<12) | (r<<8) | (g<<4) | (b) end
  237. local rgba8 = function(r,g,b,a)
  238.     return (a<<24) | (r<<16) | (g<<8) | (b) end
  239.  
  240. -- > misc saving
  241. aya.pixpack_tile = function(bun,tsize)
  242.     -- vars
  243.     tsize = tsize or 8
  244.     local width = bun:width()
  245.     local height = bun:height()
  246.     -- separate image into [tsize,tsize] tiles
  247.     local tiles = {} do
  248.         for y = 0,(height/tsize)-1 do
  249.             for x = 0,(width/tsize)-1 do
  250.                 local tilebuf = {}
  251.                 -- > write tile into buffer
  252.                 for ty = 0,tsize-1 do
  253.                     for tx = 0,tsize-1 do
  254.                         local c = bun:pix(tx + x*tsize,ty + y*tsize)
  255.                         tilebuf[tx + ty*tsize] = c
  256.                     end
  257.                 end
  258.                 -- > send buffer to tile table
  259.                 tiles[#tiles+1] = tilebuf
  260.             end
  261.         end
  262.     end
  263.    
  264.     return tiles
  265. end
  266. aya.save_pal_dat = function(bun,fmt)
  267.     -- to store the converted palette
  268.     local str = {}
  269.     -- accepted palette formats
  270.     local accepted_formats = {
  271.         [aya.pal_formats.rgb5a1]=true,
  272.     }
  273.     -- convert all 15 or so colors
  274.     for i = 0,15 do
  275.         local r,g,b = table.unpack(bun.palette[i])
  276.         local clr = 0;
  277.         -- if the format isn't recognized, error.
  278.         assert(accepted_formats[fmt],"palette format not recognized")
  279.         -- set the color according to the format
  280.         -- > RGB5A1
  281.         if fmt == aya.pal_formats.rgb5a1 then
  282.             clr = (i==0) and rgb5a1(0,0,0,0) or rgb5a1(0,0,0,1)
  283.             clr = clr | rgb5a1(r>>3,g>>3,b>>3,0)
  284.             str[#str+1] = tochr_16(clr)
  285.         -- > RGBA4
  286.         elseif fmt == aya.pal_formats.rgba4 then
  287.             clr = (i==0) and 0x0000 or 0xF000
  288.             clr = clr | rgba4(r>>4,g>>4,b>>4,0)
  289.         -- > RGBA8
  290.         elseif fmt == aya.pal_formats.rgba8 then
  291.             clr = (i==0) and rgba8(0,0,0,0) or rgba8(0,0,0,255)
  292.             clr = clr | rgba8(r,g,b,0)
  293.             str[#str+1] = tochr_32(clr)
  294.         end
  295.     end
  296.     return table.concat(str)
  297. end
  298.  
  299. -- > 1bpp saving
  300. aya.save_1bpp_tile_dat = function(bun,tsize)
  301.     -- vars
  302.     tsize = tsize or 8
  303.     local width = bun:width()
  304.     local height = bun:height()
  305.     -- separate image into [tsize,tsize] tiles
  306.     local tiles = bun:pixpack_tile(tsize)
  307.     -- write tiles to string
  308.     local str = {}
  309.     for t = 1,#tiles do
  310.         local tile = tiles[t]
  311.         for i = 0,(tsize^2)-1,8 do
  312.             local b = {}
  313.             for c = 0,7 do b[c] = tile[i+c] end
  314.             local chr = 0
  315.             for c = 0,7 do chr = chr | (b[7-c]<<c) end
  316.             str[#str+1] = string.char(chr)
  317.         end
  318.     end
  319.     return table.concat(str)
  320. end
  321. aya.save_1bpp_tile = function(bun,fmt,tsize)
  322.     -- write palette
  323.     print("writing palette...")
  324.     local palette = bun:save_pal_dat(fmt)
  325.     -- write data
  326.     print("writing tiled character data...")
  327.     assert(tsize and tsize>0,"tile size is incorrect.")
  328.     local data = bun:save_1bpp_tile_dat(tsize)
  329.     -- get name
  330.     print("writing image...")
  331.     local name = bun.name or ("SDZACHR")
  332.     name = name:clamp(7," ").."\0"
  333.     -- get dimensions
  334.     -- > new width is going to be the tile size
  335.     -- > new height is (width*height)/tsize
  336.     -- > so 32x32 with tsize 8 is 8x128
  337.     local width = tsize
  338.     local height = (bun:width()*bun:height())/tsize
  339.     -- write header
  340.     local header = {
  341.         -- > $0000 : name
  342.         name;
  343.         -- > $0008 : size
  344.         tochr_32(width); -- width
  345.         tochr_32(height); -- height
  346.         -- > $0010 : data size
  347.         tochr_32(#data);
  348.         -- > $0014 : color format
  349.         tochr_32(aya.clr_formats.pal2);
  350.         -- > $0018 : palette format
  351.         tochr_32(fmt);
  352.         -- > $001C : character offset
  353.         tochr_32(0x0024 + 0x0000);
  354.         -- > $0020 : palette offset
  355.         tochr_32(0x0024 + #data);
  356.     }
  357.     -- write string
  358.     local str_header = table.concat(header)
  359.     local str_data = data
  360.     local str_palette = palette
  361.     local str_img = str_header..str_data..str_palette
  362.     print(("header size: %04X"):format(#str_header))
  363.     return str_img
  364. end
  365.  
  366. -- > 2bpp saving
  367. aya.save_2bpp_tile_dat = function(bun,tsize)
  368.     -- vars
  369.     tsize = tsize or 8
  370.     local width = bun:width()
  371.     local height = bun:height()
  372.     -- separate image into [tsize,tsize] tiles
  373.     local tiles = bun:pixpack_tile(tsize)
  374.     -- write tiles to string
  375.     local str = {}
  376.     for t = 1,#tiles do
  377.         local tile = tiles[t]
  378.         for i = 0,(tsize^2)-1,8 do
  379.             local bp = {}
  380.             for p = 0,1 do bp[p] = {} end
  381.             for c = 0,7 do bp[0][c],bp[1][c] = tile[i+c]&1,tile[i+c]>>1 end
  382.             for p = 0,1 do
  383.                 local chr = 0
  384.                 for c = 0,7 do chr = chr | (bp[p][c]<<(7-c)) end
  385.                 str[#str+1] = tochr_8(chr)
  386.             end
  387.         end
  388.     end
  389.     return table.concat(str)
  390. end
  391. aya.save_2bpp_tile = function(bun,fmt,tsize)
  392.     -- write palette
  393.     print("writing palette...")
  394.     local palette = bun:save_pal_dat(fmt)
  395.     -- write data
  396.     print("writing tiled character data...")
  397.     assert(tsize and tsize>0,"tile size is incorrect.")
  398.     local data = bun:save_2bpp_tile_dat(tsize)
  399.     -- get name
  400.     print("writing image...")
  401.     local name = bun.name or ("SDZACHR")
  402.     name = name:clamp(7," ").."\0"
  403.     -- get dimensions
  404.     -- > new width is going to be the tile size
  405.     -- > new height is (width*height)/tsize
  406.     -- > so 32x32 with tsize 8 is 8x128
  407.     local width = tsize
  408.     local height = (bun:width()*bun:height())/tsize
  409.     -- write header
  410.     local header = {
  411.         -- > $0000 : name
  412.         name;
  413.         -- > $0008 : size
  414.         tochr_32(width); -- width
  415.         tochr_32(height); -- height
  416.         -- > $0010 : data size
  417.         tochr_32(#data);
  418.         -- > $0014 : color format
  419.         tochr_32(aya.clr_formats.pal4);
  420.         -- > $0018 : palette format
  421.         tochr_32(fmt);
  422.         -- > $001C : character offset
  423.         tochr_32(0x0024 + 0x0000);
  424.         -- > $0020 : palette offset
  425.         tochr_32(0x0024 + #data);
  426.     }
  427.     -- write string
  428.     local str_header = table.concat(header)
  429.     local str_data = data
  430.     local str_palette = palette
  431.     local str_img = str_header..str_data..str_palette
  432.     print(("header size: %04X"):format(#str_header))
  433.     return str_img
  434. end
  435.  
  436. -- > 4bpp saving
  437. aya.save_4bpp_tile_imm = function(bun,tile,tsize)
  438.     local str = {}
  439.     for i = 0,(tsize^2)-1,2 do
  440.         local p0 = tile[i]
  441.         local p1 = tile[i+1]
  442.         str[#str+1] = tochr_8(p0 | (p1<<4))
  443.     end
  444.     return table.concat(str)
  445. end
  446. aya.save_4bpp_tile_dat = function(bun,tsize)
  447.     -- vars
  448.     tsize = tsize or 8
  449.     local width = bun:width()
  450.     local height = bun:height()
  451.     -- separate image into [tsize,tsize] tiles
  452.     local tiles = bun:pixpack_tile(tsize)
  453.     -- write tiles to string
  454.     local str = {}
  455.     for t = 1,#tiles do
  456.         local tile = tiles[t]
  457.         str[#str+1] = bun:save_4bpp_tile_imm(tile,tsize)
  458.     end
  459.     return table.concat(str)
  460. end
  461. aya.save_4bpp_tile_map = function(bun,tsize)
  462.     -- convert image to an array of 8x8px tiles
  463.     local tiles = bun:pixpack_tile(tsize)
  464.     -- vars
  465.     local used = {}     -- | used tiles
  466.     local mapstr = {}   -- | tilemap data
  467.     local datstr = {}   -- | character data
  468.     local swpindx = 0   -- | current tile recycle index
  469.     -- shit loop
  470.     for i = 1,#tiles do
  471.         -- > convert the current 8x8 tile
  472.         local tile = bun:save_4bpp_tile_imm(tiles[i],tsize)
  473.         -- > if tile hasn't been used yet, add it
  474.         if not used[tile] then
  475.             used[tile] = swpindx
  476.             mapstr[#mapstr+1] = tochr_16(swpindx)
  477.             datstr[#datstr+1] = tile
  478.             swpindx = swpindx+1
  479.         -- > otherwise, use the used tile.
  480.         else
  481.             mapstr[#mapstr+1] = tochr_16(used[tile])
  482.         end
  483.     end
  484.     -- > convert map & char data to strings & return
  485.     mapstr = table.concat(mapstr)
  486.     datstr = table.concat(datstr)
  487.     return mapstr,datstr
  488. end
  489. aya.save_4bpp_tile = function(bun,fmt,tsize,map)
  490.     printf("-------- [ SAVING '%-7s' ] --------",bun.name)
  491.     local dt = os.clock()
  492.     -- write palette
  493.     dt = os.clock()
  494.     io.write("\t* writing palette... ")
  495.     local palette = bun:save_pal_dat(fmt)
  496.     printf("(%.8f)",os.clock() - dt)
  497.     dt = os.clock()
  498.     -- write data
  499.     io.write("\t* writing tiled character data... ")
  500.     assert(tsize and tsize>0,"tile size is incorrect.")
  501.     local data = bun:save_4bpp_tile_dat(tsize)
  502.     printf("(%.8f)",os.clock() - dt)
  503.     dt = os.clock()
  504.     -- write map
  505.     local map_dat;
  506.     if map then
  507.         io.write("\t* writing map... ")
  508.         map_dat,data = bun:save_4bpp_tile_map(tsize)
  509.         printf("(%.8f)",os.clock() - dt)
  510.     end
  511.     -- get name
  512.     dt = os.clock()
  513.     io.write("\t* writing image... ")
  514.     bun:set_name(bun.name)
  515.     -- get dimensions
  516.     -- > new width is going to be the tile size
  517.     -- > new height is (width*height)/tsize
  518.     -- > so 32x32 with tsize 8 is 8x128
  519.     local width = tsize
  520.     local height = (bun:width()*bun:height())/tsize
  521.     -- write header
  522.     local header = {
  523.         -- > $0000 : 0H : name
  524.         bun.name;
  525.         -- > $0008 : 2H : size
  526.         tochr_32(width); -- width
  527.         tochr_32(height); -- height
  528.         tochr_32(map and bun:width()/tsize or 0); -- map width
  529.         tochr_32(map and bun:height()/tsize or 0); -- map height
  530.         -- > $0018 : 7H : data size
  531.         tochr_32(#data);
  532.         -- > $001C : 8H : map size
  533.         tochr_32(map and #map_dat/2 or 0);
  534.         -- > $0020 : 9H : color format,palette format
  535.         tochr_32(aya.clr_formats.pal16 | (fmt<<16));
  536.         -- > $0024 : AH : character offset
  537.         tochr_32(0x0030 + 0x0000);
  538.         -- > $0028 : BH : palette offset
  539.         tochr_32(0x0030 + #data);
  540.         -- > $002C : CH : map offset
  541.         tochr_32(0x0030 + #data + #palette);
  542.     }
  543.     -- write string
  544.     local str_header = table.concat(header)
  545.     local str_data = data
  546.     local str_palette = palette
  547.     local str_map = map_dat or ""
  548.     local str_img = str_header..str_data..str_palette..str_map
  549.     printf("(%.8f)",os.clock() - dt)
  550.     return str_img
  551. end
  552. aya.save_4bpp_dat = function(bun)
  553.     local str = {}
  554.     local width,height = bun:dimensions()
  555.     local bmpdata_pix = bun.bmpdata_pix
  556.     for i = 0,(width*height)-1,2 do
  557.         local p0,p1 = bmpdata_pix[i],bmpdata_pix[i+1]
  558.         str[#str+1] = string.char(p0 | (p1<<4))
  559.     end
  560.     return table.concat(str)
  561. end
  562. aya.save_4bpp = function(bun,fmt)
  563.     -- write palette
  564.     local palette = bun:save_pal_4bpp_dat(fmt)
  565.     -- write data
  566.     local data = bun:save_4bpp_dat()
  567.     -- get name
  568.     bun:set_name(bun.name)
  569.     -- write header
  570.     local header = {
  571.         -- > $0000 : name
  572.         bun.name;
  573.         -- > $0010 : size
  574.         tochr_32(bun:width()); -- width
  575.         tochr_32(bun:height()); -- height
  576.         -- > $0018 : data size
  577.         tochr_32(#data);
  578.         -- > $0014 : color format
  579.         tochr_32(aya.clr_formats.pal16);
  580.         -- > $0018 : palette format
  581.         tochr_32(fmt);
  582.         -- > $001C : character offset
  583.         tochr_32(0x002C + 0x0000);
  584.         -- > $0020 : palette offset
  585.         tochr_32(0x002C + #data);
  586.     }
  587.     -- write string
  588.     local str_header = table.concat(header)
  589.     local str_data = data
  590.     local str_palette = palette
  591.     local str_img = str_header..str_data..str_palette
  592.     return str_img
  593. end
  594.  
  595. -- > 8bpp saving
  596. aya.save_8bpp_tile_map = function(bun,tsize)
  597.     -- convert image to an array of 8x8px tiles
  598.     local tiles = bun:pixpack_tile(tsize)
  599.     -- vars
  600.     local used = {}     -- | used tiles
  601.     local mapstr = {}   -- | tilemap data
  602.     local datstr = {}   -- | character data
  603.     local swpindx = 0   -- | current tile recycle index
  604.     -- shit loop
  605.     for i = 1,#tiles do
  606.         -- > convert the current tile
  607.         local tile = bun:save_8bpp_tile_imm(tiles[i],tsize)
  608.         -- > if tile hasn't been used yet, add it
  609.         if not used[tile] then
  610.             used[tile] = swpindx
  611.             mapstr[#mapstr+1] = tochr_16(swpindx)
  612.             datstr[#datstr+1] = tile
  613.             swpindx = swpindx+1
  614.         -- > otherwise, use the used tile.
  615.         else
  616.             mapstr[#mapstr+1] = tochr_16(used[tile])
  617.         end
  618.     end
  619.     -- > convert map & char data to strings & return
  620.     mapstr = table.concat(mapstr)
  621.     datstr = table.concat(datstr)
  622.     return mapstr,datstr
  623. end
  624. aya.save_8bpp_tile_imm = function(bun,tile,tsize)
  625.     local str = {}
  626.     for i = 0,(tsize^2)-1,2 do
  627.         str[#str+1] = tochr_8(tile[i])
  628.     end
  629.     return table.concat(str)
  630. end
  631. aya.save_8bpp_tile_dat = function(bun,tsize)
  632.     local tiles = bun:pixpack_tile(tsize)
  633.     local width,height = bun:dimensions()
  634.     -- write tiles to string
  635.     local str = {}
  636.     for t = 1,#tiles do
  637.         local tile = tiles[t]
  638.         str[#str+1] = bun:save_8bpp_tile_imm(tile,tsize)
  639.     end
  640.     return table.concat(str)
  641. end
  642. aya.save_8bpp_tile = function(bun,fmt,tsize,map)
  643.     local dt = os.clock()
  644.     printf("-------- [ SAVING '%-7s' ] --------",bun.name)
  645.     -- write palette
  646.     io.write("\t* writing palette... ")
  647.         local palette = bun:save_pal_dat(fmt)
  648.         printf("(%.8f)",os.clock() - dt)
  649.         dt = os.clock()
  650.     -- write data
  651.     io.write("\t* writing tiled character data... ")
  652.         assert(tsize and tsize>0,"tile size is incorrect.")
  653.         local data = bun:save_8bpp_tile_dat(tsize)
  654.         printf("(%.8f)",os.clock() - dt)
  655.         dt = os.clock()
  656.     -- write map
  657.     local map_dat;
  658.     if map then
  659.         -- insert map function here lul
  660.         map_dat,data = bun:save_8bpp_tile_map(tsize)
  661.     end
  662.     -- get name
  663.     bun:set_name(bun.name)
  664.     -- get dimensions
  665.     local width = tsize
  666.     local height = (bun:width()*bun:height())/tsize
  667.     -- write header
  668.     local header = {
  669.         -- > 0000H : name
  670.         bun.name;
  671.         -- > 0008H : image dimensions
  672.         tochr_32(width);
  673.         tochr_32(height);
  674.         tochr_32(map and bun:width()/tsize or 0);
  675.         tochr_32(map and bun:height()/tsize or 0);
  676.         -- > 0018H : data sizes
  677.         tochr_32(#data),tochr_32(map and #map_dat or 0);
  678.         -- > 0020H : color & palette format
  679.         tochr_32(aya.clr_formats.pal16 | (fmt<<16));
  680.         -- > 0024H : character offset
  681.         tochr_32(0x0024 + 0x0000);
  682.         -- > 0028H : palette offset
  683.         tochr_32(0x0024 + #data);
  684.         -- > 002CH : map offset
  685.         tochr_32(0x0024 + #data + #palette);
  686.     }
  687.     -- write string
  688.     local str_header = table.concat(header)
  689.     local str_data = data
  690.     local str_palette = palette
  691.     local str_map = map_dat or ""
  692.     local str_img = str_header..str_data..str_palette..str_map
  693.     return str_img
  694. end
  695. aya.save_8bpp_dat = function(bun)
  696.     local str = {}
  697.     local width,height = bun:dimensions()
  698.     local pixdat = bun.bmpdata_pix
  699.     for i = 0,(width*height)-1 do
  700.         str[#str+1] = tochr_8(pixdat[i])
  701.     end
  702.     return table.concat(str)
  703. end
  704. aya.save_8bpp = function(bun,fmt)
  705.     -- write palette
  706.     io.write("writing palette... ")
  707.     local palette = bun:save_pal_dat(fmt)
  708.     -- write data
  709.     io.write("writing character data...\n")
  710.     local data = bun:save_8bpp_dat()
  711.     -- get name
  712.     local name = bun.name or ("SDZACHR")
  713.     name = name:clamp(7," ").."\0"
  714.     -- write header
  715.     local header = {
  716.         -- > 0000H : name
  717.         name;
  718.         -- > 0008H : image dimensions
  719.         tochr_32(bun:width());
  720.         tochr_32(bun:height());
  721.         -- > 0010H : data size
  722.         tochr_32(#data);
  723.         -- > 0014H : color format
  724.         tochr_32(aya.clr_formats.pal16);
  725.         -- > 0018H : palette format
  726.         tochr_32(fmt);
  727.         -- > 001CH : character offset
  728.         tochr_32(0x0024 + 0x0000);
  729.         -- > 0020H : palette offset
  730.         tochr_32(0x0024 + #data);
  731.     }
  732.     -- write string
  733.     local str_header = table.concat(header)
  734.     local str_data = data
  735.     local str_palette = palette
  736.     local str_img = str_header..str_data..str_palette
  737.     print(("header size: %04X"):format(#str_header))
  738.     return str_img
  739. end
  740.  
  741. return aya
  742.  
RAW Paste Data