diff --git a/tools/vscode-extension/templates/bare-metal/cmake-cube/CMakeLists.txt b/tools/vscode-extension/templates/bare-metal/cmake-cube/CMakeLists.txt index 05bef1ee0..dae3c189b 100644 --- a/tools/vscode-extension/templates/bare-metal/cmake-cube/CMakeLists.txt +++ b/tools/vscode-extension/templates/bare-metal/cmake-cube/CMakeLists.txt @@ -16,22 +16,24 @@ project( HOMEPAGE_URL "https://github.com/grumpycoders/pcsx-redux" ) -# Set up compiler flags and initialize the Python environment used to run the -# scripts in the tools directory. +# Set up compiler flags, initialize the Python environment used to run the +# scripts in the tools directory and define some helper macros. include(ps1-bare-metal/cmake/setup.cmake) -include(ps1-bare-metal/cmake/virtualenv.cmake) +include(ps1-bare-metal/cmake/tools.cmake) -# Build a "common" library containing basic support code. We are going to link -# this library into our executable. +# Build a "common" library containing basic support code and link it by default +# into every executable. add_library( common OBJECT + ps1-bare-metal/src/libc/clz.s ps1-bare-metal/src/libc/crt0.c ps1-bare-metal/src/libc/cxxsupport.cpp ps1-bare-metal/src/libc/malloc.c - ps1-bare-metal/src/libc/memset.s ps1-bare-metal/src/libc/misc.c - ps1-bare-metal/src/libc/misc.s + ps1-bare-metal/src/libc/setjmp.s ps1-bare-metal/src/libc/string.c + ps1-bare-metal/src/libc/string.s + ps1-bare-metal/src/ps1/cache.s ps1-bare-metal/src/vendor/printf.c ) target_include_directories( @@ -39,52 +41,24 @@ target_include_directories( ps1-bare-metal/src ps1-bare-metal/src/libc ) +link_libraries(common) -# Compile the main executable. You may add more source files by listing them -# here. -add_executable( +# Compile the main executable; you may add more source files by listing them +# here. The addPS1Executable() macro is defined in tools.cmake and automatically +# takes care of converting the built ELF file into a PS1 executable (.psexe) +# which can run be run on emulators or real hardware. +addPS1Executable( {{projectName}} src/font.c src/gpu.c src/main.c src/trig.c ) -target_link_libraries({{projectName}} PRIVATE common) - -# Define a CMake macro that invokes convertImage.py in order to generate VRAM -# texture data from an image file. -function(convertImage input bpp) - add_custom_command( - OUTPUT ${ARGN} - DEPENDS "${PROJECT_SOURCE_DIR}/${input}" - COMMAND - "${Python3_EXECUTABLE}" - "${PROJECT_SOURCE_DIR}/ps1-bare-metal/tools/convertImage.py" - -b ${bpp} - "${PROJECT_SOURCE_DIR}/${input}" - ${ARGN} - VERBATIM - ) -endfunction() # Convert the font spritesheet to a 4bpp texture and palette, then embed them -# into the executable. The addBinaryFile() macro is defined in setup.cmake; you -# may call it multiple times to embed other data into the binary. +# into the executable. The convertImage() and addBinaryFile() macros are defined +# in tools.cmake and setup.cmake respectively. You may call them multiple times +# to embed other images or data into the binary. convertImage(assets/font.png 4 fontTexture.dat fontPalette.dat) addBinaryFile({{projectName}} fontTexture "${PROJECT_BINARY_DIR}/fontTexture.dat") addBinaryFile({{projectName}} fontPalette "${PROJECT_BINARY_DIR}/fontPalette.dat") - -# Add a step to run convertExecutable.py after the executable is compiled in -# order to convert it into a PS1 executable. By default all custom commands run -# from the build directory, so paths to files in the source directory must be -# prefixed with ${PROJECT_SOURCE_DIR}. -add_custom_command( - TARGET {{projectName}} POST_BUILD - BYPRODUCTS {{projectName}}.psexe - COMMAND - "${Python3_EXECUTABLE}" - "${PROJECT_SOURCE_DIR}/ps1-bare-metal/tools/convertExecutable.py" - "$" - {{projectName}}.psexe - VERBATIM -) diff --git a/tools/vscode-extension/templates/bare-metal/cmake-cube/src/font.c b/tools/vscode-extension/templates/bare-metal/cmake-cube/src/font.c index 2590bf6c3..74919643a 100644 --- a/tools/vscode-extension/templates/bare-metal/cmake-cube/src/font.c +++ b/tools/vscode-extension/templates/bare-metal/cmake-cube/src/font.c @@ -103,8 +103,12 @@ static const SpriteInfo fontSprites[] = { }; void printString( - DMAChain *chain, const TextureInfo *font, int x, int y, int zIndex, - const char *str + GPUDMAChain *chain, + const TextureInfo *font, + int x, + int y, + int zIndex, + const char *str ) { int currentX = x, currentY = y; @@ -145,7 +149,7 @@ void printString( // VRAM to those of the sprite itself within the sheet. Enable blending // to make sure any semitransparent pixels in the font get rendered // correctly. - ptr = allocatePacket(chain, zIndex, 4); + ptr = allocateGP0Packet(chain, zIndex, 4); ptr[0] = gp0_rectangle(true, true, true); ptr[1] = gp0_xy(currentX, currentY); ptr[2] = gp0_uv(font->u + sprite->x, font->v + sprite->y, font->clut); @@ -155,11 +159,10 @@ void printString( currentX += sprite->width; } - // Finish by sending a texpage command to tell the GPU to use the font's - // spritesheet (keep in mind that DMA sends ordering table packets in - // last-to-first order). Note that the texpage command before a drawing - // command can be omitted when reusing the same texture, so sending it here - // just once is enough. - ptr = allocatePacket(chain, zIndex, 1); - ptr[0] = gp0_texpage(font->page, false, false); + // Finish by sending a texture page command to tell the GPU to use the + // font's spritesheet (keep in mind that DMA sends ordering table packets in + // last-to-first order). The page setting persists when drawing rectangles, + // so sending it here just once is enough. + ptr = allocateGP0Packet(chain, zIndex, 1); + ptr[0] = gp0_setPage(font->page, false, false); } diff --git a/tools/vscode-extension/templates/bare-metal/cmake-cube/src/font.h b/tools/vscode-extension/templates/bare-metal/cmake-cube/src/font.h index d7982b69f..9cd872de5 100644 --- a/tools/vscode-extension/templates/bare-metal/cmake-cube/src/font.h +++ b/tools/vscode-extension/templates/bare-metal/cmake-cube/src/font.h @@ -5,7 +5,7 @@ #include "gpu.h" #define FONT_FIRST_TABLE_CHAR '!' -#define FONT_SPACE_WIDTH 4 +#define FONT_SPACE_WIDTH 4 #define FONT_TAB_WIDTH 32 #define FONT_LINE_HEIGHT 10 @@ -18,8 +18,12 @@ extern "C" { #endif void printString( - DMAChain *chain, const TextureInfo *font, int x, int y, int zIndex, - const char *str + GPUDMAChain *chain, + const TextureInfo *font, + int x, + int y, + int zIndex, + const char *str ); #ifdef __cplusplus diff --git a/tools/vscode-extension/templates/bare-metal/cmake-cube/src/gpu.c b/tools/vscode-extension/templates/bare-metal/cmake-cube/src/gpu.c index 33357d281..a7505509d 100644 --- a/tools/vscode-extension/templates/bare-metal/cmake-cube/src/gpu.c +++ b/tools/vscode-extension/templates/bare-metal/cmake-cube/src/gpu.c @@ -6,6 +6,8 @@ #include "ps1/gpucmd.h" #include "ps1/registers.h" +#define DMA_MAX_CHUNK_SIZE 16 + void setupGPU(GP1VideoMode mode, int width, int height) { int x = 0x760; int y = (mode == GP1_MODE_PAL) ? 0xa3 : 0x88; @@ -20,8 +22,21 @@ void setupGPU(GP1VideoMode mode, int width, int height) { GPU_GP1 = gp1_fbRangeH(x - offsetX, x + offsetX); GPU_GP1 = gp1_fbRangeV(y - offsetY, y + offsetY); GPU_GP1 = gp1_fbMode( - horizontalRes, verticalRes, mode, false, GP1_COLOR_16BPP + horizontalRes, + verticalRes, + mode, + false, + GP1_COLOR_16BPP ); + GPU_GP1 = gp1_dispBlank(false); + + DMA_DPCR |= 0 + | DMA_DPCR_CH_ENABLE(DMA_GPU) + | DMA_DPCR_CH_ENABLE(DMA_OTC); + DMA_CHCR(DMA_GPU) = 0; + DMA_CHCR(DMA_OTC) = 0; + + GPU_GP1 = gp1_dmaRequestMode(GP1_DREQ_GP0_WRITE); } void waitForGP0Ready(void) { @@ -29,7 +44,7 @@ void waitForGP0Ready(void) { __asm__ volatile(""); } -void waitForDMADone(void) { +void waitForGPUDMADone(void) { while (DMA_CHCR(DMA_GPU) & DMA_CHCR_ENABLE) __asm__ volatile(""); } @@ -41,19 +56,28 @@ void waitForVSync(void) { IRQ_STAT = ~(1 << IRQ_VSYNC); } -void sendLinkedList(const void *data) { - waitForDMADone(); +void sendGPULinkedList(const void *data) { + waitForGPUDMADone(); assert(!((uint32_t) data % 4)); DMA_MADR(DMA_GPU) = (uint32_t) data; - DMA_CHCR(DMA_GPU) = DMA_CHCR_WRITE | DMA_CHCR_MODE_LIST | DMA_CHCR_ENABLE; + DMA_CHCR(DMA_GPU) = 0 + | DMA_CHCR_WRITE + | DMA_CHCR_MODE_LIST + | DMA_CHCR_ENABLE; } -void sendVRAMData(const void *data, int x, int y, int width, int height) { - waitForDMADone(); +void sendVRAMData( + const void *data, + int x, + int y, + int width, + int height +) { + waitForGPUDMADone(); assert(!((uint32_t) data % 4)); - size_t length = (width * height) / 2; + size_t length = (width * height + 1) / 2; size_t chunkSize, numChunks; if (length < DMA_MAX_CHUNK_SIZE) { @@ -73,55 +97,79 @@ void sendVRAMData(const void *data, int x, int y, int width, int height) { DMA_MADR(DMA_GPU) = (uint32_t) data; DMA_BCR (DMA_GPU) = chunkSize | (numChunks << 16); - DMA_CHCR(DMA_GPU) = DMA_CHCR_WRITE | DMA_CHCR_MODE_SLICE | DMA_CHCR_ENABLE; + DMA_CHCR(DMA_GPU) = 0 + | DMA_CHCR_WRITE + | DMA_CHCR_MODE_SLICE + | DMA_CHCR_ENABLE; } void clearOrderingTable(uint32_t *table, int numEntries) { DMA_MADR(DMA_OTC) = (uint32_t) &table[numEntries - 1]; DMA_BCR (DMA_OTC) = numEntries; DMA_CHCR(DMA_OTC) = 0 - | DMA_CHCR_READ | DMA_CHCR_REVERSE | DMA_CHCR_MODE_BURST - | DMA_CHCR_ENABLE | DMA_CHCR_TRIGGER; + | DMA_CHCR_READ + | DMA_CHCR_REVERSE + | DMA_CHCR_MODE_BURST + | DMA_CHCR_ENABLE + | DMA_CHCR_TRIGGER; while (DMA_CHCR(DMA_OTC) & DMA_CHCR_ENABLE) __asm__ volatile(""); } -uint32_t *allocatePacket(DMAChain *chain, int zIndex, int numCommands) { +uint32_t *allocateGP0Packet(GPUDMAChain *chain, int zIndex, int numCommands) { + assert((numCommands >= 0) && (numCommands <= DMA_MAX_CHUNK_SIZE)); + assert((zIndex >= 0) && (zIndex < GPU_ORDERING_TABLE_SIZE)); + uint32_t *ptr = chain->nextPacket; chain->nextPacket += numCommands + 1; - assert((zIndex >= 0) && (zIndex < ORDERING_TABLE_SIZE)); - *ptr = gp0_tag(numCommands, (void *) chain->orderingTable[zIndex]); chain->orderingTable[zIndex] = gp0_tag(0, ptr); - assert(chain->nextPacket < &(chain->data)[CHAIN_BUFFER_SIZE]); + assert(chain->nextPacket < &(chain->data)[GPU_CHAIN_BUFFER_SIZE]); return &ptr[1]; } void uploadTexture( - TextureInfo *info, const void *data, int x, int y, int width, int height + TextureInfo *info, + const void *data, + int x, + int y, + int width, + int height ) { assert((width <= 256) && (height <= 256)); sendVRAMData(data, x, y, width, height); - waitForDMADone(); + waitForGPUDMADone(); + GPU_GP0 = gp0_flushCache(); info->page = gp0_page( - x / 64, y / 256, GP0_BLEND_SEMITRANS, GP0_COLOR_16BPP + x / 64, + y / 256, + GP0_BLEND_SEMITRANS, + GP0_COLOR_16BPP ); info->clut = 0; - info->u = (uint8_t) (x % 64); + info->u = (uint8_t) (x % 64); info->v = (uint8_t) (y % 256); info->width = (uint16_t) width; info->height = (uint16_t) height; } void uploadIndexedTexture( - TextureInfo *info, const void *image, const void *palette, int x, int y, - int paletteX, int paletteY, int width, int height, GP0ColorDepth colorDepth + TextureInfo *info, + const void *image, + const void *palette, + int imageX, + int imageY, + int paletteX, + int paletteY, + int width, + int height, + GP0ColorDepth colorDepth ) { assert((width <= 256) && (height <= 256)); @@ -130,17 +178,21 @@ void uploadIndexedTexture( assert(!(paletteX % 16) && ((paletteX + numColors) <= 1024)); - sendVRAMData(image, x, y, width / widthDivider, height); - waitForDMADone(); + sendVRAMData(image, imageX, imageY, width / widthDivider, height); + waitForGPUDMADone(); sendVRAMData(palette, paletteX, paletteY, numColors, 1); - waitForDMADone(); + waitForGPUDMADone(); + GPU_GP0 = gp0_flushCache(); info->page = gp0_page( - x / 64, y / 256, GP0_BLEND_SEMITRANS, colorDepth + imageX / 64, + imageY / 256, + GP0_BLEND_SEMITRANS, + colorDepth ); info->clut = gp0_clut(paletteX / 16, paletteY); - info->u = (uint8_t) ((x % 64) * widthDivider); - info->v = (uint8_t) (y % 256); + info->u = (uint8_t) ((imageX % 64) * widthDivider); + info->v = (uint8_t) (imageY % 256); info->width = (uint16_t) width; info->height = (uint16_t) height; } diff --git a/tools/vscode-extension/templates/bare-metal/cmake-cube/src/gpu.h b/tools/vscode-extension/templates/bare-metal/cmake-cube/src/gpu.h index 14b95636d..468210adb 100644 --- a/tools/vscode-extension/templates/bare-metal/cmake-cube/src/gpu.h +++ b/tools/vscode-extension/templates/bare-metal/cmake-cube/src/gpu.h @@ -4,19 +4,18 @@ #include #include "ps1/gpucmd.h" -// In order for Z averaging to work properly, ORDERING_TABLE_SIZE should be set -// to either a relatively high value (1024 or more) or a multiple of 12; see +// In order for Z averaging to work properly, GPU_ORDERING_TABLE_SIZE should be +// set to either a relatively high value (1024 or more) or a multiple of 12; see // setupGTE() for more details. Higher values will take up more memory but are // required to render more complex scenes with wide depth ranges correctly. -#define DMA_MAX_CHUNK_SIZE 16 -#define CHAIN_BUFFER_SIZE 1024 -#define ORDERING_TABLE_SIZE 240 +#define GPU_CHAIN_BUFFER_SIZE 1024 +#define GPU_ORDERING_TABLE_SIZE 240 typedef struct { - uint32_t data[CHAIN_BUFFER_SIZE]; - uint32_t orderingTable[ORDERING_TABLE_SIZE]; + uint32_t data[GPU_CHAIN_BUFFER_SIZE]; + uint32_t orderingTable[GPU_ORDERING_TABLE_SIZE]; uint32_t *nextPacket; -} DMAChain; +} GPUDMAChain; typedef struct { uint8_t u, v; @@ -30,20 +29,39 @@ extern "C" { void setupGPU(GP1VideoMode mode, int width, int height); void waitForGP0Ready(void); -void waitForDMADone(void); +void waitForGPUDMADone(void); void waitForVSync(void); -void sendLinkedList(const void *data); -void sendVRAMData(const void *data, int x, int y, int width, int height); +void sendGPULinkedList(const void *data); +void sendVRAMData( + const void *data, + int x, + int y, + int width, + int height +); void clearOrderingTable(uint32_t *table, int numEntries); -uint32_t *allocatePacket(DMAChain *chain, int zIndex, int numCommands); +uint32_t *allocateGP0Packet(GPUDMAChain *chain, int zIndex, int numCommands); void uploadTexture( - TextureInfo *info, const void *data, int x, int y, int width, int height + TextureInfo *info, + const void *data, + int x, + int y, + int width, + int height ); void uploadIndexedTexture( - TextureInfo *info, const void *image, const void *palette, int x, int y, - int paletteX, int paletteY, int width, int height, GP0ColorDepth colorDepth + TextureInfo *info, + const void *image, + const void *palette, + int imageX, + int imageY, + int paletteX, + int paletteY, + int width, + int height, + GP0ColorDepth colorDepth ); #ifdef __cplusplus diff --git a/tools/vscode-extension/templates/bare-metal/cmake-cube/src/main.c b/tools/vscode-extension/templates/bare-metal/cmake-cube/src/main.c index 673864427..2ab23b39d 100644 --- a/tools/vscode-extension/templates/bare-metal/cmake-cube/src/main.c +++ b/tools/vscode-extension/templates/bare-metal/cmake-cube/src/main.c @@ -24,13 +24,13 @@ // that fractional values will be stored as integers by multiplying them by a // fixed unit, in this case 4096 or 1 << 12 (hence making the fractional part 12 // bits long). We'll define this unit value to make their handling easier. -#define ONE (1 << 12) +#define GTE_UNIT (1 << 12) static void setupGTE(int width, int height) { // Ensure the GTE, which is coprocessor 2, is enabled. MIPS coprocessors are // enabled through the status register in coprocessor 0, which is always // accessible. - cop0_setReg(COP0_SR, cop0_getReg(COP0_SR) | COP0_SR_CU2); + cop0_setReg(COP0_STATUS, cop0_getReg(COP0_STATUS) | COP0_STATUS_CU2); // Set the offset to be added to all calculated screen space coordinates (we // want our cube to appear at the center of the screen) Note that OFX and @@ -50,8 +50,8 @@ static void setupGTE(int width, int height) { // be sorted into. This will work best if the ordering table length is a // multiple of 12 (i.e. both 3 and 4) or high enough to make any rounding // error negligible. - gte_setControlReg(GTE_ZSF3, ORDERING_TABLE_SIZE / 3); - gte_setControlReg(GTE_ZSF4, ORDERING_TABLE_SIZE / 4); + gte_setControlReg(GTE_ZSF3, GPU_ORDERING_TABLE_SIZE / 3); + gte_setControlReg(GTE_ZSF4, GPU_ORDERING_TABLE_SIZE / 4); } // When transforming vertices, the GTE will multiply their vectors by a 3x3 @@ -64,24 +64,24 @@ static void multiplyCurrentMatrixByVectors(GTEMatrix *output) { // done one column at a time, as the GTE only supports multiplying a matrix // by a vector using the MVMVA command. gte_command(GTE_CMD_MVMVA | GTE_SF | GTE_MX_RT | GTE_V_V0 | GTE_CV_NONE); - output->values[0][0] = gte_getDataReg(GTE_IR1); - output->values[1][0] = gte_getDataReg(GTE_IR2); - output->values[2][0] = gte_getDataReg(GTE_IR3); + output->values[0][0] = (int16_t) gte_getDataReg(GTE_IR1); + output->values[1][0] = (int16_t) gte_getDataReg(GTE_IR2); + output->values[2][0] = (int16_t) gte_getDataReg(GTE_IR3); gte_command(GTE_CMD_MVMVA | GTE_SF | GTE_MX_RT | GTE_V_V1 | GTE_CV_NONE); - output->values[0][1] = gte_getDataReg(GTE_IR1); - output->values[1][1] = gte_getDataReg(GTE_IR2); - output->values[2][1] = gte_getDataReg(GTE_IR3); + output->values[0][1] = (int16_t) gte_getDataReg(GTE_IR1); + output->values[1][1] = (int16_t) gte_getDataReg(GTE_IR2); + output->values[2][1] = (int16_t) gte_getDataReg(GTE_IR3); gte_command(GTE_CMD_MVMVA | GTE_SF | GTE_MX_RT | GTE_V_V2 | GTE_CV_NONE); - output->values[0][2] = gte_getDataReg(GTE_IR1); - output->values[1][2] = gte_getDataReg(GTE_IR2); - output->values[2][2] = gte_getDataReg(GTE_IR3); + output->values[0][2] = (int16_t) gte_getDataReg(GTE_IR1); + output->values[1][2] = (int16_t) gte_getDataReg(GTE_IR2); + output->values[2][2] = (int16_t) gte_getDataReg(GTE_IR3); } static void rotateCurrentMatrix(int yaw, int pitch, int roll) { static GTEMatrix multiplied; - int s, c; + int s, c; // For each axis, compute the rotation matrix then "combine" it with the // GTE's current matrix by multiplying the two and writing the result back @@ -91,9 +91,9 @@ static void rotateCurrentMatrix(int yaw, int pitch, int roll) { c = icos(yaw); gte_setColumnVectors( - c, -s, 0, - s, c, 0, - 0, 0, ONE + c, -s, 0, + s, c, 0, + 0, 0, GTE_UNIT ); multiplyCurrentMatrixByVectors(&multiplied); gte_loadRotationMatrix(&multiplied); @@ -103,9 +103,9 @@ static void rotateCurrentMatrix(int yaw, int pitch, int roll) { c = icos(pitch); gte_setColumnVectors( - c, 0, s, - 0, ONE, 0, - -s, 0, c + c, 0, s, + 0, GTE_UNIT, 0, + -s, 0, c ); multiplyCurrentMatrixByVectors(&multiplied); gte_loadRotationMatrix(&multiplied); @@ -115,9 +115,9 @@ static void rotateCurrentMatrix(int yaw, int pitch, int roll) { c = icos(roll); gte_setColumnVectors( - ONE, 0, 0, - 0, c, -s, - 0, s, c + GTE_UNIT, 0, 0, + 0, c, -s, + 0, s, c ); multiplyCurrentMatrixByVectors(&multiplied); gte_loadRotationMatrix(&multiplied); @@ -173,8 +173,8 @@ static const Face cubeFaces[NUM_CUBE_FACES] = { #define SCREEN_WIDTH 320 #define SCREEN_HEIGHT 240 -#define FONT_WIDTH 96 -#define FONT_HEIGHT 56 +#define FONT_WIDTH 96 +#define FONT_HEIGHT 56 #define FONT_COLOR_DEPTH GP0_COLOR_4BPP extern const uint8_t fontTexture[], fontPalette[]; @@ -192,36 +192,38 @@ int main(int argc, const char **argv) { setupGTE(SCREEN_WIDTH, SCREEN_HEIGHT); - DMA_DPCR |= DMA_DPCR_ENABLE << (DMA_GPU * 4); - DMA_DPCR |= DMA_DPCR_ENABLE << (DMA_OTC * 4); - - GPU_GP1 = gp1_dmaRequestMode(GP1_DREQ_GP0_WRITE); - GPU_GP1 = gp1_dispBlank(false); - // Upload the font texture to VRAM. TextureInfo font; uploadIndexedTexture( - &font, fontTexture, fontPalette, SCREEN_WIDTH * 2, 0, SCREEN_WIDTH * 2, - FONT_HEIGHT, FONT_WIDTH, FONT_HEIGHT, FONT_COLOR_DEPTH + &font, + fontTexture, + fontPalette, + SCREEN_WIDTH * 2, + 0, + SCREEN_WIDTH * 2, + FONT_HEIGHT, + FONT_WIDTH, + FONT_HEIGHT, + FONT_COLOR_DEPTH ); - DMAChain dmaChains[2]; - bool usingSecondFrame = false; - int frameCounter = 0; + GPUDMAChain dmaChains[2]; + bool usingSecondFrame = false; + int frameCounter = 0; for (;;) { int bufferX = usingSecondFrame ? SCREEN_WIDTH : 0; int bufferY = 0; - DMAChain *chain = &dmaChains[usingSecondFrame]; - usingSecondFrame = !usingSecondFrame; + GPUDMAChain *chain = &dmaChains[usingSecondFrame]; + usingSecondFrame = !usingSecondFrame; uint32_t *ptr; GPU_GP1 = gp1_fbOffset(bufferX, bufferY); - clearOrderingTable(chain->orderingTable, ORDERING_TABLE_SIZE); + clearOrderingTable(chain->orderingTable, GPU_ORDERING_TABLE_SIZE); chain->nextPacket = chain->data; // Reset the GTE's translation vector (added to each vertex) and @@ -232,9 +234,9 @@ int main(int argc, const char **argv) { gte_setControlReg(GTE_TRY, 0); gte_setControlReg(GTE_TRZ, 128); gte_setRotationMatrix( - ONE, 0, 0, - 0, ONE, 0, - 0, 0, ONE + GTE_UNIT, 0, 0, + 0, GTE_UNIT, 0, + 0, 0, GTE_UNIT ); rotateCurrentMatrix(0, frameCounter * 16, frameCounter * 12); @@ -254,10 +256,12 @@ int main(int argc, const char **argv) { // Determine the winding order of the vertices on screen. If they // are ordered clockwise then the face is visible, otherwise it can - // be skipped as it is not facing the camera. + // be culled as it is not facing the camera. Note that + // gte_getDataReg() always returns a 32-bit unsigned value, but most + // GTE registers should be interpreted as signed. gte_command(GTE_CMD_NCLIP); - if (gte_getDataReg(GTE_MAC0) <= 0) + if (((int) gte_getDataReg(GTE_MAC0)) <= 0) continue; // Save the first transformed vertex (the GTE only keeps the X/Y @@ -272,14 +276,14 @@ int main(int argc, const char **argv) { // Calculate the average Z coordinate of all vertices and use it to // determine the ordering table bucket index for this face. gte_command(GTE_CMD_AVSZ4 | GTE_SF); - int zIndex = gte_getDataReg(GTE_OTZ); + int zIndex = (int) gte_getDataReg(GTE_OTZ); - if ((zIndex < 0) || (zIndex >= ORDERING_TABLE_SIZE)) + if ((zIndex < 0) || (zIndex >= GPU_ORDERING_TABLE_SIZE)) continue; // Create a new quad and give its vertices the X/Y coordinates // calculated by the GTE. - ptr = allocatePacket(chain, zIndex, 5); + ptr = allocateGP0Packet(chain, zIndex, 5); ptr[0] = face->color | gp0_shadedQuad(false, false, false); ptr[1] = xy0; gte_storeDataReg(GTE_SXY0, 2 * 4, ptr); @@ -287,30 +291,36 @@ int main(int argc, const char **argv) { gte_storeDataReg(GTE_SXY2, 4 * 4, ptr); } - ptr = allocatePacket(chain, ORDERING_TABLE_SIZE - 1, 3); + ptr = allocateGP0Packet(chain, GPU_ORDERING_TABLE_SIZE - 1, 3); ptr[0] = gp0_rgb(64, 64, 64) | gp0_vramFill(); ptr[1] = gp0_xy(bufferX, bufferY); ptr[2] = gp0_xy(SCREEN_WIDTH, SCREEN_HEIGHT); - ptr = allocatePacket(chain, ORDERING_TABLE_SIZE - 1, 4); - ptr[0] = gp0_texpage(0, true, false); + ptr = allocateGP0Packet(chain, GPU_ORDERING_TABLE_SIZE - 1, 4); + ptr[0] = gp0_setPage(0, true, false); ptr[1] = gp0_fbOffset1(bufferX, bufferY); ptr[2] = gp0_fbOffset2( - bufferX + SCREEN_WIDTH - 1, bufferY + SCREEN_HEIGHT - 2 + bufferX + SCREEN_WIDTH - 1, + bufferY + SCREEN_HEIGHT - 1 ); ptr[3] = gp0_fbOrigin(bufferX, bufferY); // Draw some text in front of the cube. printString( - chain, &font, 16, 32, 0, - "PSX.Dev bare-metal CMake example\n" + chain, + &font, + 16, + 24, + 0, + "PSX.Dev / ps1-bare-metal CMake example\n" "PCSX-Redux project\n" - "https://bit.ly/pcsx-redux" + "https://github.com/grumpycoders/pcsx-redux\n" + "https://github.com/spicyjpeg/ps1-bare-metal" ); waitForGP0Ready(); waitForVSync(); - sendLinkedList(&(chain->orderingTable)[ORDERING_TABLE_SIZE - 1]); + sendGPULinkedList(&(chain->orderingTable)[GPU_ORDERING_TABLE_SIZE - 1]); } return 0; diff --git a/tools/vscode-extension/templates/bare-metal/cmake-cube/src/trig.c b/tools/vscode-extension/templates/bare-metal/cmake-cube/src/trig.c index a11f32c13..51dd41eeb 100644 --- a/tools/vscode-extension/templates/bare-metal/cmake-cube/src/trig.c +++ b/tools/vscode-extension/templates/bare-metal/cmake-cube/src/trig.c @@ -8,7 +8,7 @@ #define A (1 << 12) #define B 19900 -#define C 3516 +#define C 3516 int isin(int x) { int c = x << (30 - ISIN_SHIFT); diff --git a/tools/vscode-extension/templates/bare-metal/empty-cmake/CMakeLists.txt b/tools/vscode-extension/templates/bare-metal/empty-cmake/CMakeLists.txt index 7e9e4a340..b803c6309 100644 --- a/tools/vscode-extension/templates/bare-metal/empty-cmake/CMakeLists.txt +++ b/tools/vscode-extension/templates/bare-metal/empty-cmake/CMakeLists.txt @@ -16,22 +16,24 @@ project( HOMEPAGE_URL "https://github.com/grumpycoders/pcsx-redux" ) -# Set up compiler flags and initialize the Python environment used to run the -# scripts in the tools directory. +# Set up compiler flags, initialize the Python environment used to run the +# scripts in the tools directory and define some helper macros. include(ps1-bare-metal/cmake/setup.cmake) -include(ps1-bare-metal/cmake/virtualenv.cmake) +include(ps1-bare-metal/cmake/tools.cmake) -# Build a "common" library containing basic support code. We are going to link -# this library into our executable. +# Build a "common" library containing basic support code and link it by default +# into every executable. add_library( common OBJECT + ps1-bare-metal/src/libc/clz.s ps1-bare-metal/src/libc/crt0.c ps1-bare-metal/src/libc/cxxsupport.cpp ps1-bare-metal/src/libc/malloc.c - ps1-bare-metal/src/libc/memset.s ps1-bare-metal/src/libc/misc.c - ps1-bare-metal/src/libc/misc.s + ps1-bare-metal/src/libc/setjmp.s ps1-bare-metal/src/libc/string.c + ps1-bare-metal/src/libc/string.s + ps1-bare-metal/src/ps1/cache.s ps1-bare-metal/src/vendor/printf.c ) target_include_directories( @@ -39,25 +41,10 @@ target_include_directories( ps1-bare-metal/src ps1-bare-metal/src/libc ) +link_libraries(common) -# Create the main executable. You may add more source files by listing them -# after main.c. -add_executable( - {{projectName}} - src/main.c -) -target_link_libraries({{projectName}} PRIVATE common) - -# Add a step to run convertExecutable.py after the executable is compiled in -# order to convert it into a PS1 executable. By default all custom commands run -# from the build directory, so paths to files in the source directory must be -# prefixed with ${PROJECT_SOURCE_DIR}. -add_custom_command( - TARGET {{projectName}} POST_BUILD - BYPRODUCTS {{projectName}}.psexe - COMMAND - "${Python3_EXECUTABLE}" - "${PROJECT_SOURCE_DIR}/ps1-bare-metal/tools/convertExecutable.py" - "$" {{projectName}}.psexe - VERBATIM -) +# Compile the main executable; you may add more source files by listing them +# here. The addPS1Executable() macro is defined in tools.cmake and automatically +# takes care of converting the built ELF file into a PS1 executable (.psexe) +# which can run be run on emulators or real hardware. +addPS1Executable({{projectName}} src/main.c)