DotnetSnes:一个允许使用C#创建SNES ROM的库
DotnetSnes: Library allowing to use C# to create SNES ROMs

原始链接: https://github.com/KallDrexx/DotnetSnes

DotnetSnes 允许使用 C# 等 .NET 语言进行 SNES ROM 开发。它利用一个 .NET 库 (DotnetSnes.Core) 来抽象 SNES 的功能。这个过程包括编译你的 .NET 项目的 DLL,使用 Dotnet To C 转译器 (dntc) 将其转译成 C 代码,然后使用 PvSnesLib SDK 编译 C 代码以创建一个可运行的 ROM。 由于 SNES 的限制,C# 代码需要进行调整,例如避免动态内存分配。dntc 转译器也有一些限制。PvSnesLib SDK 在 Linux 下运行效果最佳,建议 Windows 开发使用 WSL。 工作流程包括递归克隆 DotnetSnes 仓库,构建 PvSnesLib 工具链,并在你的项目目录中创建一个 Makefile 和 manifest.json 文件。manifest.json 文件配置转译过程。然后你可以使用 `make` 命令编译你的项目。资源管理涉及在 Makefile 中定义 `game_assets` 规则,并在你的 C# 代码中使用 `[AssemblyLabel]` 属性引用它们。

Hacker News 最新 | 往期 | 评论 | 提问 | 展示 | 招聘 | 提交 登录 DotnetSnes:使用 C# 创建 SNES ROM 的库 (github.com/kalldrexx) ingve 1小时前 5 分 | 隐藏 | 往期 | 收藏 | 讨论 加入我们,参加 6 月 16-17 日在旧金山举办的 AI 初创公司学校! 指南 | 常见问题 | 列表 | API | 安全 | 法律 | 申请 YC | 联系我们 搜索:

原文

Allows using .net languages to create real working SNES roms!

This works by providing a .net library that abstracts functions and globals used in creating SNES games. Once a project using the DotnetSnes.Core library is compiled, the resulting DLL is transpiled to C using the Dotnet To C transpiler (dntc). The game's C code is then compiled against the PvSnesLib SDK toolchain to create a working rom.

Due to the limitations of the SNES, it is not always possible to write idiomatic C# for a working rom. For example:

  • Minimal System level type support
  • No dynamic allocations are supported (thus no reference type support)
  • Minimizing variables on the stack is important
  • Pointer/address tracking is common to save memory

Even with these limitations, it is still possible to create real SNES games, though there might be instances where it may be necessary to go to a lower level than C# supports.

Note: The dntc transpiler has its own limitations on what MSIL operations it supports and doesn't yet support, so it's possible to hit code that should work but the transpiler does not yet have support for.

There are several things to be aware of before getting started

  • The PVSnesLib SDK works best under Linux. If developing on windows, you'll want to do the final compilation of the SNES rom under WSL, but obviously you can use windows emulators to test the resulting rom.
  • This repository should be cloned using ssh credentials. This is because all submodules (and submodules within submodules) are using git@ addresses and I have not yet figured out a good way to allow them to be mixed. See the Github SSH key docs for help.
  • Make sure to do a full recursive submodule update after cloning (e.g. git submodule update --init --recursive)

Dependencies needed to install on WSL Ubuntu for make

  • export PVSNESLIB_HOME=(yourpath)/DotnetSnes/pvsneslib
  • sudo apt-get update (if needed)
  • sudo apt-get install cmake
  • sudo apt-get install g++
  • sudo apt-get install dotnet-sdk-8.0

Preparing the Repo and SDKs

  1. Clone the DotnetSnes repository
  2. Do a recursive submodule initialization on the clone to get dependent projects
    • git submodule update --init --recursive
  3. cd into the pvsneslib/ directory and run make
    • This will make sure the pvsneslib toolchain is now built

The Hello World is a basic example that shows a bare minimum SNES rom that prints text to the screen.

  1. cd into src/DotnetSnes.Example.HellowWorld/
  2. run make

You should see Build finished successfully ! and a HelloWorld.sfc should now exist in your bin/Release/net8.0 folder. This is your SNES rom that you can load into an emulator, or save to flash cart.

mario.mp4

This is a C# port of the PVSnesLib LikeMario example, which demonstrates how to manage objects, tmx tile maps, audio, and game pad input.

Important classes are:

  • Globals.cs contains assembly labels for where content exists in the baked in rom.
  • Game.cs contains the logic for initializing the game
  • Mario.cs contains the logic for showing and controlling the mario object

To build:

  1. cd into [src/DotnetSnes.Example.LikeMario]
  2. run 'make'

The LikeMario.sfc rom file should now exist in the bin/Release/net8.0 folder.

To start a brand-new project:

  1. Create a new .net class library project
  2. Reference the DotnetSnes.Core library
    • This provides core functionality needed by SNES roms
  3. Reference the Dntc.Attributes library
    • This provides pretty important attributes thatare useful for the transpilation process
  4. Create a public static int Main() function declaration to declare your rom's entry point
  5. Add the [CustomFunctionName("main")] attribute to your Main() function, to force it to have main as the function name after transpiling to C. This allows the SDK to know it's the entry point.
  6. Create a file named Makefile with the following contents:
.SUFFIXES:

SNES_NAME ?= HelloWorld # Replace with the name you want your rom to have
SNES_DLL ?= $(ARTIFACTS_ROOT)/DotnetSnes.Example.HelloWorld.dll # Replace with the DLL your csproj will generate
ARTIFACTS_ROOT ?= $(abspath bin/Release/net8.0)
DNSNES_CORE_DIR ?= $(abspath ../DotnetSnes.Core) # Replace with the relative path to the DotnetSnes.Core project
DNTC_TOOL_CSPROJ ?= $(abspath ../../dntc/Dntc.Cli/Dntc.Cli.csproj) #
PVSNESLIB_HOME ?= $(abspath ../../pvsneslib) # Replace with the relative path to the pvsneslib folder from the repo
DNSNES_BASE_MAKEFILE ?= $(abspath ../Makefile.base) # Replace with the relative path to the DotnetSnes Makefile.base file

include $(DNSNES_BASE_MAKEFILE)

# PVSNESLIB
include ${PVSNESLIB_HOME}/devkitsnes/snes_rules
PVSNESLIB_DEVKIT_TOOLS = $(PVSNESLIB_HOME)/devkitsnes/tools
  1. If any content/game assets are needed to be added to the ROM, include them in the directory and create game_assets rules for them at the bottom of the Makefile. For example:
game_assets: mario_sprite.pic tiles.pic map_1_1.m16 mariofont.pic musics mariojump.brr

mario_sprite.pic: mario_sprite.bmp
	@echo convert sprites ... $(notdir $@)
	$(GFXCONV) -s 16 -o 16 -u 16 -p -t bmp -i $<

tiles.pic: tiles.png
	@echo convert map tileset... $(notdir $@)
	$(GFXCONV) -s 8 -o 16 -u 16 -p -m -i $<

map_1_1.m16: map_1_1.tmj tiles.pic
	@echo convert map tiled ... $(notdir $@)
	$(TMXCONV) $< tiles.map

mariofont.pic: mariofont.bmp
	@echo convert font with no tile reduction ... $(notdir $@)
	$(GFXCONV) -s 8 -o 2 -u 16 -e 1 -p -t bmp -m -R -i $<
  1. Create a manifest.json file in the same directory as your csproj. This instructs the transpiler on how to convert your project from a .net DLL to C.
{
  "AssemblyDirectory": ".",
  "AssembliesToLoad": [
    "DotnetSnes.Core.dll",
    "DotnetSnes.Example.LikeMario.dll"
  ],
  "PluginAssembly": "DotnetSnes.Core.dll",
  "OutputDirectory": ".",
  "SingleGeneratedSourceFileName": "LikeMario.c",
  "MethodsToTranspile": [
    "System.Int32 DotnetSnes.Example.LikeMario.Game::Main()"
  ],
  "GlobalsToTranspile": []
}
  1. Make the following updates to the manifest.json file:
    1. Change the second AssembliesToLoad value from DotnetSnes.Example.LikeMario.dll to the dll being generated by your project.
    2. Change SingleGeneratedSourceFileName from LikeMario.c to be <RomName>.c, where <RomName> is the same name specified in the SNES_NAME value in the Makefile
    3. Set MethodsToTranspile to point towards your Main function id. In most cases, this is just a matter of changing DotnetSnes.Example.LikeMario.Game to the full namespace + static class name that contains your Main function.
  2. Make sure your .net project copies the manifest.json file and any other content files needed to the output directory on build.
  3. Add code to your Main() function
  4. cd into your project directory and type make.

That should compile your project, and if successful will build the SNES rom in the directory specified by the ARTIFACTS_ROOT in your Makefile.

If your code references game content specified in assembly files, those locations in the assembly files are referenced by labels. In C code these are referenced by defining an extern char for the label name. In .net projects, you can reference these by annotating a field with a [AssemblyLabel("labelName")] attribute.

联系我们 contact @ memedata.com