diff --git a/build.sh b/build.sh index 90c7a52..28a8ef7 100755 --- a/build.sh +++ b/build.sh @@ -7,6 +7,8 @@ clang-format -i src/ppu.h clang-format -i src/ppu.c clang-format -i src/apu.h clang-format -i src/apu.c +clang-format -i src/mpu.h +clang-format -i src/mpu.c clang-format -i src/assembler.c clang-format -i src/emulator.c clang-format -i src/debugger.c @@ -23,12 +25,12 @@ if [ "${1}" = '--debug' ]; then echo "[debug]" cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined src/assembler.c -o bin/assembler - cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined src/uxn.c src/ppu.c src/emulator.c src/apu.c -L/usr/local/lib -lSDL2 -o bin/emulator + cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined src/uxn.c src/ppu.c src/apu.c src/mpu.c src/emulator.c -L/usr/local/lib -lSDL2 -lportmidi -o bin/emulator cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined src/uxn.c src/debugger.c -o bin/debugger else cc src/assembler.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o bin/assembler cc src/uxn.c src/debugger.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o bin/debugger - cc src/uxn.c src/ppu.c src/emulator.c src/apu.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -L/usr/local/lib -lSDL2 -o bin/emulator + cc src/uxn.c src/ppu.c src/apu.c src/mpu.c src/emulator.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -L/usr/local/lib -lSDL2 -lportmidi -o bin/emulator fi echo "Assembling.." diff --git a/projects/demos/piano.usm b/projects/demos/piano.usm index 9b001fe..c7e77bf 100644 --- a/projects/demos/piano.usm +++ b/projects/demos/piano.usm @@ -10,10 +10,12 @@ ( devices ) |00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ] +|10 @Console [ &pad $8 &char $1 &byte $1 &short $2 &string $2 ] |20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &color $1 ] |30 @Audio [ &pad $8 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ] |40 @Controller [ &vector $2 &button $1 &key $1 ] |60 @Mouse [ &vector $2 &x $2 &y $2 &state $1 &chord $1 ] +|90 @Midi [ &vector $2 &message $2 ] ( variables ) @@ -42,6 +44,8 @@ ( vectors ) ;on-control .Controller/vector DEO2 ;on-mouse .Mouse/vector DEO2 + ;on-midi .Midi/vector DEO2 + ;on-frame .Screen/vector DEO2 ( find center ) .Screen/width DEI2 2/ .center/x POK2 @@ -79,6 +83,23 @@ BRK +@on-frame ( -> ) + + .wave-view/x1 PEK2 #0028 ADD2 .Screen/x DEO2 + .wave-view/y1 PEK2 #0010 SUB2 .Screen/y DEO2 + .Audio/volume DEI #04 SFT TOS #0008 MUL2 ;meter ADD2 .Screen/addr DEO2 + #21 .Screen/color DEO + #88 .Audio/volume DEO + + +BRK + +@on-midi ( -> ) + + .Midi/message DEI .Audio/pitch DEO + +BRK + @on-mouse ( -> ) ;draw-cursor JSR2 @@ -436,6 +457,24 @@ RTN 07 06 05 03 02 01 00 00 00 00 01 02 03 05 06 07 ] +@meter [ + 0000 0000 0000 0000 + 0000 0000 0000 0070 + 0000 0000 0000 007e + 0000 0000 0000 707e + 0000 0000 0070 7e7e + 0000 0000 007e 7e7e + 0000 0000 707e 7e7e + 0000 0000 7e7e 7e7e + 0000 0070 7e7e 7e7e + 0000 007e 7e7e 7e7e + 0000 707e 7e7e 7e7e + 0000 7e7e 7e7e 7e7e + 0070 7e7e 7e7e 7e7e + 007e 7e7e 7e7e 7e7e + 707e 7e7e 7e7e 7e7e + 7e7e 7e7e 7e7e 7e7e ] + @font-hex ( 0-F ) [ 007c 8282 8282 827c 0030 1010 1010 1010 diff --git a/src/emulator.c b/src/emulator.c index dcda3c1..147a6f9 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -16,6 +16,7 @@ WITH REGARD TO THIS SOFTWARE. #include "uxn.h" #include "ppu.h" #include "apu.h" +#include "mpu.h" static SDL_AudioDeviceID audio_id; static SDL_Window *gWindow; @@ -23,7 +24,8 @@ static SDL_Renderer *gRenderer; static SDL_Texture *gTexture; static Ppu ppu; static Apu apu[POLYPHONY]; -static Device *devscreen, *devmouse, *devctrl; +static Mpu mpu; +static Device *devscreen, *devmouse, *devctrl, *devmidi; Uint8 zoom = 0, debug = 0, reqdraw = 0; @@ -102,6 +104,8 @@ init(void) SDL_AudioSpec as; if(!initppu(&ppu, 48, 32, 16)) return error("PPU", "Init failure"); + if(!initmpu(&mpu, 1)) + return error("MPU", "Init failure"); if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) return error("Init", SDL_GetError()); gWindow = SDL_CreateWindow("Uxn", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, ppu.width * zoom, ppu.height * zoom, SDL_WINDOW_SHOWN); @@ -288,6 +292,14 @@ datetime_talk(Device *d, Uint8 b0, Uint8 w) (void)w; } +void +midi_talk(Device *d, Uint8 b0, Uint8 w) +{ + (void)d; + (void)b0; + (void)w; +} + void nil_talk(Device *d, Uint8 b0, Uint8 w) { @@ -304,6 +316,7 @@ start(Uxn *u) evaluxn(u, 0x0100); redraw(ppu.output, u); while(1) { + int i; SDL_Event event; double elapsed, start = SDL_GetPerformanceCounter(); while(SDL_PollEvent(&event) != 0) { @@ -333,6 +346,11 @@ start(Uxn *u) break; } } + listenmpu(&mpu); + for(i = 0; i < mpu.queue; ++i) { + mempoke16(devmidi->dat, 2, mpu.events[i].message); + evaluxn(u, mempeek16(devmidi->dat, 0)); + } evaluxn(u, mempeek16(devscreen->dat, 0)); if(reqdraw) redraw(ppu.output, u); @@ -366,7 +384,7 @@ main(int argc, char **argv) devmouse = portuxn(&u, 0x6, "mouse", nil_talk); portuxn(&u, 0x7, "file", file_talk); portuxn(&u, 0x8, "---", nil_talk); - portuxn(&u, 0x9, "midi", nil_talk); + devmidi = portuxn(&u, 0x9, "midi", midi_talk); portuxn(&u, 0xa, "datetime", datetime_talk); portuxn(&u, 0xb, "---", nil_talk); portuxn(&u, 0xc, "---", nil_talk); diff --git a/src/mpu.c b/src/mpu.c new file mode 100644 index 0000000..25cfcd6 --- /dev/null +++ b/src/mpu.c @@ -0,0 +1,33 @@ +/* +Copyright (c) 2021 Devine Lu Linvega +Copyright (c) 2021 Andrew Alderwick + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE. +*/ + +#include "mpu.h" + +int +initmpu(Mpu *m, Uint8 device) +{ + int i; + Pm_Initialize(); + for(i = 0; i < Pm_CountDevices(); ++i) + printf("Device #%d -> %s%s\n", + i, + Pm_GetDeviceInfo(i)->name, + i == device ? "[x]" : "[ ]"); + Pm_OpenInput(&m->midi, device, NULL, 128, 0, NULL); + return 1; +} + +void +listenmpu(Mpu *m) +{ + m->queue = Pm_Read(m->midi, m->events, 32); +} diff --git a/src/mpu.h b/src/mpu.h new file mode 100644 index 0000000..9b1b703 --- /dev/null +++ b/src/mpu.h @@ -0,0 +1,26 @@ +#include +#include +#include + +/* +Copyright (c) 2021 Devine Lu Linvega +Copyright (c) 2021 Andrew Alderwick + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE. +*/ + +typedef unsigned char Uint8; + +typedef struct { + Uint8 queue; + PmStream *midi; + PmEvent events[32]; +} Mpu; + +int initmpu(Mpu *m, Uint8 device); +void listenmpu(Mpu *m);