An enhanced version of the unforgiving Japanese parody of Super Mario Bros.
Fix wraparound when cycling through debug options
Make README header a tiny bit prettier i guess


browse  log 



You can also use your local clone with git send-email.

Ultimate Syobon Action

yup this is a thing that exists now i guess

this is a fork of Open Syobon Action by Matthew Velasquez:

this codebase is dogshit but i'm making it work.
stuff new to ultimate syobon action:
- lua API, see stuff below
- debug overlay
- variables to tweak (as options, on debug page 1)
- save states (which you can use to save options)
- an actual pause button
- fixed some bugs and quirks (nothing that changes actual gameplay though)

feel free to send patches :)

dependencies: SDL, SDL_image, SDL_mixer, SDL_ttf, SDL_gfx


controls can be customized by overriding extra/config.lua (as described below in
the lua API secton). the default controls are as follows:

game controls:
z, up, semicolon, button 1 (joystick) - jump
left, right - movement
down - enter warp pipe
return - pause
escape - quit
space - double the game's speed (while held down)
1-9 (on title screen) - level select
0 (on title screen) - mystery dungeon
o - suicide

save state controls:
	keys f1-f12 load a save state from any of 12 slots. holding shift and
	pressing f1-f12 saves a state in said slot. holding ctrl and pressing
	f1-f12 deletes the saved state from said slot. if the player tries to
	load a slot that doesn't have anything saved, all values are reset to
	their defaults (as though the game had just launched, basically). when
	the game launches, the stock default.lua automatically loads slot 1
	(which does nothing if nothing is saved there). that's the means by
	which you can have your options persist across sessions: first set the
	options (as detailed below), then press shift+f1. then everytime you
	launch the game, so long as the slot isn't overwritten or deleted, your
	options will automatically be applied. also note that "x_pause" (which
	stores whether or not the game is paused) and "x_load_on_death" (which
	stores the save state to automatically load when the player dies) aren't
	saved nor loaded. this is so the player can pause the game before they
	make a save state if they wish and the state will still work as though
	the game were never paused, and so the player can use a save state for
	practice without having the slot persist when a state is loaded

debug controls:
ctrl + 0-9 on title screen; 0-9 everywhere else:
	view debug overlay. the number is the page to view. hold down shift when
	pressing 0-9 to add 10 to the page number. in total there are 20 pages,
	but page 0 is empty, so there are really 19 actual debug pages. page 1
	is options which are new to Ultimate Syobon Action; everything else is
	stuff that stores the game's state. the variable names are awful and
	tell you nothing about what they do, don't blame me lol, good luck. all
	variables whose name begins with "x_" are new to ultimate syobon action.
	if you really want a reference, some of the variables are documented in
	main.h, but it might be more fun to just fuck around and find out
j, k:
	cycle through variables in debug page (down, up)
h, l:
	change the value of a variable. h decrements; l increments. holding down
	shift lets you hold down h or l to change the value quickly. holding
	down ctrl does the same thing, but changes the value much faster, and
	holding both ctrl and shift goes even faster than that
	toggle debug lock. this lets you set variables to specific values
	without having the values change as you're incrementing/decrementing to
	the value you want (i.e., once you unlock, the values jumps to whatever
	you set them to while the lock was active). to use: press i, set the
	values for all the variables you want, then press i again. you can
	change as many variables at a time as you want, and you can switch debug
	pages while the lock is active, except you can't view page 0, since that
	just hides the debug screen

lua API

lua "mods" are sourced from two locations: the current working directory (which
is set to /usr/share/ultimate-syobon-action or equivalent when using the
installed wrapper script), or your config home (usually
~/.config/ultimate-syobon-action). files from both locations are read, unless a
file with the same name exists in both locations, in which case the file in your
config home will "override" the file in the current working directory. this
allows you to e.g. set custom controls by overriding the default
extra/config.lua. for more advanced use-cases, you can override default.lua,
though bear in mind that all input handling, as well as the debug overlay, are
handled by default in default.lua.

every mod file will be run when the game is first launched. each mod file is
also expected to return a function, which will be called repeatedly on every

every mod will most likely begin with `local game = require("game")`; all API
functions are in the "game" package.

every variable accessible on the debug screen may be accessed or mutated by
using its name as a field of "game" (e.g. game.nokori, game.x_load_on_death).

the following additional functions are supplied:

-- deletes all save data from a slot and resets it
game.delete(slot: integer)

-- causes the cat to die, rip

-- equivalent to dofile in the stdlib, except files are sourced from the same
-- locations as mods (detailed above)
game.dofile(path: string)

-- enter warp pipe

-- stops the currently playing music, if any

-- stops all currently playing sound effects

-- checks if a slot has any save data
game.haltsfx(slot: integer) -> boolean

-- checks if any of the given joystick buttons is being held
game.joydown(buttons: (integer | []integer)...) -> boolean

-- jmuup

-- checks if any of the given keys is being held
game.keydown(keys: (string | []string)...) -> boolean

-- checks if any of the given keys was just pressed
game.keypressed(keys: (string | []string)...) -> boolean

-- checks if any of the given keys was just released
game.keyreleased(keys: (string | []string)...) -> boolean

-- move left

-- loads save data from a slot
game.load(slot: integer)

-- pauses the currently playing music, if any

-- resumes the currently paused music, if any

-- move right

-- saves the current game state to a slot
game.save(slot: integer)

-- draws text to the screen for one frame
game.write(s: string, x: integer, y: integer, r: integer, g: integer, b: integer)