From 5fa60b6fb76e04ec39f497d55e9aaf45c28b7f64 Mon Sep 17 00:00:00 2001 From: ABelliqueux Date: Tue, 22 Dec 2020 11:52:22 +0100 Subject: [PATCH] add world, poly, vag --- README.md | 1 + VAG/hello_poly.vag | Bin 0 -> 38896 bytes hello_vag.c | 275 +++++++++++++++++++++++++++++++++++++++++++++ hello_world.c | 86 ++++++++++++++ 4 files changed, 362 insertions(+) create mode 100644 VAG/hello_poly.vag create mode 100644 hello_vag.c create mode 100644 hello_world.c diff --git a/README.md b/README.md index 92d3787..ef57c96 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,7 @@ That's it! When you'll type `make` next time, it should convert your files to .o # Links and Doc * [https://psx.arthus.net/starting.html](Getting started) + * [http://psx.arthus.net/sdk/Psy-Q/DOCS/](PsyQ Doc) * [https://ps1.consoledev.net/](Ps1 dev links) * [http://psxdev.net/](psxdev.net) * [https://discord.com/invite/N2mmwp?utm_source=Discord%20Widget&utm_medium=Connect](psxdev Discord) diff --git a/VAG/hello_poly.vag b/VAG/hello_poly.vag new file mode 100644 index 0000000000000000000000000000000000000000..fd984d894d33280201dd959a03e99b6f49b0b7ac GIT binary patch literal 38896 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 +#include + +#include +#include +#include + + +// Sound system +#include +#include + +#define VMODE 0 // Video Mode : 0 : NTSC, 1: PAL + +#define SCREENXRES 320 +#define SCREENYRES 240 + +#define CENTERX SCREENXRES/2 +#define CENTERY SCREENYRES/2 + +#define MARGINX 0 // margins for text display +#define MARGINY 32 + +#define FONTSIZE 8 * 7 // Text Field Height + +DISPENV disp[2]; // Double buffered DISPENV and DRAWENV +DRAWENV draw[2]; + +short db = 0; // index of which buffer is used, values 0, 1 + +// Sound stuff + +#define MALLOC_MAX 3 // Max number of time we can call SpuMalloc + +//~ // convert Little endian to Big endian +#define SWAP_ENDIAN32(x) (((x)>>24) | (((x)>>8) & 0xFF00) | (((x)<<8) & 0x00FF0000) | ((x)<<24)) + +typedef struct VAGheader{ // All the values in this header must be big endian + char id[4]; // VAGp 4 bytes -> 1 char * 4 + unsigned int version; // 4 bytes + unsigned int reserved; // 4 bytes + unsigned int dataSize; // (in bytes) 4 bytes + unsigned int samplingFrequency;// 4 bytes + char reserved2[12]; // 12 bytes -> 1 char * 12 + char name[16]; // 16 bytes -> 1 char * 16 + // Waveform data after that +}VAGhdr; + +SpuCommonAttr commonAttributes; // structure for changing common voice attributes +SpuVoiceAttr voiceAttributes ; // structure for changing individual voice attributes + +u_long vag_spu_address; // address allocated in memory for first sound file +u_long vag1_spu_address; // address allocated in memory for second sound file + +// DEBUG : these allow printing values for debugging + +u_long spu_start_address; +u_long get_start_addr; +u_long transSize; + +// Memory management table ; allow MALLOC_MAX calls to SpuMalloc() - ibref47.pdf p.1044 +char spu_malloc_rec[SPU_MALLOC_RECSIZ * (2 + MALLOC_MAX+1)]; + +// VAG files + +// We're using GrumpyCoder's Nugget wrapper to compile the code with a modern GCC : https://github.com/grumpycoders/pcsx-redux/tree/main/src/mips/psyq +// To include binary files in the exe, add your VAG files to the SRCS variable in Makefile +// and in common.mk, add this rule to include *.vag files : +// +//~ %.o: %.vag + //~ $(PREFIX)-objcopy -I binary --set-section-alignment .data=4 --rename-section .data=.rodata,alloc,load,readonly,data,contents -O elf32-tradlittlemips -B mips $< $@ + + +// hello_poly.vag - 44100 Khz +extern unsigned char _binary_VAG_hello_poly_vag_start[]; // filename must begin with _binary_ followed by the full path, with . and / replaced, and then suffixed with _ and end with _start[]; or end[]; +extern unsigned char _binary_VAG_hello_poly_vag_end[]; // https://discord.com/channels/642647820683444236/663664210525290507/780866265077383189 + +void initGraph(void) +{ + ResetGraph(0); + + SetDefDispEnv(&disp[0], 0, 0, SCREENXRES, SCREENYRES); + SetDefDispEnv(&disp[1], 0, SCREENYRES, SCREENXRES, SCREENYRES); + + SetDefDrawEnv(&draw[0], 0, SCREENYRES, SCREENXRES, SCREENYRES); + SetDefDrawEnv(&draw[1], 0, 0, SCREENXRES, SCREENYRES); + + if (VMODE) + { + SetVideoMode(MODE_PAL); + disp[0].screen.y += 8; + disp[1].screen.y += 8; + } + + setRGB0(&draw[0], 50, 50, 50); + setRGB0(&draw[1], 50, 50, 50); + + draw[0].isbg = 1; + draw[1].isbg = 1; + + PutDispEnv(&disp[db]); + PutDrawEnv(&draw[db]); + + FntLoad(960, 0); + FntOpen(8, 60, 304, 200, 0, 500 ); + +} + +void display(void) +{ + DrawSync(0); + VSync(0); + + PutDispEnv(&disp[db]); + PutDrawEnv(&draw[db]); + + SetDispMask(1); + + db = !db; + +} + + +// Audio initialisation & functions + +void initSnd(void){ + + SpuInitMalloc(MALLOC_MAX, spu_malloc_rec); // Maximum number of blocks, mem. management table address. + + commonAttributes.mask = (SPU_COMMON_MVOLL | SPU_COMMON_MVOLR); // Mask which attributes to set + commonAttributes.mvol.left = 0x3fff; // Master volume left + commonAttributes.mvol.right = 0x3fff; // see libref47.pdf, p.1058 + + SpuSetCommonAttr(&commonAttributes); // set attributes + + SpuSetIRQ(SPU_OFF); +} + +u_long sendVAGtoRAM(unsigned int VAG_data_size, unsigned char *VAG_data){ + u_long size; + + SpuSetTransferMode(SpuTransByDMA); // DMA transfer; can do other processing during transfer + + size = SpuWrite (VAG_data + sizeof(VAGhdr), VAG_data_size); // transfer VAG_data_size bytes from VAG_data address to sound buffer + + SpuIsTransferCompleted (SPU_TRANSFER_WAIT); // Checks whether transfer is completed and waits for completion + + return size; +} + +void setVoiceAttr(unsigned int pitch, long channel, unsigned long soundAddr ){ + + voiceAttributes.mask= //~ Attributes (bit string, 1 bit per attribute) + ( + SPU_VOICE_VOLL | + SPU_VOICE_VOLR | + SPU_VOICE_PITCH | + SPU_VOICE_WDSA | + SPU_VOICE_ADSR_AMODE | + SPU_VOICE_ADSR_SMODE | + SPU_VOICE_ADSR_RMODE | + SPU_VOICE_ADSR_AR | + SPU_VOICE_ADSR_DR | + SPU_VOICE_ADSR_SR | + SPU_VOICE_ADSR_RR | + SPU_VOICE_ADSR_SL + ); + + voiceAttributes.voice = channel; //~ Voice (low 24 bits are a bit string, 1 bit per voice ) + + voiceAttributes.volume.left = 0x1000; //~ Volume + voiceAttributes.volume.right = 0x1000; //~ Volume + + voiceAttributes.pitch = pitch; //~ Interval (set pitch) + voiceAttributes.addr = soundAddr; //~ Waveform data start address + + voiceAttributes.a_mode = SPU_VOICE_LINEARIncN; //~ Attack rate mode = Linear Increase - see libref47.pdf p.1091 + voiceAttributes.s_mode = SPU_VOICE_LINEARIncN; //~ Sustain rate mode = Linear Increase + voiceAttributes.r_mode = SPU_VOICE_LINEARDecN; //~ Release rate mode = Linear Decrease + + voiceAttributes.ar = 0x0; //~ Attack rate + voiceAttributes.dr = 0x0; //~ Decay rate + voiceAttributes.rr = 0x0; //~ Release rate + voiceAttributes.sr = 0x0; //~ Sustain rate + voiceAttributes.sl = 0xf; //~ Sustain level + + SpuSetVoiceAttr(&voiceAttributes); // set attributes + +} + +void playSFX(void){ + SpuSetKey(SpuOn,SPU_0CH | SPU_2CH); // Set several channels by ORing each channel bit ; channel 0 and 2 here. +} + +int main(void) +{ + short counter = 0; + + const VAGhdr * VAGfileHeader = (VAGhdr *) _binary_VAG_hello_poly_vag_start; // get header of VAG file + + // From libover47.pdf : + // The sampling frequency of the original audio file can be used to determine the pitch + // at which to play the VAG. pitch = (sampling frequency << 12)/44100L + // Ex: 44.1kHz=0x1000 22.05kHz=0x800 etc + + unsigned int pitch = (SWAP_ENDIAN32(VAGfileHeader->samplingFrequency) << 12) / 44100L; + + SpuInit(); // Initialize SPU. Called only once. + + initSnd(); + + //~ // First VAG + + vag_spu_address = SpuMalloc(SWAP_ENDIAN32(VAGfileHeader->dataSize)); // Allocate an area of dataSize bytes in the sound buffer. + + spu_start_address = SpuSetTransferStartAddr(vag_spu_address); // Sets a starting address in the sound buffer + + get_start_addr = SpuGetTransferStartAddr(); // SpuGetTransferStartAddr() returns current sound buffer transfer start address. + + transSize = sendVAGtoRAM(SWAP_ENDIAN32(VAGfileHeader->dataSize), _binary_VAG_hello_poly_vag_start); + + // set VAG to channel + + setVoiceAttr(pitch, SPU_0CH, vag_spu_address); + + initGraph(); + + while (1) + { + + if(!counter){ + playSFX(); + counter = 180; + } + + FntPrint("\nPitch : %08x-%dKhz", pitch, (SWAP_ENDIAN32(VAGfileHeader->samplingFrequency)) ); + FntPrint("\nSet Start addr : %08x", vag_spu_address); + FntPrint("\nReturn start addr : %08x", spu_start_address); + FntPrint("\nGet Start addr : %08x", get_start_addr); + FntPrint("\nSend size : %08x", SWAP_ENDIAN32(VAGfileHeader->dataSize)); + FntPrint("\nReturn size : %08x\n", transSize); + FntPrint("\nCounter : %d\n", counter); + + FntFlush(-1); + + counter --; + + display(); + + } + return 0; + } diff --git a/hello_world.c b/hello_world.c new file mode 100644 index 0000000..ac96f85 --- /dev/null +++ b/hello_world.c @@ -0,0 +1,86 @@ +// This is stolen from Lameguy64 tutorial : http://lameguy64.net/svn/pstutorials/chapter1/1-display.html + +#include +#include +#include +#include +#include + +#define VMODE 0 // Video Mode : 0 : NTSC, 1: PAL + +#define SCREENXRES 320 // Screen width +#define SCREENYRES 240 // Screen height + +#define CENTERX SCREENXRES/2 // Center of screen on x +#define CENTERY SCREENYRES/2 // Center of screen on y + +#define MARGINX 0 // margins for text display +#define MARGINY 32 + +#define FONTSIZE 8 * 7 // Text Field Height + +DISPENV disp[2]; // Double buffered DISPENV and DRAWENV +DRAWENV draw[2]; + +short db = 0; // index of which buffer is used, values 0, 1 + +void init(void) +{ + ResetGraph(0); // Initialize drawing engine with a complete reset (0) + + SetDefDispEnv(&disp[0], 0, 0 , SCREENXRES, SCREENYRES); // Set display area for both &disp[0] and &disp[1] + SetDefDispEnv(&disp[1], 0, SCREENYRES, SCREENXRES, SCREENYRES); // &disp[0] is on top of &disp[1] + + SetDefDrawEnv(&draw[0], 0, SCREENYRES, SCREENXRES, SCREENYRES); // Set draw for both &draw[0] and &draw[1] + SetDefDrawEnv(&draw[1], 0, 0 , SCREENXRES, SCREENYRES); // &draw[0] is below &draw[1] + + if (VMODE) // PAL + { + SetVideoMode(MODE_PAL); + disp[0].screen.y += 8; // add offset : 240 + 8 + 8 = 256 + disp[1].screen.y += 8; + } + + setRGB0(&draw[0], 50, 50, 50); // set color for first draw area + setRGB0(&draw[1], 50, 50, 50); // set color for second draw area + + draw[0].isbg = 1; // set mask for draw areas. 1 means repainting the area with the RGB color each frame + draw[1].isbg = 1; + + PutDispEnv(&disp[db]); // set the disp and draw environnments + PutDrawEnv(&draw[db]); + + FntLoad(960, 0); // Load font to vram at 960,0(+128) + FntOpen(MARGINX, SCREENYRES - MARGINY - FONTSIZE, SCREENXRES - MARGINX * 2, FONTSIZE, 0, 280 ); // FntOpen(x, y, width, height, black_bg, max. nbr. chars + +} + +void display(void) +{ + DrawSync(0); // Wait for all drawing to terminate + VSync(0); // Wait for the next vertical blank + + PutDispEnv(&disp[db]); // set alternate disp and draw environnments + PutDrawEnv(&draw[db]); + + SetDispMask(1); // Display on screen + + db = !db; // flip db value (0 or 1) +} + + +int main(void) +{ + + init(); // execute init() + + while (1) // infinite loop + { + FntPrint("Hello world !"); // Send string to print stream + + FntFlush(-1); // Draw printe stream + + display(); // Execute display() + } + return 0; + }