在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:jsdf/n64-sdk-demo开源软件地址:https://github.com/jsdf/n64-sdk-demo开源编程语言:Objective-C 44.9%开源软件介绍:Nintendo 64 homebrew demo & tutorialThis is a demo app with heavily-commented source showing basic usage of the N64 SDK and the NuSystem framework. The game-specific code is in stage00.c. The compiled rom file can be found here. It can be run with an emulator or an N64 flashcart. Try pressing the A and B buttons. How to build (macOS or linux):
Understanding the code (or, an N64 homebrew tutorial)There are basically two options for making an N64 game these days:
This tutorial uses the SDK. RetroReversing has a pretty good tutorial for installing and using the SDK under Wine, which will allow you to compile the code in this repo. The N64 SDK comes with a small framework for quickly starting a new game, called NuSystem. The N64 comes with an OS (really, a library that you link into your game binary and boot on the bare metal), which provides features like threads and I/O, but still requires a fair bit of boilerplate to get a game engine set up. NuSystem removes the need to think about threads and initializing the hardware, and just lets you provide the typical InitializationWhen a game using NuSystem boots, it runs the From there it's up to you to fill in the logic for these functions with your game-specific code. Reading controller input and updating the game worldIn In RenderingOn the N64, at a high level the procedure for rendering graphics looks something like this:
Rendering on the N64 is a cooperative act between the main CPU, which runs the game logic and produces the list of things to draw, and the RCP, which performs the drawing of one frame while the main CPU moves on to running the logic and producing the display list for the next frame. To do this, we will need to allocate some structures to hold the displaylists and other data that will be shared between the code which runs on the main CPU (our program) and the code which runs on the RCP (called 'microcode', provided in binary form as part of the SDK). We need to allocate separate instances of this shared data for each frame, and switch which instance we're using when starting a new frame, like a circular buffer. The The Matrix StackAnother concept that's worth understanding is the 'matrix stack'. This concept comes directly from OpenGL 1.0 (which makes sense as both the Nintendo 64 hardware and OpenGL were developed by SGI). If you're put off by matrix math, don't worry, you don't need to understand it to make use of this feature. If you've used 2D drawing APIs like Turtle graphics or the Canvas2DContext in the HTML Canvas API, you'll be familiar with moving the drawing position by applying successive relative transformations such as translation, rotation and scaling, and this is very similar. The matrix stack is a stack data structure of matrices representing transformations of current drawing position in 3D space, which can be pushed onto and popped off. Pushing a matrix onto the stack effectively means applying a relative transformation to the drawing position which we can later undo by popping it back off. This allows rendering of hierarchical structures which might have transformations relative to some parent object, such as the positions and rotations of the wheels of a car relative to the car, and the car itself positioned and rotated in relation to the world. Modern OpenGL no longer includes this concept in its API, but for the N64 being able to offload the work of performing the matrix math (to transform objects in 3D space) to the RCP necessitated this sort of API. In OpenGL 1.0 this looks something like: glMatrixMode(GL_MODELVIEW); // using modelview matrix stack
glLoadIdentity(); // start at 0,0,0, with no rotation or scaling
glPushMatrix();
glTranslate(10, 0, 0); // translate in the x axis
drawCube(); // draw something, translated
glPushMatrix();
glRotate(0, 45, 0); // rotate around the y axis
glScale(1, 2, 1); // scale in the y axis
drawPyramid(); // draw something else, translated, rotated and scaled
glPopMatrix(); // undo rotation and scale
glPopMatrix(); // undo translation
drawSphere(); // draw something else, back at 0,0,0 On the N64, the equivalent code is: int curMatrix = 0;
// start at 0,0,0, with no rotation or scaling
guMtxIdent(&gfxTask->objectTransforms[curMatrix]);
gSPMatrix(displayListPtr++,
OS_K0_TO_PHYSICAL(&(gfxTask->objectTransforms[curMatrix++])),
G_MTX_MODELVIEW | G_MTX_NOPUSH | G_MTX_LOAD
);
// translate in the x axis
guTranslate(&gfxTask->objectTransforms[curMatrix], 10, 0, 0);
// push translation matrix
gSPMatrix(displayListPtr++,
OS_K0_TO_PHYSICAL(&(gfxTask->objectTransforms[curMatrix++])),
G_MTX_MODELVIEW | G_MTX_PUSH | G_MTX_MUL
);
drawCube(); // draw something, translated
// rotate around the y axis
guRotate(&gfxTask->objectTransforms[curMatrix], 0, 45, 0);
// scale in the y axis
guScale(&gfxTask->objectTransforms[curMatrix], 1, 2, 1);
// push transformation matrix
gSPMatrix(displayListPtr++,
OS_K0_TO_PHYSICAL(&(gfxTask->objectTransforms[curMatrix++])),
G_MTX_MODELVIEW | G_MTX_PUSH | G_MTX_MUL
);
drawPyramid(); // draw something else, translated, rotated and scaled
// undo rotation and scale
gSPPopMatrix(displayListPtr++, G_MTX_MODELVIEW);
// undo translation
gSPPopMatrix(displayListPtr++, G_MTX_MODELVIEW);
drawSphere(); // draw something else, back at 0,0,0 Although there is a strong correspondence between the two APIs, there are some important differences. On N64, you are responsible for allocating and the matrix ( Rendering squaresThe rendering of each square is wrapped up in the Rendering a complex meshA common approach to including models in your game created in a 3d modeling is to convert them into C source files containing static display lists. A static displaylist is a list of displaylist commands defined in an array. You can find an example of this in the Beyond...As the SDK docs are online, you can google any N64 function name to find documentation about it, or you can use the google 'site search' feature to search for some topic, for example: site:http://n64devkit.square7.ch/ memory management. If you would like to see an example of a more complete game codebase, take a look at goose64. |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论