Views: 994,319,776
17 users online: Duraner Hawkeye,  Eevee, Golden Yoshi, Ice Man, Infinity, kurtistrydiz, lol121, Murphmario, NGB, NikSik1, RollingRigatonis,  Segment1Zone2, SilentSnake20, Soul Storm, Souldbminer, TheJank, YouFailMe - Guests: 110 - Bots: 157 Users: 54,516 (2,079 active)
Latest: theokayguy
Tip: Check this thread for a list of SMW sound effects.
Not logged in.
[SNES Homebrew] Bad Apple!! (updated)
Forum Index - Donut Plains - Creation Corner - [SNES Homebrew] Bad Apple!! (updated)
Pages: « 1 2 3 » Link
I get the whole compression thing now. I am assuming Ladida is talking about Lunar Compress. However, I can't find commands for it. It tells me what parameters to set, but not what the options are.
I'm assuming you're using the pre-compiled binary from The parameters say

recomp.exe FileToRecompress FileToSaveAs/InsertTo OffsetToSave(h) Format1 Format2

The documentation is addmitedly pretty stinky, in that it only exists in the included source code, not in the Readme. This kinda makes sense for the original Lunar Compress, since it was distributed as a DLL, but for the precompiled version on, they really should have included that in the Readme. Anyways, here is what I found in LunarDLL.h:


unsigned int Format           - compression format (see table below).
unsigned int Format2          - must be zero unless otherwise stated.


 LC_LZ2    SMW [G]         Almost identical to LZ1.  You can use Format2=1 
           SMW2 [G]        to auto-convert 3bpp to 4bpp graphics.
           Zelda3 [D]


And the actual defines can be found in LundarDLL.def:


#define LC_LZ2 1


So based on this, I'm assuming what you'd need would be something along those lines:

recomp.exe my_image.bin ba0000.bin 0 1 0

Feel free to visit my website/blog - it's updated rarely, but it looks pretty cool!
The compiler still crashes. I might put this project on the shelf for now, I don't want keep bugging you with questions. I am just a teenager with almost no experience programming assembly. Many thanks for your help though!
i recommend against just replacing the bin files

files.txt incsrc's all the bins, grouped under different org's (because bankcrossing is annoying). i used a paithong script to add up the filesizes for subsequent bins, and if it went over 64kb, i'd split it off and add a different org. so essentially, files.txt is the output for that script. if the filesize changes for one of the bins, then it might make the last file in the bank cross into the next bank, thus kapooting the assembly. not sure if this is the exact issue youre having

if you need the actual script... i think its this one? might be python 2. better if you write your own script tho (and not use my lolcode)

import os

count = 0
initbank = 0x410000

with open("incbins.txt", "a") as incbinmaker:
	while count <= 6573:
		incbinmaker.write("dl ba{}\n".format(str(count).zfill(4)))
		count += 1
	count = 0
	while count <= 6573:
		currentbank = 0
		while 1:
			if (count > 6573) or ((currentbank + os.path.getsize("ba{}.bin".format(str(count).zfill(4)))) > 0x10000):
				incbinmaker.write("ba{0}: incbin ba{0}.bin\n".format(str(count).zfill(4)))
				currentbank += os.path.getsize("ba{}.bin".format(str(count).zfill(4)))
				count += 1
		initbank += 0x10000

for mass-compressing the bin files in the first place, i basically ran rpghacker's script but in a large batch and had to leave something heavy on the spacebar because lunar compress requires keypress to quit #lm{specpal}
so... i managed to get 20fps working on this!

rom direct download

raw source direct download
see source on github

youtube link for lazy

it required a few things:
1. fastrom
2. running the decompressor's block moves in fast ram (aka the dma registers)
3. rewrite of the decompressor to accomodate the new changes. i ended up just writing my own
4. sardine-packing the frames so they fit evenly in the banks rather than leaving a bunch of space at the end
5. arranging the tiles vertically rather than horizontally because it compresses better. which makes sense in retrospect. but the tilemap is kookier
6. asar 1.8! because of nifty stuff like dpbase and a nonbroken exhirom mapper (original broken one being my fault...)
7. optimizing and automating the process of video -> compressed bins + brr. was a pita before but now its ezpz one script. no more fucking batch files god bless python

speaking of, i never really detailed the process of converting the video. i used to use virtualdub and irfanview but now its simpler and more command liney. here is the process i used to create the audio data:

1. ffmpeg to extract audio and convert to 16bit WAV.
settings: -ss 0:00:00.3 -acodec pcm_s16le -ac 1 -ar 32000
the starting timecode is to solve a timing discrepancy. the rest forces output to 32kHz single-channel 16bit signed PCM

2. brr tools' brr encoder to convert WAV to BRR.
settings: -a0.9
this slightly lowers the amplitude of the soundwave. if left at the default, the DSP will clip it

3. custom script to insert 0x2E0 bytes of empty space every 0xFD20 bytes, due to how the audio HDMA is set up
script itself (NO BULLY):
out = bytearray()
with open("./out.brr","rb") as infile:
    sample =
    start = 0
    end = 0x10000-0x2E0
    while len(sample[start:end]) == 0x10000-0x2E0:
        start += 0x10000-0x2E0
        end += 0x10000-0x2E0
with open("./badapple_32khz.brr","wb") as outfile:

SNES does audio at a maximum of 32kHz (32000Hz), which means 32,000 samples per second, which means 32 samples per millisecond. the (NTSC) SNES renders video at 60Hz, which means 60 frames per second, which means 1 frame per 16.66666666666(etc) milliseconds. basically, the math isnt nice. in order to match the framerate, 17ms of audio is uploaded one frame (to a buffer in ARAM), then 17ms the next frame, then 16ms on the third frame. 16ms of (BRR) audio is 288 bytes, and 17ms of (BRR) audio is 306 bytes. this 17.17.16 pattern is repeated until it fills a bank (0x10000 bytes). since indirect HDMA cant cross bank boundaries, this means the pattern will leave some space at the end of each bank (specifically, 0x2E0 bytes)

here is the process i used to create the video data:
1. ffmpeg to extract video and resize/convert to 256x192 PNG.
settings: -filter:v fps=fps=20 -s 256x192
framerate is changed to 20fps (from original 30), and video is resized to 256x192 (from original 512x384, maintaining aspect ratio)

now, for each image:
2. imagemagick to convert to PCX
settings: +dither -depth 8 -remap colortable.pcx
disable dither (or it won't compress very well), lower bitdepth to 8bpp (for pcx2snes), and use a colormap to force the image to use one of 4 colors (black, dark gray, light gray, white). the colormap is included in the source

3. pcx2snes to convert to snes format
settings: -n -s8 -c4 -o0
no border, 8x8 blocks, and 4-colors per block (aka 2bpp). we dont need a palette output

4. custom script to rearrange the 8x8 blocks vertically (as in, store the tiles per-column rather than per-row)
the frames compress better this way, however it requires a slightly more complicated tilemap
the script itself (note that it needs to run for each frame, also again NO BULLY):
with open("./out.pic", "r+b") as infile:
    srcdata =
    fslice = 0x0
    eslice = 0x10
    destdata = bytearray()
    for count1 in range(0,32):
        for count2 in range(0,24):
            temp = srcdata[fslice:eslice]
            fslice += 0x200
            eslice += 0x200
        fslice = (fslice&0x1FF)+0x10
        eslice = (eslice&0x1FF)+0x10

5. Lunar Compress to compress via LC_LZ2
settings: 0 1 0

another custom script is then used to allocate each frame to a suitable bank, so that each bank can be packed like republicans packed the supreme court (specifically, the largest files are allocated first, then the smaller ones). although there is space in banks 40-7F, frames stored there wont be accessed as quickly as frames stored in 80-FF (due to fastrom). however, only smaller frames are more likely to be stored there; shouldnt be an issue. the script is included in the source (in the video folder)

preliminary testing shows that 30fps is IMPOSSIBLE with LZ2, even with the new decompressor i wrote and with optimizing the tile data and with all the free space now available. i have ideas for improving it (basically a custom LZ2 format), but that's for another day

i can rest for now
Pretty cool, nice improvement! 👍
And thanks for adding the detailed instructions. That will definitely be useful for someone.

Feel free to visit my website/blog - it's updated rarely, but it looks pretty cool!
Pages: « 1 2 3 » Link
Forum Index - Donut Plains - Creation Corner - [SNES Homebrew] Bad Apple!! (updated)

The purpose of this site is not to distribute copyrighted material, but to honor one of our favourite games.

Copyright © 2005 - 2022 - SMW Central
Legal Information - Privacy Policy - Link To Us


Follow Us On

  • YouTube
  • Twitch
  • Twitter


  • Super Mario Bros. X Community
  • Mario Fan Games Galaxy
  • sm64romhacks