diff options
author | Alec Murphy <alec@checksum.fail> | 2017-07-09 17:44:53 -0400 |
---|---|---|
committer | Alec Murphy <alec@checksum.fail> | 2017-07-09 17:44:53 -0400 |
commit | 24690096e69fdaeb0f98ff810a636b99d860a5ea (patch) | |
tree | 3265df3fae00c0d95ae6b5e1920e6805f44283d4 | |
parent | 750376b125d3e43b1e995596707d94e68ed4c7a7 (diff) |
Add SNES gamepad support, adjust PC speaker sound settings
-rwxr-xr-x | GamePad.HC | 16 | ||||
-rwxr-xr-x | Keyboard.HC | 119 | ||||
-rw-r--r-- | Load.HC | 354 | ||||
-rw-r--r-- | README.md | 30 | ||||
-rw-r--r-- | Settings.HC | 11 | ||||
-rwxr-xr-x | Sound.HC | 48 |
6 files changed, 412 insertions, 166 deletions
diff --git a/GamePad.HC b/GamePad.HC new file mode 100755 index 0000000..eb3001a --- /dev/null +++ b/GamePad.HC @@ -0,0 +1,16 @@ +U0 updateGamePad() +{ + OutU8(GP_TX_PORT,GP_SNES_POWER|GP_SNES_CLOCK|GP_SNES_LATCH); + Sleep(GP_SNES_DELAY*2); + OutU8(GP_TX_PORT,GP_SNES_POWER|GP_SNES_CLOCK); + gp_ctr=0; + while (gp_ctr<12) + { + Sleep(GP_SNES_DELAY); + OutU8(GP_TX_PORT,GP_SNES_POWER); + gp_data[gp_ctr]=InU8(GP_RX_PORT)^0x7F; + Sleep(GP_SNES_DELAY); + OutU8(GP_TX_PORT,GP_SNES_POWER|GP_SNES_CLOCK); + gp_ctr++; + }; +}; diff --git a/Keyboard.HC b/Keyboard.HC new file mode 100755 index 0000000..2d3d80f --- /dev/null +++ b/Keyboard.HC @@ -0,0 +1,119 @@ +U0 updateKeyboard() +{ + switch(sc) + { + + // Reset (kbd only) + case 0x13: + kReset=0; + break; + case 0x13 + 0x80: + if(!kReset) { + kReset=1; + StrCpy(DisplayMsg,"Reset"); + DisplayMsgTicks=1; + initEmulator; + }; + break; + + // Set Display Size (kbd only) + case 0x02 + 0x80: + LCDScale=1; + SetLCDScale; + break; + case 0x03 + 0x80: + LCDScale=2; + SetLCDScale; + break; + case 0x04 + 0x80: + LCDScale=3; + SetLCDScale; + break; + + // Exit + case 0x01: + gp_data[10]=0x40; + break; + // LoadState + case 0x06: + gp_data[11]=0x40; + break; + // SaveState + case 0x08: + gp_data[9]=0x40; + break; + // ToggleSound + case 0x10: + gp_data[8]=0x40; + break; + // Exit(up) + case 0x01 + 0x80: + gp_data[10]=0x00; + break; + // LoadState(up) + case 0x06 + 0x80: + gp_data[11]=0x00; + break; + // SaveState(up) + case 0x08 + 0x80: + gp_data[9]=0x00; + break; + // ToggleSound(up) + case 0x10 + 0x80: + gp_data[8]=0x00; + break; + + case 0x4D: + gp_data[7]=0x40; + break; + case 0x4B: + gp_data[6]=0x40; + break; + case 0x48: + gp_data[4]=0x40; + break; + case 0x50: + gp_data[5]=0x40; + break; + case 0x1F: + gp_data[0]=0x40; + break; + case 0x1E: + gp_data[1]=0x40; + break; + case 0x2A: + gp_data[2]=0x40; + break; + case 0x1C: + gp_data[3]=0x40; + break; + + case 0x4D + 0x80: + gp_data[7]=0x00; + break; + case 0x4B + 0x80: + gp_data[6]=0x00; + break; + case 0x48 + 0x80: + gp_data[4]=0x00; + break; + case 0x50 + 0x80: + gp_data[5]=0x00; + break; + case 0x1F + 0x80: + gp_data[0]=0x00; + break; + case 0x1E + 0x80: + gp_data[1]=0x00; + break; + case 0x2A + 0x80: + gp_data[2]=0x00; + break; + case 0x1C + 0x80: + gp_data[3]=0x00; + break; + + default: + break; + }; +}; @@ -2,6 +2,19 @@ StrCpy(Fs->task_name,""); StrCpy(Fs->task_title,""); // Settings #include "Settings"; + +#define GP_TX_PORT 0x0378 +#define GP_RX_PORT 0x0379 + +#define GP_SNES_DELAY 0 + +#define GP_SNES_POWER 0xFC +#define GP_SNES_CLOCK 0x01 +#define GP_SNES_LATCH 0x02 + +U8 gp_data[16]; +I64 gp_ctr; + I64 keyCtr=0; I64 sc=0; I64 ROMSize=0; @@ -10,15 +23,17 @@ I64 obp03,obp02,obp01,obp00; I64 obp13,obp12,obp11,obp10; I64 jp_state[8]; +I64 exitApp=0; + +I64 tdCtr=0; I64 apuCtr=0; I64 apuToggle=1; -I64 kAPUChan1=0; -I64 kAPUChan2=0; -I64 kAPUChan3=0; I64 kLoad=0; I64 kReset=0; I64 kSave=0; +I64 kSnd=0; +I64 soundMode=2; I64 DisplayMsgTicks=0; U8 DisplayMsg[32]; @@ -921,6 +936,9 @@ U0 initEmulator() registersHL = 0x014D; } +#include "GamePad"; +#include "Keyboard"; + U0 saveState() { U8 *statebuf=CAlloc(2048*1024); @@ -1018,6 +1036,9 @@ U0 runInterrupt() } testbit = 1 << ++bitShift; } + + tdCtr=0; + while(tdCtr<frameDelay) { tdCtr++; }; } // #include "LCD"; @@ -1027,7 +1048,7 @@ U0 updateCore() if (apuToggle==1) { apuCtr++; - if(apuCtr>1000) + if(apuCtr>2000) { memory[0xFEED]++; if(memory[0xFEED]>1) { memory[0xFEED]=0; }; @@ -1058,7 +1079,15 @@ U0 updateCore() //Emulator Timing (Timed against audio for optimization): emulatorTicks += audioTicks; if (emulatorTicks >= machineCyclesPerLoop) { - sc=InU8(0x60); + if (useGamePad==TRUE) + { + updateGamePad; + }; + if (useKeyboard==TRUE) + { + sc=InU8(0x60); + updateKeyboard; + }; //LCD off takes at least 2 frames. if (drewBlank == 0) { @@ -1105,7 +1134,7 @@ U0 executeIteration() //Iterate the interpreter loop: I64 op = 0; - while (sc!=1) { + while (exitApp!=1) { //Fetch the current opcode. op = memoryRead(programCounter); if (!skipPCIncrement) { @@ -1132,163 +1161,173 @@ U0 executeIteration() } //Timing: updateCore; - //Keyboard - - switch(sc) { - case 0x10: - kAPUChan1=0; - break; - case 0x10 + 0x80: - if(!kAPUChan1) { - kAPUChan1=1; - apuToggle=0; - memory[0xFEED]=0; - StrCpy(DisplayMsg,"APU Ch 01"); - DisplayMsgTicks=1; - }; - break; - - case 0x11: - kAPUChan2=0; - break; - case 0x11 + 0x80: - if(!kAPUChan2) { - kAPUChan2=1; - apuToggle=0; - memory[0xFEED]=1; - StrCpy(DisplayMsg,"APU Ch 02"); - DisplayMsgTicks=1; - }; - break; + if (gp_data[7]==0) + { + jp_state[0]=FALSE; + } + else + { + jp_state[0]=TRUE; + }; + if (gp_data[6]==0) + { + jp_state[1]=FALSE; + } + else + { + jp_state[1]=TRUE; + }; + if (gp_data[4]==0) + { + jp_state[2]=FALSE; + } + else + { + jp_state[2]=TRUE; + }; + if (gp_data[5]==0) + { + jp_state[3]=FALSE; + } + else + { + jp_state[3]=TRUE; + }; - case 0x12: - kAPUChan3=0; - break; - case 0x12 + 0x80: - if(!kAPUChan3) { - kAPUChan3=1; - apuToggle=1; - StrCpy(DisplayMsg,"APU Ch Auto"); - DisplayMsgTicks=1; - }; - break; + if (gp_data[0]==0) + { + jp_state[4]=FALSE; + } + else + { + jp_state[4]=TRUE; + }; + if (gp_data[1]==0) + { + jp_state[5]=FALSE; + } + else + { + jp_state[5]=TRUE; + }; + if (gp_data[2]==0) + { + jp_state[6]=FALSE; + } + else + { + jp_state[6]=TRUE; + }; + if (gp_data[3]==0) + { + jp_state[7]=FALSE; + } + else + { + jp_state[7]=TRUE; + }; - case 0x13: - kReset=0; - break; - case 0x13 + 0x80: - if(!kReset) { - kReset=1; - StrCpy(DisplayMsg,"Reset"); - DisplayMsgTicks=1; - initEmulator; - }; - break; + for (keyCtr=0;keyCtr<8;keyCtr++) { + joyPadEvent(keyCtr,jp_state[keyCtr]); + }; - case 0x08: - kSave=0; - break; - case 0x08 + 0x80: - if(!kSave) { - kSave=1; - StrCpy(DisplayMsg,"State Saved"); - DisplayMsgTicks=1; - saveState; - }; - break; + Sleep(0); + + if (gp_data[10]!=0) + { + exitApp=1; + }; - case 0x06: - kLoad=0; - break; - case 0x06 + 0x80: - if(!kLoad) { - kLoad=1; - if (FileFind(StateFile)) { - StrCpy(DisplayMsg,"State Loaded"); - DisplayMsgTicks=1; - initEmulator; - loadState; - } else { - StrCpy(DisplayMsg,"No State Found"); - DisplayMsgTicks=1; - }; - }; - break; + if (gp_data[11]!=0) + { + if(!kLoad) + { + kLoad=1; + if (FileFind(StateFile)) { + StrCpy(DisplayMsg,"State Loaded"); + DisplayMsgTicks=1; + initEmulator; + loadState; + } else { + StrCpy(DisplayMsg,"No State Found"); + DisplayMsgTicks=1; + }; + }; + } + else + { + kLoad=0; + }; - case 0x02 + 0x80: - LCDScale=1; - SetLCDScale; - break; - case 0x03 + 0x80: - LCDScale=2; - SetLCDScale; - break; - case 0x04 + 0x80: - LCDScale=3; - SetLCDScale; - break; - case 0x4D: - joyPadState(0,TRUE); - joyPadState(1,FALSE); - break; - case 0x4B: - joyPadState(1,TRUE); - joyPadState(0,FALSE); - break; - case 0x48: - joyPadState(2,TRUE); - joyPadState(3,FALSE); - break; - case 0x50: - joyPadState(3,TRUE); - joyPadState(2,FALSE); - break; - case 0x1F: - joyPadState(4,TRUE); - break; - case 0x1E: - joyPadState(5,TRUE); - break; - case 0x2A: - joyPadState(6,TRUE); - break; - case 0x1C: - joyPadState(7,TRUE); - break; - case 0x4D + 0x80: - joyPadState(0,FALSE); - break; - case 0x4B + 0x80: - joyPadState(1,FALSE); - break; - case 0x48 + 0x80: - joyPadState(2,FALSE); - break; - case 0x50 + 0x80: - joyPadState(3,FALSE); - break; - case 0x1F + 0x80: - joyPadState(4,FALSE); - break; - case 0x1E + 0x80: - joyPadState(5,FALSE); - break; - case 0x2A + 0x80: - joyPadState(6,FALSE); - break; - case 0x1C + 0x80: - joyPadState(7,FALSE); - break; - default: - break; + if (gp_data[9]!=0) + { + if(!kSave) { + kSave=1; + StrCpy(DisplayMsg,"State Saved"); + DisplayMsgTicks=1; + saveState; + }; + } + else + { + kSave=0; }; - for (keyCtr=0;keyCtr<8;keyCtr++) { - joyPadEvent(keyCtr,jp_state[keyCtr]); + if (gp_data[8]!=0) + { + if(!kSnd) { + kSnd=1; + soundMode++; + if (soundMode>3) + { + soundMode=0; + }; + + if (soundMode==0) + { + StrCpy(DisplayMsg,"Snd Ch01"); + }; + if (soundMode==1) + { + StrCpy(DisplayMsg,"Snd Ch02"); + }; + if (soundMode==2) + { + StrCpy(DisplayMsg,"Snd Auto"); + }; + if (soundMode==3) + { + StrCpy(DisplayMsg,"Snd Off"); + }; + + DisplayMsgTicks=1; + }; + } + else + { + kSnd=0; }; - Sleep(0); + if (soundMode==0) + { + apuToggle=0; + memory[0xFEED]=0; + }; + if (soundMode==1) + { + apuToggle=0; + memory[0xFEED]=1; + }; + if (soundMode==2) + { + apuToggle=1; + }; + if (soundMode==3) + { + memory[0xFEED]=128; + apuToggle=0; + }; }; } @@ -1348,6 +1387,15 @@ U0 start() for (keyCtr=0;keyCtr<8;keyCtr++) { jp_state[keyCtr]=0; }; + + gp_ctr=0; + while(gp_ctr<12) + { + gp_data[gp_ctr]=0; + gp_ctr++; + }; + gp_ctr=0; + SettingsPush; DocClear; DCFill(lcd,15); @@ -9,7 +9,29 @@ Z80 Core and timing routines ported from [PHP Terminal GameBoy Emulator](https:/ Put ROM files in `Roms` folder, and `#include "Run";` -# Controls +You can connect a SNES gamepad w/ adapter to the parallel port. Enable gamepad in `Settings.HC` with `useGamePad=TRUE;` + +# Gamepad Controls + +D-PAD: D-PAD + +B: `Y` + +A: `B` + +Select: `SELECT` + +Start: `START` + +Exit: `L` + +Load State: `R` + +Save State: `X` + +Toggle Sound: `A` + +# Keyboard Controls D-PAD: `ARROW KEYS` @@ -31,9 +53,5 @@ Load State: `5` Save State: `7` -Sound Channel 1: `Q` - -Sound Channel 2: `W` - -Sound Channel Auto Toggle: `E` +Toggle Sound: `Q` diff --git a/Settings.HC b/Settings.HC index a696eec..6e77b53 100644 --- a/Settings.HC +++ b/Settings.HC @@ -3,12 +3,13 @@ I64 audioGranularity = 20; //Auto Frame Skip I64 autoFrameskip = TRUE; -//Colorize GB mode? **No CGB support** -I64 colorize = FALSE; +I64 frameDelay = 120; -//Keyboard button map. **Not implemented yet** -//Order: Right, Left, Up, Down, A, B, Select, Start -I64 keyboardButtonMap[8] = {'d', 'a', 'w', 's', ',', '.', 'n', 'm'}; +// Sound modes: 0 (Ch 01), 1 (Ch 02), 2 (Auto), 3 (Off) +I64 soundMode=2; + +I64 useKeyboard=TRUE; +I64 useGamePad=TRUE; I64 LCDScale=3; @@ -1,5 +1,11 @@ U0 GBSoundTask(U8 *regs) { + + I64 frmCtr=0; + I64 restCtrA=0; + I64 restCtrB=0; + I64 restA=0; + I64 restB=0; I64 div; I64 freq; I64 x; @@ -9,9 +15,9 @@ U0 GBSoundTask(U8 *regs) while (TRUE) { - if(memory[0xFEED]==0) { + restA=1; if (memory[0xFF12]>0b10000) { x = memory[0xFF13]; @@ -28,13 +34,29 @@ U0 GBSoundTask(U8 *regs) OutU8(0x42, div>>8); OutU8(0x61,3|InU8(0x61)); prevA=x; + restA=0; + restCtrA=0; }; } else { }; + + if (restA==1) + { + restCtrA++; + if (restCtrA>30000) + { + SndRst; + SndRst; + restCtrA=0; + //prevB=0; + }; + }; + }; if(memory[0xFEED]==1) { + restB=1; if (memory[0xFF17]>0b10000) { x = memory[0xFF18]; @@ -48,11 +70,33 @@ U0 GBSoundTask(U8 *regs) OutU8(0x42, div>>8); OutU8(0x61,3|InU8(0x61)); prevB=x; + restB=0; + restCtrB=0; }; } else { }; + + if (restB==1) + { + restCtrB++; + if (restCtrB>30000) + { + SndRst; + SndRst; + restCtrB=0; + //prevA=0; + }; + }; + }; - Sleep(2); + if(memory[0xFEED]==128) + { + SndRst; + }; + + + frmCtr=0; + while(frmCtr<30000){frmCtr++;}; }; } |