Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics


A member registered Mar 28, 2016 · View creator page →

Creator of

Recent community posts

Star Flow Effect

function Start()
    stars = {}
function Update()
    for i = 1, #stars do
        stars[i] = nil
    minx, miny, maxx, maxy = 10000, 10000, 0, 0
function UpdateS()
    stars[#stars+1] = shape
    local pos = shape.OriPos
    minx = math.min(minx, pos.x)
    miny = math.min(miny, pos.y)
    maxx = math.max(maxx, pos.x)
    maxy = math.max(maxy, pos.y) 
function LateUpdate()
    if #stars > 3 then
        --local cx = (minx + maxx) / 2
        --local cy = (miny + maxy) / 2    
        local delta = (maxx + maxy - minx - miny) / 3
        --print(cx .. " - " ..  minx .. " - " .. maxx)
        for i = 1, #stars do
            local shape = stars[i]
            local ofs = shape.Offset
            ofs.z = ofs.z - delta
function End()
    stars = nil

I want to create a little bit more content for 3dSen PC/VR before thinking of porting it to the Quest.

Hey have you add the meta info in the updated profile so that i can remove the "Mod Update" line?

You are right indeed. I will try to improve it later.

(1 edit)

Left click to select the game first then right lick to select rom. What's annoying about it? I think it's the same way we do in most PC UI. Oh and sorry for missing your question.

May I suggest you increase the Border Left value a little bit to hide the buggy tiles at the left side?

JJXB I notice that characters is layered along side the background. Any reason for it?

(1 edit)

Get bored so I decide to improve the tree layout a little bit :) 


For top down game, I think the best setup is Layer1 : depth 0 align back, Layer 2: depth 0 align front. Layer 1 is for everything on the ground and Layer 2 is for the ground.

Please provide a little bit more info about the game and the profile. A short clip is a plus.

3dSen Maker community » Documents · Created a new topic FAQs
(2 edits)
  • 3dSen Maker flashes/blinks a lot. 

    Just uncheck Fast Render in Setting tab

  • How to render the Empty Tile - the one filled with zero indexed color

    Add the following script:

function Start()
    Setting.EmptyTile = true
(2 edits)

I started working on this profile since 2018 but just couldn't finish it. There are some characters moving via all 3 axis that I couldn't determine their 3d locations properly. I still want to share the work though, I think it's 90% complete.


Scene tracking script

Generally a games will contain many diffrent "scenes"  such as  "start screen" scene, cut scene,  gameplay scene, transition scene with score gain sumery ... Each scene will probably need different dynamic adjustment so we need a way to track which scene our current frame belongs to. The "scene" script below will help us with this task.

function Start()
    scene = 0
function Update()
    _scene = 0 
function UpdateS()
    _scene = shape.CData[0]
function LateUpdate()
    scene = _scene

For each scene determine a pattern which only appears on it and give it a "scene" tag and assign a scene id number to its CData0. That way the variable "scene" will alway refer to the current scene.

(1 edit)

Multi-depth platforming solution

There are games like SMB3 or Chip&Dale Rescue Ranger where it makes more sense to position platforms at different depths in 3d scene. How to calculate all the platform depths and moreover characters's depth who are sitting on top of those platforms? Obviously this is a dynamic problem that only could be solved after having the 2d output of each scene. The addopted solution of 3dSen is addopted in the video bellow with the help of two script tagged "pf" and "char"

- "pf" script:  pattern parameters used in this script

  • DeformSpeed.m00 : the z offset of the upper platform compared to its lower one
function Start()
    pfList = {}
function End()
    pfList = nil
function Update()
    for i = 1, #pfList do
        pfList[i] = nil
    pfs = Frame:GetShapesWithTag("pf")
    for i = 0, pfs.Count - 1 do
        pfList[i + 1] = pfs[i]
        pfList[i + 1].Pivot.z = 0
    if #pfList > 0 then
function Compare(s1, s2)
    if s1.TopRight.y < s2.TopRight.y then
        return true
        return false
function max(a,b)
    if a > b then
        return a;
        return b;
function UpdatePf()
    table.sort(pfList, Compare)
    for i = 1, #pfList -1 do
        pfI = pfList[i]
        for j = i + 1, #pfList do
            pfJ = pfList[j]
            if pfI.TopRight.y + 16 > pfJ.BottomLeft.y and pfI.BottomLeft.x <= pfJ.TopRight.x and pfI.TopRight.x >= pfJ.BottomLeft.x then
                if pfJ.Offset.z  < pfI.Offset.z + 8 then
                    pfJ.Layer = pfI.Layer
                    pfJ.Offset.z = pfI.Offset.z + pfJ.DeformSpeed.m00
                    if pfJ.Bg then
                        pfJ.Scale.z = pfI.Scale.z - pfJ.DeformSpeed.m00 / pfJ.sizeZ 

- "char" script: pattern parameters used:

  • DeformSpeed.m10 : the delta value help determine if a char in on top of a platform
function UpdateS()
    if #pfList == 0 then
    local pfNear = nil
    local yNear = 0
    local y = shape.BottomLeft.y
    local x1, x2 = shape.BottomLeft.x, shape.TopRight.x
    for i = 1, #pfList do
        s = pfList[i]
        if s.TopRight.y - s.DeformSpeed.m10 <= y and s.BottomLeft.x <= x2 and s.TopRight.x >= x1   then
            if pfNear == nil or yNear < s.TopRight.y then
                pfNear = s
                yNear = s.TopRight.y
    if pfNear ~= nil then
        shape.Offset.z = shape.Offset.z + pfNear.Offset.z
(6 edits)

Multi-layer interpretation solution

NES games have only one background layer. Therefore in games with multiple graphical layers object in the front layer will completly hide the one in the back layer or both objects apperance will be mixed in the same tiles. However we can interpolate the missing graphic of the back layer based on surround shapes to create the correct multi-layer representation. To do it we use a pair of script tagged "bg" and "bg1".  The surround shapes will be tagged "bg" and the target 3dShape will be tagged "bg1" and play the role of a "place holder". 

- "bg" script:  pattern parameters used in the script:

  • CData[1]: if the value is different than 0 then the shape texture will not be used as background  texture in case there is different shapws in the bg region/slot
  • CData[2] : the tolerance delta deternimes if a background shape belongs to a backgroun region/slot. If this value is -1 then the shape will be treated like the sole bg region in the current frame
function Start()
    bgSlot = {}
    MaxSlot = 10
    for i = 1, MaxSlot do
        bgSlot[i] = {}
function End()
    bgSlot = nil
function Update()
    bgCount = 0
    bgOne = 0
function Connect(s, slot, delta)
    local r = s.Palette == slot.shape.Palette and s.tStart.x <= slot.ex + delta and <= s.tEnd.x + delta and s.tStart.y <= slot.ey + delta and <= s.tEnd.x + delta;
    return r;
function UpdateS()
    if bgOne == 1 then
    if shape.Bg then
        if shape.CData[2] == -1 then
            bgOne = 1
            bgCount = 1
            local slot = bgSlot[1]
   = -1
   = -1
            slot.ex = 33
            slot.ey = 31
   = 0            
            slot.shape = shape
        for i = 1, bgCount do
            local slot = bgSlot[i]
            local delta = max(, shape.CData[2])
            if Connect(shape2D, slot, delta) then
       = min(, shape2D.tStart.x)
       = min(, shape2D.tStart.y)
                slot.ex = max(slot.ex, shape2D.tEnd.x)
                slot.ey = max(slot.ey, shape2D.tEnd.y)
       = delta
                if slot.shape.CData[1] ~= 0 then
                    slot.shape = shape
           = delta
        if bgCount < MaxSlot then
            bgCount = bgCount + 1;
            local slot = bgSlot[bgCount]
            slot.shape = shape
   = shape2D.tStart.x
   = shape2D.tStart.y
            slot.ex = shape2D.tEnd.x
            slot.ey = shape2D.tEnd.y
   = shape.CData[2]
function min(a,b)
    if a < b then
        return a
    return b
function max(a,b)
    if a > b then
        return a
    return b

- "bg1" script: pattern parameters used in the script:

  • CDatap[0] : bg texture will have this offset while applying to this place holder
function In(shape2D, bgSlot)
    return shape2D.tStart.x + 1 >= and shape2D.tStart.y + 1 >= and shape2D.tEnd.x <= bgSlot.ex + 1  and shape2D.tEnd.y  <= bgSlot.ey + 1
function Start()
    bg1List = {}
    bg1Count = 0
function Update()
    for i = 1,bg1Count do
        bg1List[i] = nil
    bg1Count = 0
function UpdateS()
    if shape.Bg then
        bg1Count = bg1Count + 1
        bg1List[bg1Count] = shape
function LateUpdate()
    for j = 1,bg1Count do
        local select = nil
        local shape = bg1List[j]
        for i = 1, bgCount do
            local _bgSlot = bgSlot[i]
            if  shape.Shape2D ~= _bgSlot.shape.Shape2D and In(shape.Shape2D, _bgSlot) and (not select or (select.ey - > _bgSlot.ey - then
                select = _bgSlot
        if select then
            shape.Enable = true            
            local bgShape = select.shape            
            shape.customPalette = bgShape.Palette
            shape.Layer = bgShape.Layer
            shape.Offset.z = bgShape.Offset.z
            shape.CastShadow = bgShape.CastShadow
            shape.RecvShadow = bgShape.RecvShadow
            shape.slot = bgShape.slot
            shape.texOffset.x = shape.CData[0]
            shape.Scale.z = bgShape.Scale.z * bgShape.sizeZ / shape.sizeZ
            shape.Alpha = bgShape.Alpha
            shape.Pivot.z = 0    
            shape.Enable = false        

Rotation effect.

In many situations, we will want to add a little animation to the object by make it self-rotate. We can do it with the below script:

function UpdateS()
    shape.Rot.z = time * shape.CData[0]
    shape.Rot.y = time * shape.CData[1]
    shape.Rot.z = time * shape.CData[2]

Tag the pattern we want to self-rotate and set the angular speed via three axises in CData 0, 1, 2

(3 edits)

Invisible effect. 

When a NES game want to temporary hide an on-screen object it often modify all colors of this object palette to the background one. The trick doesn't work really well with 3dSen because of depth, lighting and shadow are always still there. To regenerate this effect, you can link the target shape pattern with the following script:

function UpdateS()
    local p = shape.Palette
    local c1 = Palette.FrameColorIndex(p * 4)
    local c2 = Palette.FrameColorIndex(p * 4 + 1)
    local c3 = Palette.FrameColorIndex(p * 4 + 2)
    local c4 = Palette.FrameColorIndex(p * 4 + 3)
    shape.Enable = c1 ~= c2 or c2 ~= c3 or c3 ~= c4
(1 edit)

Useful scripts that have been being reused many times in different 3dprofiles.


(12 edits)

Record walkthrough gameplay

- Solution 1: use the Movie mode Record and at the end of the gameplay create a savestate. The savestate will contain all the input history you have just entered.

- Solution 2: use the existing TAS movie from and

3dSen already has the Bizhawk core built-in so you can use the bk2 movie right always. 

You can also import the fcemm core into 3dSen Maker and starting using fcm movie. To import it just copy its binary into:

  •  On Windows: 3dSenMaker_Data\Plugins\
  •  On Linux: 3dSenMaker_Data\Plugins\x86_64\
  •  On Mac: Contents\Plugins\

Remember that while 3dSen fceumm core is compatible with fcm movie content, it doesn't support fcm binary format. To use it, you have to convert it into fm2 format first using Fceuxx emulator.

Replay the walk-through

- Switch Movie Mode to Playback

- Select the correct core ( the core was used to created the movie/savestate)

- Load the rom

Profile Creation

Pattern Definition

By default, the tool create a new pattern for each new tile appearing on the screen. Our task is re-grouping those tiles to create the correct pattern.

- Pattern.RemoveWithTag(tag_name="_del") : remove all patterns having the tag tag_name from the profile

Multi-mapping + Deformation + Animation

Scripting + Texture Adjustment

(27 edits)


Basic Concepts

  • Shape: in-game meaningful graphical object - mario, cloud, pipe, bullet, brick etc...
  • 2dShape: the 2d representation of Shape, that’s what we see in the original game. It is equivalent to a grid of 8x8px tiles.
  • 3dShape: the 3d representation of Shape in real world which will created and rendered in the emulation process. 3dShape is not a unique 3d object, it is a set of 3d object(3dTile), each one correspond to a 8x8px tile (2dTile)
  • Pattern: first of all, a Pattern is a Shape without a fixed position.
    • It will be compatible with a class of Shape which contains the same tileset and have the same tile constraint set. Examples of diffrent shapes belong to the same pattern in SMB: pipes with different height, clouds with diffrent sizes. 
    • Tile constraint set is the info of which tile is located on the right/bottom of which tile.
    • A pattern contains a 2dPattern(2dShape) and a set of 3dPattern(3dShape). Normally a 2dShape will be interpreted as a 3dShape but in some cases it will be interpreted as some 3dShapes. 
  • A shape will be compatible with a pattern if its tileset is a sub set of 3dPattern tileset and 
  • 2dPattern: is a 2dShape without a fixed position.
  • 3dPattern: 3dShape without a fix position. 3dPattern is not defined by a set of parameters - with it we can create a set of 3dTile procedurally from a 2dPattern. Given a 3dPattern each tile(2dTile) from the 2dPattern will be linked to a 3dTile. It also contains a list of tags. 
  • Script: a script is  set of Lua function with a name and a list of tags. If a script and a 3dShape has a common tag then they are linked together and we can use this script to customize the 3dShape each frame.
  • 3d Profile: a list of pattern and script work together to guide the 3dification process of a specific game.

Scripting System

A script is a  set of special Lua function which is executed to customize 3dShape by modifying its parameters. A script is identified by a name and has a list of tags.

To hook itself into the 3dification process, a scripts must implement one or some of following special functions:

  • Start(): after loading the rom or the save state, all Start functions will be executed.
  • End(): right before finishing the emulation process of a given game, all End function will be executed.

At each frame, following functions will be executed in order:

  • Update: all Update functions will be executed first.
  • UpdateS: if a script is linked with a  3dShape (share a same tag) then the global variables shape and shape2D will be assigned to this 3dShape and its corresponding 2dShape then the UpdateS function of this sceipt will be executed.
  • LateUpdate: all LateUpdate function will be executed  

The special tag "*" means that this UpdateS function will be linked to all 3dShape of the current frame.

Script code can access and modify setting and the current list of 3dShape via various global variables:

  • variable shape of type Pattern3D (shape3D and pattern3D have the same type)  and variable shape2D of type Shape. shape and shape2D are only  determinist in UpdateS scope.
  • variable Script of type ScriptManager
  • variable Frame of type FrameManager (contains all 3dShapes of the current frame)
    • variable frame - the frame counter, shortcut of Frame.frameCounter
    • variable time – current game time in second, shortcut of Frame.time
  • variable Setting of type SettingManager
    • variable Light - shortcut of Setting.Light
    • variable Layer - shortcut of Setting.Layer
    • variable Clipping - shortcut of Setting.Clipping
  • variable Pattern of type PatternManager
  • variable Palette of type PaletteManager
  • variable Camera of type CameraControl
  • variable gamepad, gamepad1, gamepad2 of type Nespad3D. gamepad1 and gamepad2 contain the state of respective gamepads, gamepad state will return true if either gamepad1’s or gamepad2’s state return true.  

Lua variables are the wrappers of C# objects. To access a field or a property, we use the dot syntax:


To invoke a method, we use the ':' syntax


To invoke a static method, we use the normal dot syntax:


For example:

Setting.BgColor = false;

Scripting API


public struct Vector3 { public float x, y, z;}
public class PVector3 {public int x, y, z;}
public class PVector4 {public float x, y, z, w;}
public class PMatrix4x4 { public float m00, m01,m02, m03, m10, m11,m12, m13, m20, m21,m22, m23, m30, m31,m32, m33;}
public class Color {public float r, g, b, a;}
public enum ZLayer { UNIDENTIFIED, UI, L1, L2, L3, L4, COUNT };
public enum Geo3DType
public enum SelectionMode { Shape3D, Tile };
public enum Alignment { FRONT, CENTER, BACK };
public enum RenderAlgo { Greedy, Marching };


Provide APIs to access to scripts and read, write game memory.

public class ScriptManager
    Script Get(string name); // get script with name
    byte ReadMem(ushort address); // read from nes memory
    void WriteMem(ushort address, byte value); // write to nes memory
public class Script
    string Name { get; } // script name
    bool Enable { get; set; } // if the script is allowed to run
    bool Error { get; } // if there is any error in script code – auto detect by 3dSen

Frame Manager

Provide APIs to access to 3dShapes in current frame buffer.

public class FrameManager
    List<Pattern3D> GetShapesWithTag(string tag); // return a list of shape having the tag “tag” in the current frame buffer
    Pattern3D GetShapeWithTag(string tag); // return the first shape having the tag “tag” in the current frame buffer
    Pattern3D GetShape(int index); // return the index-th 3DShape in the current frame buffer 
    int shapeCount { get; } // return the 3DShape count in the current frame buffer
    int frameCounter { get; } // return the current frame counter 
    float time { get; } // return time in second of current frame buffer


Provide APIs to control the camera.

public class CameraControl 
    public float Distance {get; set} // the distance from the camera to the root (0,0,0)
    public PVector3 Rot {get;} //the camera rotation via three axis


Provides APIs to access gamepad state.

public class Nespad3D
    bool UpPressed { get; }
    bool DownPressed { get; }
    bool LeftPressed { get; }
    bool RightPressed { get; }
    bool SelectPressed { get; }
    bool StartPressed { get; }
    bool APressed { get; }
    bool BPressed { get; }
    bool RotLeftPressed { get; }
    bool RotRightPressed { get; }
    bool RotUpPressed { get; }
    bool RotDownPressed { get; }
    bool ZoomInPressed { get; }
    bool ZoomOutPressed { get; }


Provides APIs to access color palette info of the current frame.  For each frame there are 4 color palette for sprite and 4 color palette for background tiles. Each color palette has 4 colors so totally there are 32 indexed color. Each indexed color will refer to one of 64 NES colors.

public class Nespad3D
    //return the color of the ith color [0..31]
    public static Color FrameColor(int i); 
    // return the color index in the NES color table [0..63] of the ith color
    public static int FrameColorIndex(int i); 


Provide APIs to access properties of a 2dShape

public class Shape
    int Count { get; } // the number of shape3D linked with this 2dshape
    Pattern3D Shape3D(int index = 0);  // get the index-th shape3D linked with this 2DShape
    IntVector2 TStart { get; } // start (top left) position in tile unit (8 pixels)
    IntVector2 TEnd { get; } // end position (bottom right) position in tile unit
    IntVector2 TSize { get; } // shape size in tile
    IntVector2 Start {get;} // start (top left) position in pixel
    IntVector2 End; // end position (bottom right) position in pixel
    IntVector2 Size { get; } // shape size in pixel
    bool Bg { get; } // true if created by background tiles
    bool Hiden { get; } // true if one of one of its sprite tiles is hidden 
    int Palette { get; } // palette index 
    int TileCount { get; } // tile count
    bool Completed { get; } // true if the shape has every tile in the pattern tile set 
    bool Inside { get; } // true if the shape is completely located inside the screen 
    bool AtBorder { get; } // true if shape lies on a screen border
    int Age {get;} // the current amount of time - in frame unit - that the linked pattern has at least one linked shape in output frame


Provide APIs to access properties of a 3dShape/3dPattern

public class Pattern3D
    Shape Shape2D { get; } // the corresponding 2dshape
    int Index { get; } // its order in its linked 2dshape's 3dshape list 
    ZLayer Layer { get; set; } // shape layer
    bool UI { get; set; } // return true if Layer is UI, otherwise return false, setting it to true corresponds setting Layer to ZLayer.UI
    PVector3 Scale { get; }
    PVector3 Rot { get; }
    PVector3 Offset { get; }
    PVector3 Pivot { get; } // the pivot of scale and rotation operation float 
    Alpha { get; set; } // shape transparency 
    PVector3 DeformAmp { get; }
    PVector3 DeformPivot { get; }
    PMatrix4x4 DeformSpeed { get; }
    PMatrix4x4 DeformOffset { get; }
    bool Enable { get; set; } // if true, the shape will be rendered 
    bool Sp { get; } // return true if this is a sprite shape
    bool Bg { get; } // return true if this is a background shape 
    bool CastShadow {get; set} // shape will cast shadow or not
    bool ReceiveShadow {get; set} // shape will receive shadow or not
    Vector3 OriPos { get; } // the original shape position, calculated based on BottomLeft, TopRight and Pivot 
    Vector3 BottomLeft { get; } // the original bottom left coordination in pixel
    Vector3 TopRight { get; } // the original top right coordination in pixel
    Vector3 GetDeform(Vector3 pos); // return the deform vector at "pos" position based on Deform parameters and formula
    bool ContainsTag(string tag); // return true if shape contains the tag
    int CData[]; // 8 custom data of each pattern


Provide APIs to access setting parameters.

public class SettingManager
    public SelectionMode SelectionMode {get; set;}
    public class LightConfig
        public Vector3 Direction {get; set;}
        public Color Color {get; set;}
        public float Intensity {get; set;}
    LightConfig Light { get;}
    bool BgColor {get; set;} //if true, use the game background color else use CustomBgColor 
    Color CustomBgColor {get; set;}
    PVector4 Clipping {get;} //amount of clipped pixel at four borders Left, Bottom, Right, Top 
    bool MapEnable {get; set;} // show or hide the mini map 
    public class LayerP
        public float Offset {get; set}
        public Alignment Aligned {get; set;}
    public class LayerConfig
        public LayerP this[int index] {get;}
        public ZLayer DefLayer {get; set;}
        public bool Auto {get; set;} // if true, 3dSen will auto assign layer for pattern if possible
    LayerConfig Layer {get;}
    int GraphicQuality {get; set;} // valid values: 0, 1, 2
    int VrMode {get; set;} // 0: None, 1: OpenVr, 2: Oculus
    int VSync {get; set;} // enable or disable vsync
    int FrameRate {get; set;} // the frame buffer count per second if VSync is false float 
    GameSpeed {get; set;} // from -4 to 4, 0 is normal speed
    float Volume {get; set;} // from 0 to 1
    RenderAlgo RenderMode {get; set;}
    bool Titling {get; set;} // camera titling effect while pressing up, down, left, right button 
    bool Shadow {get; set;} // enable or disable shadow rendering at global level bool 
    SamePalette {get; set;} // if true, tiles in a shape must have the same palette
    int SpriteTolerance {get; set;} //be default sprite tiles in a shape must be 8px aligned but we could set a tolerance value to this constraint using this property
    bool EmptyTile {get;set;} // EmptyTile = false will filter empty tiles (tiles with all zero indexed color pixels)
    string Save2String(); // save setting to string
    void Load(string s); // load setting from string
    void Save(); // save setting to the permanent storage
    void Load(); // load setting from the permanent storage


Super Mario Bros - UI

In Super Mario Bros we want the status bar at the top of the screen to be always visible, and perpendicular to camera view. That can be done by set every involved pattern to layer UI. The issue is when the same shape is positioned in another area , we don’t want it in UI layer at all. So the static layer assignment won’t work. What we want here is if the shape is high enough (that means it is in the status bar region), its layer should be set to UI. That can be done by a small script tagged “*”:

function UpdateS()
    if shape.BottomLeft.y > 216 then
        shape.UI = true

Legend Of Zelda – UI

The UI in Legend of Zelda is a little bit different. Normally the UI part is located at the top but when the start button is pressed, the UI will scroll down and show its full content. That means the UI region position isn’t fixed. To deal with it, we choose a 3dPattern that only appears at the bottom of UI region and doesn’t appear anywhere else, that 3dPattern will be tagged “ui_bottom”. Then we add a script with the tag "*".

function Start()
    saveInt = Light.Intensity
    saveDir = Light.Direction
    Light.Direction = Vector3(0.3, 0.3, 1)
    Light.Intensity = 0.7
function Update()
    ui_bottom = Frame:GetShapeWithTag("ui_bottom");
    if ui_bottom then
        bottom = ui_bottom.BottomLeft.y
        bottom = 1000
function UpdateS()
    if shape.BottomLeft.y >= bottom then
        shape.UI = true
function End()
    Light.Intensity = saveInt
    Light.Direction = saveDir

Rotation effect

The code below is a script with a “rot” tag.

function UpdateS()
    shape.Rot.y = frame * 2;

If we want any shape to rotate around Y axis continuously, just assign tag “rot” for it.

Day-night effect

function Update()
    f = frame % 600
    if (f < 200) then
        Light.Intensity = 0.5
        Light.Intensity = 1.2

This script changes the light intensity periodically to emulate the day/night effect.

3dSen Maker community » Documents · Created a new topic 1. UI Manual
(21 edits)

UI Manual


3dSen Maker is a build of 3dSen Project that focus on 3d profile creation. A 3dn file is not a ROM! It contains 3d parameter set for a specific ROM. This data is used by 3dSen while emulating the game to create and render 3d graphics on the fly. The Editor Tab allows you to adjust certain parameters of the graphics to get them looking the way you want. You can then save the new data as a 3dn file by clicking the “Save 3Dn” button. This new data will automatically be loaded when you open the ROM again. The 3dn file must have the same name as the ROM in order for the 3D data to be paired with the ROM (e.g. a ROM named “xyz.nes” will always be paired with the 3Dn file named “xyz.3dn”). All 3dn files are stored in the sub folder “./3dn”. 

There are some 3d profiles provided in the build to create reference points: Super Mario Bros, Super Mario Bros 3, Legend Of Zelda, Chip 'and Dale: Rescue Ranger, Micro Mages.


  • Load: open a rom file (nes/zip) or save state file (sav).
  • Save: Save the current game state to a file.
  • Reset: Restart the game from the beginning.
  • Save 3DN: save the current 3d data to a file with the same name with rom file and 3dn extension.
  • Quick Load: Load the file quick.sav from the current directory.
  • Quick Save: Save the current game state to the file quick.sav.
  • Load Input: load recorded input  from external file. Supported formats are: fm2 and  bk2.
  • Exit: quit 3dSen.


Generic settings - ones aren't baked into 3d profiles

  • Core: supported emulation cores. There are two built-in core: Default(3dsen core) and Bizhawk cores. Additionally the fceumm core is also supported. To import it just copy its binary into:
    •  On Windows: 3dSenMaker_Data\Plugins
    •  On Linux: 3dSenMaker_Data\Plugins\x86_64\
    •  On Mac: Contents\Plugins\
  • VrMode:
    • None : 2d rendering
    • OpenVR: SteamVR mode
    • Oculus: Oculus runtime mode
  • Fast Render: skip re-rendering and use the previous output if 3dsen hasn't had a new game frame yet. Doesn't work in some Mac and Linux config.
  • Speed: adjust the game speed.
  • Vsync:   Default is Off.
  • Volume: adjust audio volume.
  • Movie Mode:
    • None: normal mode
    • Playback: input will be read from pre-loaded sources (fm2, bk2, sav) 
    • Record: record the current input and save it into save states later 
  • Skybox
    • None: default game color
    • Black: always black
    • Gradient:  the gradient of the first color palette
    • Fantasy: skybox with color from the first color palette

Profile specific setting - ones are baked into 3d profiles

  • Scan Direction: Vertical or Horizontal. the prioritized direction used in segmentation algorithm.
  • Sprite Tolerance: the maximal offset pixel count tolerated to group different sprites into a shape
  • Same Palette: decide if tiles in a shape need to have the same color palette or not
  • Auto Layering: enable the code to auto assign any shapes to a specific layer of depth  . Should let disable in most cases.


  • Light Dir: light direction vector
  • Intensity: light brightness
  • Def Layer: default layer assigned to a shape if its layer hasn't been initialized yet
  • BG Color: use the game back ground color or use  
  • Shadow: enable/disable shadow rendering
  • Border ... masks ... px: adjust how many pixel will be clipped at each border.
  • Layer ... :depth, alignment ...: adjust the z position and the alignment of each layer.
  • Render: select to render voxel in Normal or Retina mode.


  • Player: select which player gamepad is going to be configured, the first or the second.
  • Type: select input type Keyboard or Controller. For controller press any controller button first to bind the controller with the current gamepad.
  • Select an action its text field will turn yellow, press the key/button you want to bind to this action then move on.
  • Key/Button bindings will be automatically loaded/saved each time 3dSes is launched/existed. 


When you want to change the 3d presentation of a shape just select it, the game will be paused and the Editor tab will be activated. Every shape is linked with a pattern whose parameters are displayed on (1) and can be adjusted. (2) provides 5 slots so we can save/load frequently used pattern parameter sets. (3) provides access to frame navigation, on-screen shape navigation and pattern edition. (4) provide a basic texture editor to adjust the pattern texture.

To be able to adjust patterns of a shape or some shapes at once, Click on the target shape or Shift+Click to add/remove one or Shift + Drag to select all shapes in one region.

Pattern Parameter - 1
  • SizeZ: the shape depth in z axis – integer value. For Cylinder pattern, the depth that you enter is just the upper bound, the actual one will be calculated by 3dSen
  • Layer: To create the 3d depth, 3dSen is using the layer concept. There are four normal layers L1, L2, L3, L4 and a special layer UI which contain ui element of the game. There is also an initializing value called Unknown. Every pattern layer is Unknown by default. When you are playing, 3dSes will try to guess layer value for some patterns (Auto Layering checkbox in Render tab) but you still have to manually assign value in most cases.
  • Geo: is the geometric pattern to create the 3D appearance. There are six patterns: Default, HCylinder, VCylinder, Cube, HalfHCylinder, and HalfVCylinder. Depend on Geo value, there are several additional boolean parameters like AS, Solid, Flip, Wrap.
  • Scale: the shape scale vector – real values.
  • Offset: the shape position offset vector – real values.
  • Rot: the shape rotation vector – real values.
  • Pivot: the normalized pivot to rotate the shape. With value triple 0.5, 0.5, 0.5 shape will be rotated at its center.
  • Tags: a list of tag separated by comma. Tags will be used to linked shape with corresponding scripts.
  • Rm(Render Mode)
    • 0: use global Render Mode
    • 1: forced to use Normal Mode
    • 2: forced to use Retina Mode
  • Alpha: shape transparency, from 1: solid to 0: invisible – real value.
  • Restrict: the maximum width and height (in tile unit) of shape linked with this pattern.
  • RenAtr (Render Atribute) : On, Off, Shadow Only
  • Self: determine if tiles at the bottom/right will link to  ones at the top/left or not
  • Deform: show/ hide the sub-window Deform.
  • Tex: show/hide the sub-window Texture Editor
Parameter Slots - 2
  • File slots located at bottom left (Config1, Config2 ...). They can be used to save parameter set that we use often in the profile creation process. Steps to use those slots:
    • Shift + click a slot to rename it.
    • Ctrl +  click a slot to save pattern parameters in (1) and (5) into it.
    • Ctrl + [i] to save pattern parameters into the slot ith
    • Click a slot to load its saved parameters.
Tex Editor - 4

Providing some basic tools likes Pen, Fill, Replace, Copy/Pase, Color Picker to edit the pattern texture.

Deform Editor

If we want to deform or animate a shape, we could define parameters of above formula. Note that in this formula, xyz are all normalized by dPivot and sizeX, sizeY, sizeZ. For example if dPivot is 0, 0, 0 then x,y,z will run from 0 to 1. If dPivot is 1, 1, 1 then x,y,z will run from -1, -1, -1 to 0, 0, 0. 

Moreover there are 8 slots CData0 ... CData7 to store additional info which can be read and process later by script.

The five slots at top left works similarly to the ones in editor tab but they only store parameters of the Deform window.

Control - 2
  • Frame >, >>: forward the emulation 1 and 3 frames
  • Navigation <,>: navigate the selected shapes/tiles
  • Working Mode
    • Shape : working with shapes
    • Tile : working with tiles
  • Adjust: apply new/on-screen parameters for the selected pattern. The shape appearance will be updated after button click.
  • Delete: delete the selected pattern.
  • Clone: clone the selected pattern to a new one and add it into the database
  • Track: tracked the selected shape in following frames and adjust the same parameter set to its linked patterns.
  • Stop: stop tracking process.
  • Merge: shift + drag to select multi-shapes then merging them into a new pattern
  • Create: shift + mouse click/ shift + mouse drag to select multi-tiles then create a new pattern from them.


Emulation rollbacks.

Script Editor

The left panel lists all Lua scripts of the current profile. The middle displays all field of a script: name, tag list and code. On the left side there is a tiny console. More details about scripting system are described in the Scripting Manual.

Hot Keys

  • Esc : Show/ hide main UI.
  • F2: Switch camera mode: fixed mode and tracking mode
  • F4: Reset camera and headset in VR case.
  • F5 : Switch between fastest and normal game speed
  • F6: Switch between slowest and normal game speed
  • Ctrl + O : Open File Dialog
  • Ctrl + D : Save 3dn file
  • Ctrl + R : Reset the game
  • Ctrl + S : Quick save game state to quick.sav
  • Ctrl + Q: Quick load state from quick.sav
  • Ctrl + F : Toggle Full screen Mode
  • Ctrl + X : Exit 3DNes

If Editor tab is activated:

  • Ctrl + A : trigger Adjust function
  • Ctrl + E: trigger Delete function
  • Ctrl + M: trigger Merge function
  • Ctrl + C: trigger clone function
  • Ctrl + Left/Right: shape navigation
  • Ctrl +.  : Forward 1 frames
  • Ctrl + Shift + . : Forward 3 frames
  • Ctrl +  Mouse Click : switch camera from fix mode to tracking mode with the selected pattern
(1 edit)

I feels you guys. But there are still a lot of developments so Steam release only will save my time and effort. Thank you for your understanding.

The VR version does support Desktop mode now

No the Steam version is the Consumer version pre-loaded with polished profiles. The "Maker" version will be released later for free so everyone can create your own profiles and sharing it.

(1 edit)

Note taken.

(1 edit)

I accidentally deleted the place holder file ! Thank you for point it out!

Problem has been solved.

Normally users can still purchased Steam key. I'm the dev.