From 08de895e8582dbc70b639ae5f511ab9ebfb4d68a Mon Sep 17 00:00:00 2001 From: "U-Lameguy64-LT\\Lameguy64" Date: Mon, 17 Jan 2022 09:13:54 +0800 Subject: Removed old libn00bref.odt document, added tilesasm example, examples in source form now copied on installation, more graphics primitives documented, some changes to readme --- examples/graphics/hdtv/main.c | 64 +++-- examples/graphics/tilesasm/CMakeLists.txt | 22 ++ examples/graphics/tilesasm/data.s | 35 +++ examples/graphics/tilesasm/drawtiles.s | 272 +++++++++++++++++++ examples/graphics/tilesasm/iso.xml | 34 +++ examples/graphics/tilesasm/main.c | 425 ++++++++++++++++++++++++++++++ examples/graphics/tilesasm/system.cnf | 4 + examples/graphics/tilesasm/tiles_256.png | Bin 0 -> 9362 bytes examples/graphics/tilesasm/tiles_256.tim | Bin 0 -> 66080 bytes examples/readme.txt | 64 +++++ 10 files changed, 895 insertions(+), 25 deletions(-) create mode 100644 examples/graphics/tilesasm/CMakeLists.txt create mode 100644 examples/graphics/tilesasm/data.s create mode 100644 examples/graphics/tilesasm/drawtiles.s create mode 100644 examples/graphics/tilesasm/iso.xml create mode 100644 examples/graphics/tilesasm/main.c create mode 100644 examples/graphics/tilesasm/system.cnf create mode 100644 examples/graphics/tilesasm/tiles_256.png create mode 100644 examples/graphics/tilesasm/tiles_256.tim create mode 100644 examples/readme.txt (limited to 'examples') diff --git a/examples/graphics/hdtv/main.c b/examples/graphics/hdtv/main.c index a4dcd79..827b096 100644 --- a/examples/graphics/hdtv/main.c +++ b/examples/graphics/hdtv/main.c @@ -4,33 +4,45 @@ * Full-resolution, Anamorphic Widescreen 3D Example * 2020 - 2021 Meido-Tek Productions / PSn00bSDK Project * - * This example is a modification of the fpscam example demonstrating - * a method for taking advantage of widescreen HDTVs by means of a - * custom 704x480 video mode (as opposed to 640x480) and applying - * anamorphic widescreen aspect correction to a 3D perspective. + * This example is a modification of the fpscam example incorporating + * techniques for taking advantage of wide-screen televisions by means + * of a custom 704x480 video mode (as opposed to 640x480) and applying + * anamorphic aspect correction to a 3D perspective matrix. * - * The extended horizontal resolution guarantees that the picture will - * fill the entire screen of a widescreen television as the more - * conventional 640x480 mode would often show a black border on the sides - * of the picture. However, this extended video mode may cause odd effects - * on some analog television displays, so its recommended to implement this - * extended video mode as an option in your software title. Pixels are still - * not aspect correct however, so widescreen has to be achieved through - * anamorphic means, and is not exactly practical for most 2D graphics. + * The extended horizontal resolution guarantees that the video display + * will fill a wide-screen television in 16:9 mode fully, whereas the more + * conventional 640x480 mode displays black borders on the sides of the + * picture on most wide-screen television sets- notably LCD and Plasma type + * television sets. * - * If you wish to use a lower resolution 240/256 line mode but want to make - * it presentable on a widescreen television, use 384x240 or 384x256 as - * such a resolution would not only fill the entire screen of a widescreen - * but it also has close to aspect correct pixels, which is well suited for - * 2D games. The anamorphic aspect correction demonstrated in this example - * should also work for 320x240/256 modes for 3D games, but prefer to use - * 320x240 resolution. + * However, this extended video mode may cause display problems on some + * analog television sets- such as conventional ratio Sony Trinitron + * televisions if the video display is moved too close to the left of the + * screen. Therefore it is recommended to support this extended video mode + * as an option to ensure compatibility with affected televisions. * - * When using 240/256 line modes, you may want to include an option in your - * software title to enable interlace even though your software title does not - * run in high resolution mode. This helps with compatibility on HDTVs - * immensely and in some cases, improves the image quality on such - * televisions. + * Use of the extended video mode does not provide aspect correct pixels + * for widescreen displays (the extended mode merely displays more columns + * of pixels to fill the side borders of widescreen displays), thus 2D + * bitmap graphics will appear stretched as it would when using a more + * conventional 640x480 display resolution on a wide-screen ratio + * television. + * + * If lower resolution 240/256 line mode is desired whilst being presentable + * on a wide-screen television display, use 384x240 or 384x256 as those + * display resolutions can not only cover the side borders of a wide-screen + * television display but it also provides close to aspect correct pixels + * on such television sets and is well suited for 2D games. The anamorphic + * aspect correction demonstrated in this example can also work on the more + * conventional 320x240/256 modes for 3D games when such resolutions are more + * desired. + * + * When 240/256 line video modes are used, it is highly recommended to + * consider implementing an option to enable interlace even if the software + * title does not run in high resolution mode. This is to provide + * compatibility with digital EDTV or HDTV televisions as some of these + * televisions have issues accepting non-interlaced video signals. On some + * televisions enabling interlace can improve the picture quality. * * Controls: * Up - Look up @@ -43,7 +55,7 @@ * Circle - Strafe right * R1 - Slide up * R2 - Slide down - * L1 - Look at cube + * L1 - Look at cube (tracking) * Select - Exit program (only works with CD loaders) * * @@ -51,6 +63,8 @@ * * Changelog: * + * November 23, 2021 - Improved example description. + * * May 10, 2021 - Variable types updated for psxgpu.h changes. * * November 27, 2020 - Initial version. diff --git a/examples/graphics/tilesasm/CMakeLists.txt b/examples/graphics/tilesasm/CMakeLists.txt new file mode 100644 index 0000000..59ef665 --- /dev/null +++ b/examples/graphics/tilesasm/CMakeLists.txt @@ -0,0 +1,22 @@ +# PSn00bSDK example CMake script +# (C) 2021 spicyjpeg - MPL licensed + +cmake_minimum_required(VERSION 3.20) + +if(NOT DEFINED CMAKE_TOOLCHAIN_FILE AND DEFINED ENV{PSN00BSDK_LIBS}) + set(CMAKE_TOOLCHAIN_FILE $ENV{PSN00BSDK_LIBS}/cmake/sdk.cmake) +endif() + +project( + tilesasm + LANGUAGES C ASM + VERSION 1.0.0 + DESCRIPTION "PSn00bSDK Tiles drawing with assembly example" + HOMEPAGE_URL "http://lameguy64.net/?page=psn00bsdk" +) + +file(GLOB _sources *.s *.c) +psn00bsdk_add_executable(tilesasm STATIC ${_sources}) +#psn00bsdk_add_cd_image(tilesasm_iso tilesasm iso.xml DEPENDS tilesasm) + +install(FILES ${PROJECT_BINARY_DIR}/tilesasm.exe TYPE BIN) diff --git a/examples/graphics/tilesasm/data.s b/examples/graphics/tilesasm/data.s new file mode 100644 index 0000000..c64ebbc --- /dev/null +++ b/examples/graphics/tilesasm/data.s @@ -0,0 +1,35 @@ +# +# LibPSn00b Example Programs +# +# Drawing Tile-maps with Assembler Routines +# 2022 Meido-Tek Productions / PSn00bSDK Project +# +# Example by John "Lameguy" Wilbert Villamor (Lameguy64) +# +# This assembler file is used to include the file tiles.tim as an array named +# 'tim_tileset' for use in this example program. Note how the variable name +# itself is leading with an underscore (_) in this file. This is because +# GNU C requires leading underscores for global variables, perhaps to prevent +# function names and variable names from mixing up during the linking stage. + +# Tell assembler that the contents that follow must be in the .data section +.section .data + +# This directive define the 'tim_tileset' label as a global symbol so that +# main.c and other program modules can see this symbol during linking +.global tim_tileset + +# This directive is not really required, but its best to define symbols +# not pointing to program code as an object to help identify it as a +# variable in debuggers +.type tim_tileset, @object + +# The following line defines the variable 'tim_tileset' itself filled with the +# contents of the file 'tiles.tim' by using the .incbin directive +# +# Remember the variable type of a symbol is always governed by how it is +# declared in the C code +# +tim_tileset: + .incbin "../tiles_256.tim" + \ No newline at end of file diff --git a/examples/graphics/tilesasm/drawtiles.s b/examples/graphics/tilesasm/drawtiles.s new file mode 100644 index 0000000..15a0707 --- /dev/null +++ b/examples/graphics/tilesasm/drawtiles.s @@ -0,0 +1,272 @@ +# +# LibPSn00b Example Programs +# +# Drawing Tile-maps with Assembler Routines +# 2022 Meido-Tek Productions / PSn00bSDK Project +# +# Example by John "Lameguy" Wilbert Villamor (Lameguy64) +# +# This file contains the assembler routine DrawTiles which can be called from +# a C or C++ compiled module. The routine makes use of constants and assembler +# macros written in the GNU GAS syntax. +# +# Assembler routines called from C-language modules can freely use registers +# $v0-$v1, $at, $a0-$a3, $t0-$t9 without preserving through stack. Registers +# $s0-$s9, $gp and $fp must be preserved through stack before returning and +# registers $k0-$k1 should not be used for obvious reasons (kernel registers). +# $sp and $ra is used as stack pointer and return address respectively. +# $0 or $zero is constantly zero. +# +# A C caller always passes arguments as 32-bit values on registers $a0 to $a3 +# regardless of the data type specified in the function's C declaration. +# Additional arguments are stored in the stack 16 bytes relative to the stack +# pointer ($sp). To get around the stack being modified in different parts of +# a larger routine the stack pointer would be copied to the frame pointer ($fp) +# and the previous value of the frame pointer would be pushed into stack. This +# way additional arguments may be read anywhere starting from $fp+20 instead. +# +.set noreorder # Disable GAS' annoying nop insertion + +.equ db, 1 # Constants for "emulating" SNASM style structs +.equ dh, 2 +.equ dw, 4 + +# +# TILEDEF struct +# + rs=0 # rs is used to emulate SNASM style structs +.equ TILEDEF_uv , rs # Tile texture coordinate + rs=rs+dh +.equ TILEDEF_clut , rs # Tile CLUT + rs=rs+dh +.equ TILEDEF_pad , rs # Padding + rs=rs+dh +.equ TILEDEF_tpage , rs # Tile tpage + rs=rs+dh +.equ TILEDEF_len , rs # Entry length + +# +# TILEINFO struct (to use as offsets) +# + rs=0 +.equ TILEINFO_window_x , rs # \ + rs=rs+dh # - Window coordinates +.equ TILEINFO_window_y , rs # / + rs=rs+dh +.equ TILEINFO_window_w , rs # \ + rs=rs+dh # - Window size +.equ TILEINFO_window_h , rs # / + rs=rs+dh +.equ TILEINFO_tiles , rs # Pointer to TILEDEF entries + rs=rs+dw +.equ TILEINFO_mapdata , rs # Pointer to map data + rs=rs+dw +.equ TILEINFO_map_w , rs # Map width in tile units + rs=rs+dh +.equ TILEINFO_map_h , rs # Map height in tile units + rs=rs+dh + +# +# TILEPKT struct +# + rs=0 +.equ TILEPKT_tag , rs # Primitive tag + rs=rs+dw +.equ TILEPKT_tpage , rs # tpage packet + rs=rs+dw +.equ TILEPKT_rgbc , rs # Tile color + rs=rs+dw +.equ TILEPKT_x , rs # Tile screen coordinates + rs=rs+dh +.equ TILEPKT_y , rs + rs=rs+dh +.equ TILEPKT_uv , rs # Tile texture coordinates + rs=rs+dh +.equ TILEPKT_clut , rs # Tile CLUT + rs=rs+dh +.equ TILEPKT_len , rs # Packet length + +# addprim Macro +# +# Registers a primitive to a ordering table entry. +# +# Arguments: +# ot - Register name of pointer to ordering table entry +# pri - Pointer to a primitive packet +# len - Size of packet in long words (specify as 0xnn00, ie. 0x2000) +# +# Destroys: +# at, v0, v1 +# +.macro addprim ot,pri,len + .set noat + lw $v0, 0(\ot) # Get OT entry + lui $at, 0x00ff # Mask out the packet length field + or $at, 0xffff + and $v0, $at + lui $v1, \len # Merge packet length + or $v1, $v0 + sw $v1, 0(\pri) # Store updated OT entry to packet + lw $v0, 0(\ot) # Get OT entry + and \pri, $at # Mask out last 8-bits of packet address + lui $at, 0xff00 # Mask out OT entry's address + and $v0, $at + or $v0, \pri # Merge packet address to OT entry + sw $v0, 0(\ot) # Store updated OT entry + .set at +.endm + +# +# Start of text section +# +.section .text + +# DrawTiles Function +# +# Renders a tilemap by generating TILEPKT primitives (combined SPRT_16 and +# DR_TPAGE primitives) and registering it to the specified ordering table. +# The drawing region, tile definitions and the tilemap are specified through +# a TILEINFO struct. +# +# C Declaration: +# extern u_char *DrawTiles(int scroll_x, int scroll_y, +# TILEINFO *info, long *ot, u_char *pri); +# +# Arguments: +# scroll_x - X scrolling offset of tile-map +# scroll_y - Y scrolling offset of tile-map +# info - Pointer to a TILEINFO struct +# ot - Pointer to a ordering table entry +# pri - Pointer to next primitive (placed in stack) +# +# Returns: +# New next primitive pointer value. +# +.global DrawTiles # Declare symbol as global +.type DrawTiles, @function # Declare it as a function +DrawTiles: # Symbol label of function + + addiu $sp, -4 # Push frame pointer (fp) to stack + sw $fp, 0($sp) + move $fp, $sp # Copy stack pointer (sp) to fp + + # Register reference: + # + # t0 - Packet address + # t1 - Map data address + # t2 - Tile X offset + # t3 - Tile Y offset + # t4 - Tile X coordinate backup + # t5 - Tile X loop counter + # t6 - Number of tiles to sort per row + # t7 - Number of tile rows to sort + + lhu $t6, TILEINFO_window_w($a2) # Calculate size of window in tiles + lhu $t7, TILEINFO_window_h($a2) + addi $t6, 15 # So the result will be rounded-up + addi $t7, 15 + srl $t6, 4 # Effectively divide by 16 + srl $t7, 4 + + lw $t0, 20($sp) # Obtain next primitive pointer + + srl $t2, $a0, 4 # Compute map offset in tile units + srl $t3, $a1, 4 + + bgez $a0, .Lno_neg_clip_X # Negative X clip test + sub $v0, $0 , $a0 + move $t2, $0 # Force tile offset to zero + add $v0, 15 # Reduce number of tile columns + srl $v0, 4 + sub $t6, $v0 +.Lno_neg_clip_X: + lhu $v1, TILEINFO_map_w($a2) # Positive X clip test + add $v0, $t2, $t6 + addi $v0, 1 + blt $v0, $v1, .Lno_pos_clip_X + nop + sub $v0, $v1 # Compute how many tiles to clip + sub $t6, $v0 # Reduce number of tile columns +.Lno_pos_clip_X: + bgez $a1, .Lno_neg_clip_Y # Negative Y clip test + sub $v0, $0 , $a1 + move $t3, $0 + add $v0, 15 + srl $v0, 4 + sub $t7, $v0 +.Lno_neg_clip_Y: + lhu $v1, TILEINFO_map_h($a2) # Positive Y clip test + add $v0, $t3, $t7 + addi $v0, 1 + blt $v0, $v1, .Lno_pos_clip_Y + nop + sub $v0, $v1 + sub $t7, $v0 +.Lno_pos_clip_Y: + bltz $t6, .Lno_draw # Exit when no tiles to draw + nop + bltz $t7, .Lno_draw + nop + + lh $v0, TILEINFO_window_x($a2) # Compute pixel coordinates for + sub $a0, $v0, $a0 # tiles based on the scroll offset + sll $v0, $t2, 4 + add $a0, $v0 + lh $v0, TILEINFO_window_y($a2) + sub $a1, $v0, $a1 + sll $v0, $t3, 4 + add $a1, $v0 + move $t4, $a0 + sll $t2, 1 + +.Lloop_y: # Begin of tile row loop + lhu $v0, TILEINFO_map_w($a2) # Get width of tilemap + move $t5, $t6 # n tiles to draw row + mult $t3, $v0 # Multiply Y offset by map width + lw $t1, TILEINFO_mapdata($a2) # Get tilemap address + nop + addu $t1, $t2 # Add X offset to address + mflo $v0 # Get Y offset result + sll $v0, 1 # Multiply by two + addu $t1, $v0 # Add to tile address + +.Lloop_x: # Begin of tile column loop + lhu $v1, 0($t1) # Load tile index + addiu $t1, 2 # Advance to next tile + beq $v1, 0xFFFF, .Lskip_tile # Skip tile if index is 0xFFFF + nop + lw $v0, TILEINFO_tiles($a2) # Get pointer to TILEDEF entries + sll $v1, 3 # Multiply by 8 (size of TILEDEFs) + addu $v1, $v0 # Adjust to tiledefs pointer + lw $v0, TILEDEF_uv($v1) # Obtain UV+CLUT + lhu $v1, TILEDEF_tpage($v1) # Obtain tpage + sw $v0, TILEPKT_uv($t0) # Start constructing packet + lui $v0, 0xE100 # tpage packet code + or $v0, $v1 # Merge tpage bits + sw $v0, TILEPKT_tpage($t0) + sh $a0, TILEPKT_x($t0) # Set tile screen coords + sh $a1, TILEPKT_y($t0) + li $v0, 0x7C7F7F7F # Packet code and color + sw $v0, TILEPKT_rgbc($t0) + addprim $a3, $t0, 0x0400 # Register to OT + addiu $t0, TILEPKT_len # Advance packet pointer +.Lskip_tile: + addi $t5, -1 # Decrement and continue iterating + bgez $t5, .Lloop_x # if non-zero + addiu $a0, 16 # Advance X tile coordinate + + move $a0, $t4 # Restore tile X coordinate + addi $t3, 1 # Increment Y offset + addi $t7, -1 # Decrement and continue iterating + bgez $t7, .Lloop_y # if non-zero + addiu $a1, 16 # Advance Y tile coordinate + +.Lno_draw: + + move $v0, $t0 # Set packet pointer as return value + + lw $fp, 0($sp) # Restore frame pointer and return + jr $ra + addiu $sp, 4 + # DrawTiles + \ No newline at end of file diff --git a/examples/graphics/tilesasm/iso.xml b/examples/graphics/tilesasm/iso.xml new file mode 100644 index 0000000..477c636 --- /dev/null +++ b/examples/graphics/tilesasm/iso.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + diff --git a/examples/graphics/tilesasm/main.c b/examples/graphics/tilesasm/main.c new file mode 100644 index 0000000..7f7c7fe --- /dev/null +++ b/examples/graphics/tilesasm/main.c @@ -0,0 +1,425 @@ +/* + * LibPSn00b Example Programs + * + * Drawing Tile-maps with Assembler Routines + * 2022 Meido-Tek Productions / PSn00bSDK Project + * + * Example by John "Lameguy" Wilbert Villamor (Lameguy64) + * + * Demonstrates the use of assembler code to write a high-speed graphics + * routine that draws a 2D tile-map by generating SPRT_16 primitives. + * The assembler routine is called from a compiled C module in a manner no + * different to calling a C routine... A program written in this manner is + * known as mixed-language programming which includes other programming + * languages, not just assembly. + * + * This example also demonstrates using assembler files to include data files + * into a program as arrays (see 'data.s'). Arguably much more elegant and + * convenient than converting files to C headers like in the old days. + * + * The tile data and drawing is handled in a manner similar to that of the + * tile-map drawing functions in libgs where the map data consists of 16-bit + * words with 0xFFFF being a transparent tile, with each tile entry defined + * by an array of structs specifying the tpage, clut and u,v coordinates for + * each tile number. This provides flexibility with how the tile data will be + * organized in the framebuffer. + * + * Per-pixel clipping of the tile-map is actually not performed by the + * DrawTiles function but rather with DR_AREA primitives. This method + * eliminates code overhead from performing the clipping operations in + * software and thus, yields the fastest possible performance for tile + * sorting. Use of the DR_AREA primitive must be handled with care, as + * setting it beyond the display buffers could overwrite textures and + * CLUT data. + * + * Changelog: + * + * January 16, 2022 - Initial version. + * + * Controls: + * + * D-pad - Scroll tile-map + * L1 (hold) - Move tile-map window with D-pad (must be shrunk first) + * L2 (hold) - Resize tile-map window with D-pad + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Constants for convenience + */ +#define OT_LEN 4 /* Number of ordering table entries */ +#define PKTBUFF_LEN 32768 /* Size of packet buffer (in bytes) */ + +/* Define display/draw environments for double buffering */ +DISPENV disp[2]; +DRAWENV draw[2]; +int db; + +/* Define the ordering table and packet buffer arrays */ +long ot[2][OT_LEN]; +char pkt[2][PKTBUFF_LEN]; + +/* Next packet pointer for primitive generation */ +char *pkt_addr; + +/* Pad data buffer */ +char pad_buff[2][34]; + +/* + * Tile definition structure (to define VRAM coordinates of tiles) + */ +typedef struct _TILEDEF +{ + u_char u,v; // Texture coordinates of tile + u_short clut; // CLUT number of tile + u_short pad; // Padding + u_short tpage; // Texture page number +} TILEDEF; + +/* + * Tile info structure (for drawing function) + */ +typedef struct _TILEINFO +{ + RECT window; // Drawing window of tile info (only cull, not clip) + TILEDEF *tiles; // Pointer to TILEDEF array + u_short *mapdata; // Pointer to 16-bit map data + u_short map_w; // Tile map dimensions + u_short map_h; +} TILEINFO; + +/* Define array of tiledefs */ +TILEDEF tiles[256]; + +/* + * Declarations for data.s + */ +extern u_long tim_tileset[]; + +/* + * Declarations for drawtiles.s + */ +extern u_char *DrawTiles(int scroll_x, int scroll_y, + TILEINFO *info, long *ot, u_char *pri); + +/* + * Init function + */ +void init(void) +{ + TIM_IMAGE tim; + + int i,tx,ty; + + // This not only resets the GPU but it also installs the library's + // ISR subsystem to the kernel + ResetGraph(0); + + // Define display environments, first on top and second on bottom + SetDefDispEnv(&disp[0], 0, 0, 320, 240); + SetDefDispEnv(&disp[1], 0, 240, 320, 240); + + // Define drawing environments, first on bottom and second on top + SetDefDrawEnv(&draw[0], 0, 240, 320, 240); + SetDefDrawEnv(&draw[1], 0, 0, 320, 240); + + // Set and enable clear color + setRGB0(&draw[0], 0, 96, 0); + setRGB0(&draw[1], 0, 96, 0); + draw[0].isbg = 1; + draw[1].isbg = 1; + + // Setup buffer counter, packet pointer and ordering tables + db = 0; + pkt_addr = pkt[db]; + + // Clear ordering tables + ClearOTagR(ot[0], OT_LEN); + ClearOTagR(ot[1], OT_LEN); + + // Load test font + FntLoad(960, 0); + + // Open up a test font text stream of 100 characters + FntOpen(0, 8, 320, 224, 0, 100); + + // Upload tileset TIM + GetTimInfo((u_long*)tim_tileset, &tim); /* Get TIM parameters */ + LoadImage(tim.prect, tim.paddr); /* Upload texture to VRAM */ + if( tim.mode & 0x8 ) /* Upload CLUT if present */ + LoadImage(tim.crect, tim.caddr); + + // Initialize tiledefs with coords to the tileset TIM + i = 0; + for(ty=0; ty<16; ty++) + { + for(tx=0; tx<16; tx++) + { + tiles[i].u = tx<<4; + tiles[i].v = ty<<4; + tiles[i].tpage = getTPage(tim.mode & 3, 0, + tim.prect->x, tim.prect->y); + tiles[i].clut = getClut(tim.crect->x, tim.crect->y); + i++; + } + } + + // Initialize pads + InitPAD(&pad_buff[0][0], 34, &pad_buff[1][0], 34); + StartPAD(); + ChangeClearPAD(0); + +} /* init */ + +/* + * Display function + */ +void display(void) +{ + // Wait for all drawing to complete + DrawSync(0); + + // Wait for vertical sync to cap the logic to 60fps (or 50 in PAL mode) + // and avoid screen tearing + VSync(0); + + // Switch pages + PutDispEnv(&disp[db]); + PutDrawEnv(&draw[db]); + + // Begin drawing of the ordering table + DrawOTag(ot[db]+(OT_LEN-1)); + + // Toggle buffer index + db = !db; + + // Clear next ordering table array + ClearOTagR(ot[db], OT_LEN); + + // Reset packet pointer + pkt_addr = pkt[db]; + + // Enable display output, ResetGraph() disables it by default + SetDispMask(1); + +} /* display */ + +/* + * Initializes a randomly generated tile map + */ +void initdata(u_short *tiledata, int w, int h) +{ + int tx,ty; + + for(ty=0; tyx, rect->y, + rect->x, rect->y+rect->h, + ot[db]); + sortLine(rect->x+rect->w, rect->y, + rect->x+rect->w, rect->y+rect->h, + ot[db]); + sortLine(rect->x, rect->y, + rect->x+rect->w, rect->y, + ot[db]); + sortLine(rect->x, rect->y+rect->h, + rect->x+rect->w, rect->y+rect->h, ot[db]); + +} /* sortBox */ + +/* + * Sorts a draw area primitive for hardware clipping + */ +void sortDrawEnv(RECT *drawarea) +{ + DR_AREA *drawpkt; + + drawpkt = (DR_AREA*)pkt_addr; + setDrawArea(drawpkt, drawarea); + addPrim(ot[db], drawpkt); + pkt_addr += sizeof(DR_AREA); + +} /* sortDrawEnv */ + +/* + * Main function + */ +int main(int argc, const char *argv[]) +{ + u_short *tiledata; + TILEINFO tileinfo; + PADTYPE *pad; + RECT cliprect; + + int i,scroll_x,scroll_y; + + /* Init stuff */ + init(); + + /* Allocate buffer for tile data */ + tiledata = (u_short*)malloc((256*256)<<1); + + /* Generate a random tilemap of values 0-255 */ + initdata(tiledata, 256, 256); + + /* Define the TILEINFO struct */ + tileinfo.window.x = 0; + tileinfo.window.y = 0; + tileinfo.window.w = 320; + tileinfo.window.h = 240; + tileinfo.tiles = tiles; + tileinfo.mapdata = tiledata; + tileinfo.map_w = 256; + tileinfo.map_h = 256; + + /* Main loop */ + scroll_x = 0; + scroll_y = 0; + + while(1) + { + /* Handle inputs */ + pad = (PADTYPE*)&pad_buff[0][0]; + + if( pad->stat == 0 ) + { + if( ( pad->type == 0x4 ) || + ( pad->type == 0x5 ) || + ( pad->type == 0x7 ) ) + { + if( !(pad->btn&PAD_L1) ) /* Window resize */ + { + if( !(pad->btn&PAD_UP) && ( tileinfo.window.y > 0 ) ) + { + tileinfo.window.y--; + } + i = tileinfo.window.y+tileinfo.window.h; + if( !(pad->btn&PAD_DOWN) && ( i < disp[db].disp.h ) ) + { + tileinfo.window.y++; + } + if( !(pad->btn&PAD_LEFT) && ( tileinfo.window.x > 0 ) ) + { + tileinfo.window.x--; + } + i = tileinfo.window.x+tileinfo.window.w; + if( !(pad->btn&PAD_RIGHT) && ( i < disp[db].disp.w ) ) + { + tileinfo.window.x++; + } + } + else if( !(pad->btn&PAD_L2) ) /* Window move */ + { + if( !(pad->btn&PAD_UP) && ( tileinfo.window.h > 0 ) ) + { + tileinfo.window.h--; + } + i = tileinfo.window.y+tileinfo.window.h; + if( !(pad->btn&PAD_DOWN) && ( i < disp[db].disp.h ) ) + { + tileinfo.window.h++; + } + if( !(pad->btn&PAD_LEFT) && ( tileinfo.window.w > 0 ) ) + { + tileinfo.window.w--; + } + i = tileinfo.window.y+tileinfo.window.h; + if( !(pad->btn&PAD_RIGHT) && ( i < disp[db].disp.w ) ) + { + tileinfo.window.w++; + } + } + else /* Scrolling */ + { + if( !(pad->btn&PAD_UP) ) + { + scroll_y-=2; + } + if( !(pad->btn&PAD_DOWN) ) + { + scroll_y+=2; + } + if( !(pad->btn&PAD_LEFT) ) + { + scroll_x-=2; + } + if( !(pad->btn&PAD_RIGHT) ) + { + scroll_x+=2; + } + } + } + } + + /* Draw a box around the tile-map window */ + sortBox(&tileinfo.window); + + /* Sort default clipping (this is processed last) */ + sortDrawEnv(&draw[db].clip); + + /* Sort the tiles */ + pkt_addr = DrawTiles(scroll_x, scroll_y, + &tileinfo, ot[db], pkt_addr); + + /* Sort clipping to the tile window */ + cliprect = tileinfo.window; + cliprect.y += draw[db].clip.y; + sortDrawEnv(&cliprect); + + /* Print stats */ + FntPrint(-1, "X=%d Y=%d\n", scroll_x, scroll_y); + FntPrint(-1, "WINDOW POS. (%d,%d)\n", + tileinfo.window.x, tileinfo.window.y); + FntPrint(-1, "WINDOW SIZE (%d,%d)\n", + tileinfo.window.w, tileinfo.window.h); + FntFlush(-1); + + /* Refresh display */ + display(); + } + + return 0; + +} /* main */ diff --git a/examples/graphics/tilesasm/system.cnf b/examples/graphics/tilesasm/system.cnf new file mode 100644 index 0000000..e221726 --- /dev/null +++ b/examples/graphics/tilesasm/system.cnf @@ -0,0 +1,4 @@ +BOOT=cdrom:\template.exe;1 +TCB=4 +EVENT=10 +STACK=801FFFF0 diff --git a/examples/graphics/tilesasm/tiles_256.png b/examples/graphics/tilesasm/tiles_256.png new file mode 100644 index 0000000..e58c06c Binary files /dev/null and b/examples/graphics/tilesasm/tiles_256.png differ diff --git a/examples/graphics/tilesasm/tiles_256.tim b/examples/graphics/tilesasm/tiles_256.tim new file mode 100644 index 0000000..1bb59bb Binary files /dev/null and b/examples/graphics/tilesasm/tiles_256.tim differ diff --git a/examples/readme.txt b/examples/readme.txt new file mode 100644 index 0000000..80747de --- /dev/null +++ b/examples/readme.txt @@ -0,0 +1,64 @@ +PSn00bSDK Example Programs +2019 - 2022 Meido-Tek Productions / PSn00bSDK Project + +## Building the examples ## + +The instructions below assumes that a mipsel-unknown-elf or mipsel-none-elf GNU +toolchain is installed, CMake and Ninja or make is installed and the PSn00bSDK +libraries and tools are compiled and installed. CMake version must be at least +version 3.20 or newer. + +1. If the examples are in /usr/local/share, copy the directory into your home + directory. + +2. Configure the examples with CMake by running: + + cmake -S . -B ./build -DCMAKE_TOOLCHAIN_FILE= + + must point to the sdk.cmake file provided by the SDK. + Unless you've installed the SDK with a custom path, normally this file is + located in /usr/local/lib/libpsn00b/cmake on *nix style systems or + C:\Program Files\PSn00bSDK\lib\libpsn00b\cmake in Windows. + + If the mipsel toolchain has a different prefix (ie. mipsel-none-elf), specify + -DPSN00BSDK_TARGET= to override the default toolchain prefix. + + If Ninja does not work for you or don't have it installed, pass + -G "Unix Makefiles" (or -G "MSys Makefiles" on Windows) to build using make + instead. + +3. Build the example programs by running: + + cmake --build ./build + + This should create a build directory with a directory structure that mirrors + the parent directory. The directories should contain compiled versions of the + example programs as a PS-EXE or ISO file. + + +## Examples summary ## + +The following list is a brief summary of all the example programs included. +Additional information may be found in the source code of each example. + + beginner/cppdemo Simple demonstration of (dynamic) C++ classes + beginner/hello The obligatory "Hello World" example program + cdrom/cdbrowse File browser using libpsxcd's directory functions + cdrom/cdxa Plays CD-XA audio (XA audio not included) + demos/n00bdemo The premiere demonstration program of PSn00bSDK + graphics/balls Draws colored balls bouncing around the screen + graphics/billboard Demonstrates how to draw 2D sprites in a 3D space + graphics/fpscam First-person perspective camera with look-at + graphics/gte Displays a rotating cube using GTE macros + graphics/hdtv Demonstrates anamorphic widescreen at 704x480 + graphics/render2tex Procedural texture effects using off-screen drawing + graphics/rgb24 Displays a 640x480 24-bit RGB image + graphics/tilesasm Drawing a tile-map with assembly language + io/pads Demonstrates reading controllers via low-level access + lowlevel/cartrom ROM firmware for cheat devices written using GNU GAS + sound/vagsample Demonstrates playing VAG sound files with the SPU + system/childexec Loading a child program and returning to parent + system/console TTY based text console that interrupts gameplay + system/dynlink Demonstrates dynamically linked libraries + system/timer Demonstrates using hardware timers with interrupts + system/tty Using TTY as a remote text console interface \ No newline at end of file -- cgit v1.2.3