Skip to content

Commit

Permalink
Renamed all wii references to n3ds, updated README and screenshot.
Browse files Browse the repository at this point in the history
  • Loading branch information
MaikelChan committed Oct 28, 2021
1 parent 44806b1 commit 490b04d
Show file tree
Hide file tree
Showing 9 changed files with 90 additions and 173 deletions.
70 changes: 22 additions & 48 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
# 3D Pinball - Space Cadet for Wii
# 3D Pinball - Space Cadet for 3DS

This is a port of 3D Pinball - Space Cadet for Nintendo Wii. It's originally a game that came bundled with Windows from Windows 95 up to Windows XP. This is the current state of the project:
This is a port of 3D Pinball - Space Cadet for Nintendo 3DS. It's originally a game that came bundled with Windows from Windows 95 up to Windows XP. This is the current state of the project:

- No menus, options, or results screen.
- Playable with the Wii remote and the GameCube pad.
- It plays sound effects and music (if the player supplies the music in OGG format).
- There are still some bugs here and there, but it's perfectly playable.
- There are still some bugs here and there.
- It runs slow.

It is based on the PC decompilation made by [k4zmu2a](https://github.com/k4zmu2a): https://github.com/k4zmu2a/SpaceCadetPinball

The PC decompilation uses SDL2 to render the game. This Wii port has been changed to use native GPU rendering with the GX library, as SDL for Wii is considered incomplete, doesn't use the GPU too much and it was really slow.

I also made the required changes to make the original game's binary assets work in this port. The Wii's CPU is big endian, instead of little endian like PC x86. These changes could be useful for porting to other big endian devices.
The PC decompilation uses SDL2 to render the game. This 3DS port has been changed to use native GPU rendering with the Citro3D library.

## How to build

The main requirement is to have [devkitPro](https://devkitpro.org).

Follow the instructions to install devkitPro here: https://devkitpro.org/wiki/Getting_Started
You will also need the Wii development package, and also the libraries wii-sdl and wii-sdl_mixer.
You will also need the 3DS development package, and also the libraries 3ds-sdl and 3ds-sdl_mixer.

If you use Windows or Ubuntu, here are more detailed instructions.

Expand All @@ -32,71 +29,48 @@ Even though devkitPro offers a Windows installer, I've had some issues setting i
### Ubuntu and other Debian based linux distros

1. Open the terminal in the folder where you want to clone the project.
2. Clone it with the command `git clone --branch wii https://github.com/MaikelChan/SpaceCadetPinball`. A subfolder called `SpaceCadetPinball` will be created containing the project.
2. Clone it with the command `git clone --branch 3ds https://github.com/MaikelChan/SpaceCadetPinball`. A subfolder called `SpaceCadetPinball` will be created containing the project.
3. Move to that subfolder with `cd SpaceCadetPinball`.
4. Download the latest version of the [custom devkitPro pacman](https://github.com/devkitPro/pacman/releases/tag/v1.0.2), that will be used to download the compilers and libraries to build the project. Once downloaded, put it in the `SpaceCadetPinball` folder.
5. Install devkitPro pacman with this command: `sudo gdebi devkitpro-pacman.amd64.deb`. If gdebi is not found, install it with `sudo apt install gdebi-core`, and then try again installing pacman.
6. Use the following command to sync pacman databases: `sudo dkp-pacman -Sy`.
7. Now update packages with `sudo dkp-pacman -Syu`.
8. Install the Wii development tools with `sudo dkp-pacman -S wii-dev`.
9. Install SDL with `sudo dkp-pacman -S wii-sdl`.
10. Install SDL_mixer with `sudo dkp-pacman -S wii-sdl_mixer`.
8. Install the 3DS development tools with `sudo dkp-pacman -S 3ds-dev`.
9. Install SDL with `sudo dkp-pacman -S 3ds-sdl`.
10. Install SDL_mixer with `sudo dkp-pacman -S 3ds-sdl_mixer`.
11. Set the DEVKITPRO environment variables so the system knows where the compilers and libraries are installed with these commands:
- `export DEVKITPRO=/opt/devkitpro`.
- `export DEVKITPPC=/opt/devkitpro/devkitPPC`.
- `export DEVKITPPC=/opt/devkitpro/devkitARM`.
12. Build the project with the command `make -j4`.

After a successful build, you will get a file called `SpaceCadetPinball.dol`, which is the main executable.
After a successful build, you will get a file called `SpaceCadetPinball.3dsx`, which is the main executable.

## How to run

### Wii with homebrew channel
### Citra

1. Rename `SpaceCadetPinball.dol` to `boot.dol`.
2. Go to the `sd` folder in this repository, and copy its contents to the root of the SD card you use for loading apps for the Hombrew channel.
3. Copy `boot.dol` to `apps/SpaceCadetPinball/` in your SD card.
1. Get the [Citra emulator](https://citra-emu.org/download/) if you don't have it.
2. Open it and go to the menu `File/Open Citra Folder`. This will open the folder where Citra's configuration is stored.
3. Go to the `sdmc` folder and create a new folder there named `SpaceCadetPinball`.
4. For legal reasons, you will need to get the original PC game on your own to obtain the assets like graphics and sound effects. Those are not contained in this repository.
5. Copy all PC game's assets to `apps/SpaceCadetPinball/Data/` in your SD card.
6. Optionally, since this port doesn't play MIDI files, you'll need to convert the music to ogg format, and call the file `PINBALL.ogg`, and put it along the other assets in the `Data` folder.
6. If everything went fine, you should be able to see the game in your homebrew channel and run it.

### Dolphin

1. Get the [Dolphin emulator](https://dolphin-emu.org) if you don't have it.
2. Create and edit a virtual SD card following [these instructions](https://wiki.dolphin-emu.org/index.php?title=Virtual_SD_Card_Guide).
3. Mount that virtual card.
4. Follow the steps 4, 5 and 6 in `Wii with homebrew channel` section.
5. Unmount the SD card, as Dolphin won't be able to access its contents while it's mounted.
6. Open Dolphin, go to `Config`, then to the `Audio` tab, and select `DSP LLE REcompiler (slow)`. Audio won't work without that.
7. Go to `Graphics` settings, then to the `Hacks` tab, and move the `Accuracy` slider all the way to the left to set it as `Safe`.
8. Go to the menu `File` and then `Open...`.
9. Locate and open `SpaceCadetPinball.dol` (or `boot.dol` in case you renamed it for the homebrew channel).
10. If everything went fine, you should be able to run the game.
5. Copy all PC game's assets to to the `SpaceCadetPinball` folder that was created earlier.
6. Optionally, since this port doesn't play MIDI files, you'll need to convert the music to ogg format, and call the file `PINBALL.ogg`, and put it along the other assets in the `SpaceCadetPinball` folder.
7. If everything went fine, you should be able to run the game.

## How to play

### Wii Remote
```
A : Launch the ball
Z : Move the left paddle
B : Move the right paddle
DPAD Left, Right, Up : Bump table
- : Start a new game
+ : Pause
```

### GameCube Pad
```
A : Launch the ball
L : Move the left paddle
R : Move the right paddle
DPAD Left, Right, Up : Bump table
Y : Start a new game
X : Start a new game
Y : Exit game
Start : Pause
```

## Screenshots

<p align="center">
<img title="3D Pinball - Space Cadet for Wii running on Dolphin Emulator" src="/screenshot00.png">
<img title="3D Pinball - Space Cadet for 3DS running on Citra Emulator" src="/screenshot00.png">
</p>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "wii_graphics.h"
#include "n3ds_graphics.h"

#include <cstdio>
#include <string>
Expand All @@ -7,15 +7,15 @@

#include "vshader_shbin.h"

C3D_RenderTarget *wii_graphics::target = nullptr;
C3D_RenderTarget *n3ds_graphics::target = nullptr;

DVLB_s *wii_graphics::vshader_dvlb = nullptr;
shaderProgram_s wii_graphics::program = {};
int8_t wii_graphics::uLoc_projection = 0;
int8_t wii_graphics::uLoc_modelView = 0;
int8_t wii_graphics::uLoc_uvOffset = 0;
C3D_Mtx wii_graphics::projection = {};
void *wii_graphics::vbo_data = nullptr;
DVLB_s *n3ds_graphics::vshader_dvlb = nullptr;
shaderProgram_s n3ds_graphics::program = {};
int8_t n3ds_graphics::uLoc_projection = 0;
int8_t n3ds_graphics::uLoc_modelView = 0;
int8_t n3ds_graphics::uLoc_uvOffset = 0;
C3D_Mtx n3ds_graphics::projection = {};
void *n3ds_graphics::vbo_data = nullptr;

typedef struct
{
Expand All @@ -33,7 +33,7 @@ static const vertex vertex_list[] =

#define vertex_list_count (sizeof(vertex_list) / sizeof(vertex_list[0]))

void wii_graphics::Initialize()
void n3ds_graphics::Initialize()
{
// Initialize graphics

Expand Down Expand Up @@ -86,7 +86,7 @@ void wii_graphics::Initialize()
C3D_TexEnvFunc(env, C3D_Both, GPU_REPLACE);
}

void wii_graphics::Dispose()
void n3ds_graphics::Dispose()
{
// Free the VBO

Expand All @@ -103,30 +103,30 @@ void wii_graphics::Dispose()
gfxExit();
}

void wii_graphics::BeginRender()
void n3ds_graphics::BeginRender()
{
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
C3D_RenderTargetClear(target, C3D_CLEAR_ALL, 0x000000ff, 0);
C3D_FrameDrawOn(target);
}

void wii_graphics::FinishRender()
void n3ds_graphics::FinishRender()
{
C3D_FrameEnd(0);
}

bool wii_graphics::IsMainLoopRunning()
bool n3ds_graphics::IsMainLoopRunning()
{
return aptMainLoop();
}

void wii_graphics::SetOrthoProjectionMatrix(float left, float right, float bottom, float top, float near, float far)
void n3ds_graphics::SetOrthoProjectionMatrix(float left, float right, float bottom, float top, float near, float far)
{
Mtx_OrthoTilt(&projection, left, right, bottom, top, near, far, true);
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_projection, &projection);
}

void wii_graphics::SetModelViewMatrix(float x, float y, float w, float h)
void n3ds_graphics::SetModelViewMatrix(float x, float y, float w, float h)
{
C3D_Mtx modelView;
Mtx_Identity(&modelView);
Expand All @@ -135,14 +135,14 @@ void wii_graphics::SetModelViewMatrix(float x, float y, float w, float h)
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_modelView, &modelView);
}

void wii_graphics::DrawQuad(float x, float y, float w, float h, float uvX, float uvY, float uvW, float uvH)
void n3ds_graphics::DrawQuad(float x, float y, float w, float h, float uvX, float uvY, float uvW, float uvH)
{
SetModelViewMatrix(x, y, w, h);
C3D_FVUnifSet(GPU_VERTEX_SHADER, uLoc_uvOffset, uvX, uvY, uvW, uvH);
C3D_DrawArrays(GPU_TRIANGLE_STRIP, 0, vertex_list_count);
}

void wii_graphics::CreateTextureObject(C3D_Tex *textureObject, uint16_t width, uint16_t height, GPU_TEXCOLOR format, GPU_TEXTURE_WRAP_PARAM wrap, GPU_TEXTURE_FILTER_PARAM filter)
void n3ds_graphics::CreateTextureObject(C3D_Tex *textureObject, uint16_t width, uint16_t height, GPU_TEXCOLOR format, GPU_TEXTURE_WRAP_PARAM wrap, GPU_TEXTURE_FILTER_PARAM filter)
{
bool success = C3D_TexInit(textureObject, width, height, format);

Expand All @@ -157,18 +157,18 @@ void wii_graphics::CreateTextureObject(C3D_Tex *textureObject, uint16_t width, u
C3D_TexSetWrap(textureObject, wrap, wrap);
}

void wii_graphics::UploadTextureObject(C3D_Tex *textureObject, uint8_t *textureData)
void n3ds_graphics::UploadTextureObject(C3D_Tex *textureObject, uint8_t *textureData)
{
C3D_TexUpload(textureObject, textureData);
//C3D_TexFlush(&textureObject);
}

void wii_graphics::BindTextureObject(C3D_Tex *textureObject, int32_t mapIndex)
void n3ds_graphics::BindTextureObject(C3D_Tex *textureObject, int32_t mapIndex)
{
C3D_TexBind(mapIndex, textureObject);
}

uint32_t wii_graphics::GetTextureSize(uint16_t width, uint16_t height, GPU_TEXCOLOR format, int32_t maxLevel)
uint32_t n3ds_graphics::GetTextureSize(uint16_t width, uint16_t height, GPU_TEXCOLOR format, int32_t maxLevel)
{
uint32_t size = 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | \
GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO))

class wii_graphics
class n3ds_graphics
{
private:
static C3D_RenderTarget *target;
Expand Down
25 changes: 25 additions & 0 deletions SpaceCadetPinball/n3ds_input.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include "n3ds_input.h"

void n3ds_input::Initialize()
{
}

void n3ds_input::ScanPads()
{
hidScanInput();
}

uint32_t n3ds_input::GetButtonsDown()
{
return hidKeysDown();
}

uint32_t n3ds_input::GetButtonsUp()
{
return hidKeysUp();
}

uint32_t n3ds_input::GetButtonsHeld()
{
return hidKeysHeld();
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include <3ds.h>

class wii_input
class n3ds_input
{
public:
static void Initialize();
Expand Down
2 changes: 1 addition & 1 deletion SpaceCadetPinball/pb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#include "score.h"
#include "TPinballTable.h"
#include "TTextBox.h"
#include "wii_input.h"
#include "n3ds_input.h"

TPinballTable* pb::MainTable = nullptr;
DatFile* pb::record_table = nullptr;
Expand Down
25 changes: 0 additions & 25 deletions SpaceCadetPinball/wii_input.cpp

This file was deleted.

Loading

0 comments on commit 490b04d

Please sign in to comment.