Skip to content

Instantly share code, notes, and snippets.

@windwakr
Last active December 8, 2025 20:42
Show Gist options
  • Select an option

  • Save windwakr/9a2c1d5a8f0806f00a2a67a02a1ae665 to your computer and use it in GitHub Desktop.

Select an option

Save windwakr/9a2c1d5a8f0806f00a2a67a02a1ae665 to your computer and use it in GitHub Desktop.
generates wav files for use with Wappy Dog (Wappy --> DS)
# Generates wav files for Wappy Dog for Wappy-->DS communication
# Sources: US8814627B2 / Game RE
# The game samples the mic at 33,513,982 / 1519 = ~22063Hz
import itertools
import math
import wave
import os
path = "./wappy wavs"
if not os.path.exists(path):
os.makedirs(path)
def genSquare(rate, freq, length):
wave = []
for i in range(int(length * rate)):
sample = math.sin(2.0 * freq * math.pi * i / rate)
if sample > 0.0:
sample = 128+32
else:
sample = 128-32
wave.append(sample)
return bytearray(wave)
def genSilence(rate, length):
wave = [0x80] * int(length * rate)
return bytearray(wave)
sampleRate = 22063
first = genSquare(sampleRate, 2375, 0.05)
second = genSquare(sampleRate, 2475, 0.05)
third = genSquare(sampleRate, 2675, 0.05)
fourth = genSquare(sampleRate, 2775, 0.05)
fifth = genSquare(sampleRate, 2975, 0.05)
toneList = [first, second, third, fourth, fifth]
permutations = list(itertools.product([1, 2, 3, 4, 5], repeat=3))
for perm in permutations:
with wave.open("%s/%d_%d_%d.wav" % (path, perm[0], perm[1], perm[2]), "wb") as af:
arr = bytearray()
# Output is wrapped in short silence
# short 0.1 second silence between the 0.05 second tones
arr.extend(genSilence(sampleRate, 0.25))
arr.extend(toneList[perm[0]-1])
arr.extend(genSilence(sampleRate, 0.1))
arr.extend(toneList[perm[1]-1])
arr.extend(genSilence(sampleRate, 0.1))
arr.extend(toneList[perm[2]-1])
arr.extend(genSilence(sampleRate, 0.25))
af.setsampwidth(1)
af.setnchannels(1)
af.setframerate(sampleRate)
af.writeframesraw(arr)
@windwakr
Copy link
Author

windwakr commented Dec 7, 2025

A Lua script for DeSmuME to play around with feeding the game inputs. Click the buttons and the game will think that command was sent from the Wappy Dog device.

2025-12-06.22-33-15.mp4
local command = 1
local cooldown = 0
local commandCooldown = 0

local downBox = {x = 03, y = 2-192, width = 13, height = 13}
local upBox = {x = 45, y = 2-192, width = 13, height = 13}
local okBox = {x = 62, y = 2-192, width = 13, height = 13}

function checkInside(x, y, box)
    if x >= box.x and x < (box.x+box.width) then
        if y >= box.y and y < (box.y+box.height) then
            return true
        end
    end
    return false
end

function main()
    keys = input.get()
    gui.box(0, 0-192, 77, 16-192, "#20202080")
    gui.box(20, 2-192, 40, 14-192, "#FFFFFF", "#000000")
    gui.text(21, 5-192, string.format("%3d", command))
    
    gui.box(downBox.x, downBox.y, downBox.x+downBox.width-1, downBox.y+downBox.height-1, "#000000")
    gui.line(downBox.x+2, downBox.y+2, downBox.x+6, downBox.y+downBox.height-3, "#FFFFFF")
    gui.line(downBox.x+6, downBox.y+downBox.height-3, downBox.x+downBox.width-3, downBox.y+2, "#FFFFFF")
    
    gui.box(upBox.x, upBox.y, upBox.x+upBox.width-1, upBox.y+upBox.height-1, "#000000")
    gui.line(upBox.x+2, upBox.y+upBox.height-3, upBox.x+6, upBox.y+2, "#FFFFFF")
    gui.line(upBox.x+6, upBox.y+2, upBox.x+upBox.width-3, upBox.y+upBox.height-3, "#FFFFFF")
    
    gui.box(okBox.x, okBox.y, okBox.x+okBox.width-1, okBox.y+okBox.height-1, "#000000")
    gui.text(okBox.x, okBox.y+3, "OK", "#FFFFFF")
    
    if keys["leftclick"] and keys.xmouse and keys.ymouse then
        if checkInside(keys.xmouse, keys.ymouse, downBox) then
            if command > 1 and cooldown == 0 then
                command = command - 1
                cooldown = 6
            end
        end
        if checkInside(keys.xmouse, keys.ymouse, upBox) then
            if command < 125 and cooldown == 0 then
                command = command + 1
                cooldown = 6
            end
        end
        if checkInside(keys.xmouse, keys.ymouse, okBox) then
            if commandCooldown == 0 then
                memory.writedword(0x02088E60, command)
                commandCooldown = 60
            end
        end
    end
    
    if cooldown > 0 then cooldown = cooldown - 1 end
    if commandCooldown > 0 then commandCooldown = commandCooldown - 1 end
end

emu.registerbefore(main)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment