├── .gitignore ├── Makefile ├── README.md ├── include ├── browser.h └── menu.h ├── install.sh ├── source ├── EMULIB │ ├── AY8910.c │ ├── AY8910.h │ ├── ConsoleMux.h │ ├── EMULib.c │ ├── EMULib.h │ ├── FDIDisk.c │ ├── FDIDisk.h │ ├── Floppy.c │ ├── Floppy.h │ ├── Hunt.c │ ├── Hunt.h │ ├── I8255.c │ ├── I8255.h │ ├── IPS.c │ ├── IPS.h │ ├── Image.c │ ├── ImageMux.h │ ├── MCF.h │ ├── MIDIFreq.h │ ├── Orbis │ │ ├── LibOrbis.c │ │ ├── LibOrbis.h │ │ └── SndOrbis.c │ ├── Record.c │ ├── Record.h │ ├── SCC.c │ ├── SCC.h │ ├── SHA1.c │ ├── SHA1.h │ ├── Sound.c │ ├── Sound.h │ ├── WD1793.c │ ├── WD1793.h │ ├── YM2413.c │ └── YM2413.h ├── Z80 │ ├── Codes.h │ ├── CodesCB.h │ ├── CodesED.h │ ├── CodesXCB.h │ ├── CodesXX.h │ ├── Tables.h │ ├── Z80.c │ └── Z80.h ├── browser.c ├── credits.c ├── fMSX │ ├── Boot.h │ ├── Common.h │ ├── CommonMux.h │ ├── Help.h │ ├── I8251.c │ ├── I8251.h │ ├── MSX.c │ ├── MSX.h │ ├── Orbis │ │ ├── CARTS.SHA │ │ └── Orbis.c │ ├── Patch.c │ ├── State.h │ ├── V9938.c │ ├── V9938.h │ ├── Wide.h │ ├── fMSX.c │ ├── msxaudio │ │ ├── fmopl.c │ │ ├── fmopl.h │ │ ├── readme.txt │ │ ├── ymdeltat.c │ │ └── ymdeltat.h │ └── msxmusic │ │ ├── 2413tone.h │ │ ├── emu2149.c │ │ ├── emu2149.h │ │ ├── emu2212.c │ │ ├── emu2212.h │ │ ├── emu2413.c │ │ ├── emu2413.h │ │ ├── emutypes.h │ │ └── vrc7tone.h ├── main.c └── menu.c └── system ├── CARTS.SHA ├── browser.png ├── credits.png ├── file_icon.png ├── folder_icon.png └── settings.png /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | *.elf 3 | *.self 4 | *.pkg 5 | *.o 6 | *.a 7 | *.d 8 | .DS_Store 9 | ._* 10 | 11 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ifndef Ps4Sdk 2 | ifdef ps4sdk 3 | Ps4Sdk := $(ps4sdk) 4 | endif 5 | ifdef PS4SDK 6 | Ps4Sdk := $(PS4SDK) 7 | endif 8 | ifndef Ps4Sdk 9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set) 10 | endif 11 | endif 12 | 13 | keepelf = True 14 | target ?= ps4_elf 15 | TargetFile=msxorbis.elf 16 | #need to add this flags 17 | #-Wl,-T script.ld 18 | 19 | ################################### 20 | 21 | Libraries := -ldebugnet -lps4link -lelfloader -lorbisKeyboard -lorbis2d -lpng -lz -lorbisPad -lorbisAudio -lmod -lorbisFileBrowser -lorbisXbmFont -lSceNet_stub -lSceAudioOut_stub -lSceVideoOut_stub -lSceSystemService_stub -lSceUserService_stub -lSceGnmDriver_stub -lScePad_stub -lSceLibcInternal_stub -lSceIme_stub -lSceSysmodule_stub 22 | 23 | include $(Ps4Sdk)/make/ps4sdk.mk 24 | 25 | CompilerFlags += -DFMSX -DALTSOUND -DORBIS -DLSB_FIRST -DNO_WAVE_INTERPOLATION -DBPP32 -DBPS16 -DNARROW 26 | 27 | IncludePath += -I./source/EMULIB -I./source/EMULIB/Orbis -I./source/Z80 -I./source/fMSX -I./source/fMSX/Orbis -I./source/fMSX/msxaudio -I./source/fMSX/msxmusic 28 | 29 | -------------------------------------------------------------------------------- /include/browser.h: -------------------------------------------------------------------------------- 1 | #ifndef _BROWSER_H_ 2 | #define _BROWSER_H_ 3 | 4 | #define BROWSERBACKGROUND_FILE_PATH "host0:system/browser.png" 5 | #define FILE_ICON_PATH "host0:system/file_icon.png" 6 | #define FOLDER_ICON_PATH "host0:system/folder_icon.png" 7 | 8 | 9 | void showBrowser(); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /include/menu.h: -------------------------------------------------------------------------------- 1 | #ifndef _MENU_H_ 2 | #define _MENU_H_ 3 | 4 | #include 5 | 6 | #define RED_COLOR 0x80ff0000 7 | #define YELLOW_COLOR 0xFF24FFBD 8 | #define SETTINGS_FILE_PATH "host0:system/settings.png" 9 | #define CREDITS_FILE_PATH "host0:system/credits.png" 10 | 11 | #define ICON_ABOUT_MASK_X 499 12 | #define ICON_ABOUT_MASK_Y 220 13 | #define ICON_ABOUT_MASK_W 305 14 | #define ICON_ABOUT_MASK_H 167 15 | 16 | #define ICON_MSX1_MASK_X 501 17 | #define ICON_MSX1_MASK_Y 388 18 | #define ICON_MSX1_MASK_W 56 19 | #define ICON_MSX1_MASK_H 23 20 | 21 | #define ICON_MSX2_MASK_X 571 22 | #define ICON_MSX2_MASK_Y 388 23 | #define ICON_MSX2_MASK_W 69 24 | #define ICON_MSX2_MASK_H 23 25 | 26 | #define ICON_MSX2PLUS_MASK_X 650 27 | #define ICON_MSX2PLUS_MASK_Y 388 28 | #define ICON_MSX2PLUS_MASK_W 84 29 | #define ICON_MSX2PLUS_MASK_H 23 30 | 31 | #define ICON_VIDEO_NTSC_MASK_X 653 32 | #define ICON_VIDEO_NTSC_MASK_Y 421 33 | #define ICON_VIDEO_NTSC_MASK_W 44 34 | #define ICON_VIDEO_NTSC_MASK_H 16 35 | 36 | #define ICON_VIDEO_PAL_MASK_X 606 37 | #define ICON_VIDEO_PAL_MASK_Y 421 38 | #define ICON_VIDEO_PAL_MASK_W 34 39 | #define ICON_VIDEO_PAL_MASK_H 16 40 | 41 | #define ICON_RESET_MASK_X 612 42 | #define ICON_RESET_MASK_Y 447 43 | #define ICON_RESET_MASK_W 66 44 | #define ICON_RESET_MASK_H 71 45 | 46 | 47 | 48 | 49 | 50 | enum MENU_LEVEL { 51 | MENU_ABOUT, 52 | MENU_MSX1, 53 | MENU_MSX2, 54 | MENU_MSX2PLUS, 55 | MENU_VIDEO_NTSC, 56 | MENU_VIDEO_PAL, 57 | MENU_RESET, 58 | MENU_MEGAROM1, 59 | MENU_MEGAROM2, 60 | MENU_DISKA, 61 | MENU_DISKB, 62 | MENU_TAPE, 63 | }; 64 | 65 | enum MENU_SELECT_STATUS { 66 | MENU_NOT_SELECTED, 67 | MENU_ABOUT_SELECTED, 68 | MENU_MSX1_SELECTED, 69 | MENU_MSX2_SELECTED, 70 | MENU_MSX2PLUS_SELECTED, 71 | MENU_VIDEO_NTSC_SELECTED, 72 | MENU_VIDEO_PAL_SELECTED, 73 | MENU_RESET_SELECTED, 74 | MENU_MEGAROM1_SELECTED, 75 | MENU_MEGAROM2_SELECTED, 76 | MENU_DISKA_SELECTED, 77 | MENU_DISKB_SELECTED, 78 | MENU_TAPE_SELECTED, 79 | }; 80 | 81 | enum MENU_CONTEXT_STATUS{ 82 | MENU_CONTEXT_CLOSED, 83 | MENU_CONTEXT_CLOSING, 84 | MENU_CONTEXT_OPENED, 85 | MENU_CONTEXT_OPENING, 86 | }; 87 | int menuGetStatus(); 88 | int menuGetLevel(); 89 | int menuGetContextStatus(); 90 | float menuGetContextHeight(); 91 | void menuSetStatus(int status); 92 | void menuSetLevel(int level); 93 | void menuSetContextStatus(int status); 94 | void menuSetContextHeight(float height); 95 | //DRAW MENUS TEXTURES 96 | void menuDrawIcons(); 97 | void menuDrawIconsMaskSelect(); 98 | 99 | //PUBLIC 100 | int menuInit(); 101 | void menuFinish(); 102 | void menuLevelUp(); 103 | void menuLevelDown(); 104 | void menuLevelLeft(); 105 | void menuLevelRight(); 106 | void menuDraw(); 107 | void menuStatusChange(); 108 | void showCredits(); 109 | void showSettings(); 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | cp bin/msxorbis.elf ../../../repositorios/ps4sh/bin/msxorbis.elf 2 | -------------------------------------------------------------------------------- /source/EMULIB/AY8910.h: -------------------------------------------------------------------------------- 1 | /** EMULib Emulation Library *********************************/ 2 | /** **/ 3 | /** AY8910.h **/ 4 | /** **/ 5 | /** This file contains emulation for the AY8910 sound chip **/ 6 | /** produced by General Instruments, Yamaha, etc. See **/ 7 | /** AY8910.c for the actual code. **/ 8 | /** **/ 9 | /** Copyright (C) Marat Fayzullin 1996-2016 **/ 10 | /** You are not allowed to distribute this software **/ 11 | /** commercially. Please, notify me, if you make any **/ 12 | /** changes to this file. **/ 13 | /*************************************************************/ 14 | #ifndef AY8910_H 15 | #define AY8910_H 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | #define AY8910_CHANNELS 6 /* 3 melodic + 3 noise chanls */ 21 | 22 | #define AY8910_ASYNC 0 /* Asynchronous emulation */ 23 | #define AY8910_SYNC 1 /* Synchronous emulation */ 24 | #define AY8910_FLUSH 2 /* Flush buffers only */ 25 | #define AY8910_DRUMS 0x80 /* Hit drums for noise chnls */ 26 | 27 | #ifndef BYTE_TYPE_DEFINED 28 | #define BYTE_TYPE_DEFINED 29 | typedef unsigned char byte; 30 | #endif 31 | 32 | /** AY8910 ***************************************************/ 33 | /** This data structure stores AY8910 state. **/ 34 | /*************************************************************/ 35 | typedef struct 36 | { 37 | byte R[16]; /* PSG registers contents */ 38 | int Freq[AY8910_CHANNELS]; /* Frequencies (0 for off) */ 39 | int Volume[AY8910_CHANNELS]; /* Volumes (0..255) */ 40 | int Clock; /* Base clock rate (Fin/16) */ 41 | int First; /* First used Sound() channel */ 42 | byte Changed; /* Bitmap of changed channels */ 43 | byte Sync; /* AY8910_SYNC/AY8910_ASYNC */ 44 | byte Latch; /* Latch for the register num */ 45 | int EPeriod; /* Envelope step in microsecs */ 46 | int ECount; /* Envelope step counter */ 47 | int EPhase; /* Envelope phase */ 48 | } AY8910; 49 | 50 | /** Reset8910() **********************************************/ 51 | /** Reset the sound chip and use sound channels from the **/ 52 | /** one given in First. **/ 53 | /*************************************************************/ 54 | void Reset8910(register AY8910 *D,int ClockHz,int First); 55 | 56 | /** Write8910() **********************************************/ 57 | /** Call this function to output a value V into the sound **/ 58 | /** chip. **/ 59 | /*************************************************************/ 60 | void Write8910(register AY8910 *D,register byte R,register byte V); 61 | 62 | /** WrCtrl8910() *********************************************/ 63 | /** Write a value V to the PSG Control Port. **/ 64 | /*************************************************************/ 65 | void WrCtrl8910(AY8910 *D,byte V); 66 | 67 | /** WrData8910() *********************************************/ 68 | /** Write a value V to the PSG Data Port. **/ 69 | /*************************************************************/ 70 | void WrData8910(AY8910 *D,byte V); 71 | 72 | /** RdData8910() *********************************************/ 73 | /** Read a value from the PSG Data Port. **/ 74 | /*************************************************************/ 75 | byte RdData8910(AY8910 *D); 76 | 77 | /** Sync8910() ***********************************************/ 78 | /** Flush all accumulated changes by issuing Sound() calls **/ 79 | /** and set the synchronization on/off. The second argument **/ 80 | /** should be AY8910_SYNC/AY8910_ASYNC to set/reset sync, **/ 81 | /** or AY8910_FLUSH to leave sync mode as it is. To emulate **/ 82 | /** noise channels with MIDI drums, OR second argument with **/ 83 | /** AY8910_DRUMS. **/ 84 | /*************************************************************/ 85 | void Sync8910(register AY8910 *D,register byte Sync); 86 | 87 | /** Loop8910() ***********************************************/ 88 | /** Call this function periodically to update volume **/ 89 | /** envelopes. Use uSec to pass the time since the last **/ 90 | /** call of Loop8910() in microseconds. **/ 91 | /*************************************************************/ 92 | void Loop8910(register AY8910 *D,int uSec); 93 | 94 | #ifdef __cplusplus 95 | } 96 | #endif 97 | #endif /* AY8910_H */ 98 | -------------------------------------------------------------------------------- /source/EMULIB/FDIDisk.h: -------------------------------------------------------------------------------- 1 | /** EMULib Emulation Library *********************************/ 2 | /** **/ 3 | /** FDIDisk.h **/ 4 | /** **/ 5 | /** This file declares routines to load, save, and access **/ 6 | /** disk images in various formats. The internal format is **/ 7 | /** always .FDI. See FDIDisk.c for the actual code. **/ 8 | /** **/ 9 | /** Copyright (C) Marat Fayzullin 2007-2016 **/ 10 | /** You are not allowed to distribute this software **/ 11 | /** commercially. Please, notify me, if you make any **/ 12 | /** changes to this file. **/ 13 | /*************************************************************/ 14 | #ifndef FDIDISK_H 15 | #define FDIDISK_H 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | #define FMT_AUTO 0 21 | #define FMT_IMG 1 22 | #define FMT_MGT 2 23 | #define FMT_TRD 3 24 | #define FMT_FDI 4 25 | #define FMT_SCL 5 26 | #define FMT_HOBETA 6 27 | #define FMT_DSK 7 28 | #define FMT_CPCDSK 8 29 | #define FMT_SF7000 9 30 | 31 | #define DataFDI(D) ((D)->Data+(D)->Data[10]+((int)((D)->Data[11])<<8)) 32 | 33 | #ifndef BYTE_TYPE_DEFINED 34 | #define BYTE_TYPE_DEFINED 35 | typedef unsigned char byte; 36 | #endif 37 | 38 | /** FDIDisk **************************************************/ 39 | /** This structure contains all disk image information and **/ 40 | /** also the result of the last SeekFDI() call. **/ 41 | /*************************************************************/ 42 | typedef struct 43 | { 44 | byte Format; /* Original disk format (FMT_*) */ 45 | int Sides; /* Sides per disk */ 46 | int Tracks; /* Tracks per side */ 47 | int Sectors; /* Sectors per track */ 48 | int SecSize; /* Bytes per sector */ 49 | 50 | byte *Data; /* Disk data */ 51 | int DataSize; /* Disk data size */ 52 | 53 | byte Header[6]; /* Current header, result of SeekFDI() */ 54 | byte Verbose; /* 1: Print debugging messages */ 55 | } FDIDisk; 56 | 57 | /** InitFDI() ************************************************/ 58 | /** Clear all data structure fields. **/ 59 | /*************************************************************/ 60 | void InitFDI(FDIDisk *D); 61 | 62 | /** EjectFDI() ***********************************************/ 63 | /** Eject disk image. Free all allocated memory. **/ 64 | /*************************************************************/ 65 | void EjectFDI(FDIDisk *D); 66 | 67 | /** NewFDI() *************************************************/ 68 | /** Allocate memory and create new .FDI disk image of given **/ 69 | /** dimensions. Returns disk data pointer on success, 0 on **/ 70 | /** failure. **/ 71 | /*************************************************************/ 72 | byte *NewFDI(FDIDisk *D,int Sides,int Tracks,int Sectors,int SecSize); 73 | 74 | /** LoadFDI() ************************************************/ 75 | /** Load a disk image from a given file, in a given format **/ 76 | /** (see FMT_* #defines). Guess format from the file name **/ 77 | /** when Format=FMT_AUTO. Returns format ID on success or **/ 78 | /** 0 on failure. When FileName=0, ejects the disk freeing **/ 79 | /** memory and returns 0. **/ 80 | /*************************************************************/ 81 | int LoadFDI(FDIDisk *D,const char *FileName,int Format); 82 | 83 | /** SaveFDI() ************************************************/ 84 | /** Save a disk image to a given file, in a given format **/ 85 | /** (see FMT_* #defines). Use the original format when **/ 86 | /** when Format=FMT_AUTO. Returns format ID on success or **/ 87 | /** 0 on failure. **/ 88 | /*************************************************************/ 89 | int SaveFDI(FDIDisk *D,const char *FileName,int Format); 90 | 91 | /** SeekFDI() ************************************************/ 92 | /** Seek to given side/track/sector. Returns sector address **/ 93 | /** on success or 0 on failure. **/ 94 | /*************************************************************/ 95 | byte *SeekFDI(FDIDisk *D,int Side,int Track,int SideID,int TrackID,int SectorID); 96 | 97 | #ifdef __cplusplus 98 | } 99 | #endif 100 | #endif /* FDIDISK_H */ 101 | -------------------------------------------------------------------------------- /source/EMULIB/Floppy.h: -------------------------------------------------------------------------------- 1 | /** EMULib Emulation Library *********************************/ 2 | /** **/ 3 | /** Floppy.h **/ 4 | /** **/ 5 | /** This file declares functions to operate on 720kB **/ 6 | /** floppy disk images. See Floppy.c for implementation. **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 2004-2016 **/ 9 | /** You are not allowed to distribute this software **/ 10 | /** commercially. Please, notify me, if you make any **/ 11 | /** changes to this file. **/ 12 | /*************************************************************/ 13 | #ifndef FLOPPY_H 14 | #define FLOPPY_H 15 | 16 | #define DSK_SIDS_PER_DISK 2 17 | #define DSK_TRKS_PER_SIDE 80 18 | #define DSK_SECS_PER_TRCK 9 19 | #define DSK_SECTOR_SIZE 512 20 | 21 | #ifndef BYTE_TYPE_DEFINED 22 | #define BYTE_TYPE_DEFINED 23 | typedef unsigned char byte; 24 | #endif 25 | 26 | /** DSKCreate() **********************************************/ 27 | /** Create disk image in Dsk or allocate memory when Dsk=0. **/ 28 | /** Returns pointer to the disk image or 0 on failure. **/ 29 | /*************************************************************/ 30 | byte *DSKCreate(byte *Dsk); 31 | 32 | /** DSKFile() ************************************************/ 33 | /** Create file with a given name, return file ID or 0 on **/ 34 | /** failure. **/ 35 | /*************************************************************/ 36 | int DSKFile(byte *Dsk,const char *FileName); 37 | 38 | /** DSKFileName() ********************************************/ 39 | /** Return name of a file with a given ID or 0 on failure. **/ 40 | /*************************************************************/ 41 | const char *DSKFileName(const byte *Dsk,int ID); 42 | 43 | /** DSKFileSize() ********************************************/ 44 | /** Return side of a file with a given ID or 0 on failure. **/ 45 | /*************************************************************/ 46 | int DSKFileSize(const byte *Dsk,int ID); 47 | 48 | /** DSKRead()/DSKWrite() *************************************/ 49 | /** Read or write a given number of bytes to a given file. **/ 50 | /** Both functions return the number of bytes written or **/ 51 | /** read from the file, or 0 on failure. **/ 52 | /*************************************************************/ 53 | int DSKWrite(byte *Dsk,int ID,const byte *Buf,int Size); 54 | int DSKRead(const byte *Dsk,int ID,byte *Buf,int Size); 55 | 56 | /** DSKDelete() **********************************************/ 57 | /** Delete file with a given ID. Returns ID on success or 0 **/ 58 | /** on failure. **/ 59 | /*************************************************************/ 60 | int DSKDelete(byte *Dsk,int ID); 61 | 62 | /** DSKLoad()/DSKSave() **************************************/ 63 | /** Load or save disk contents from/to a disk image or a **/ 64 | /** directory. DSKLoad() will allocate space if Dsk=0. Both **/ 65 | /** functions return pointer to disk contents on success or **/ 66 | /** 0 on failure. **/ 67 | /*************************************************************/ 68 | byte *DSKLoad(const char *Name,byte *Dsk); 69 | const byte *DSKSave(const char *Name,const byte *Dsk); 70 | 71 | #endif /* FLOPPY_H */ 72 | -------------------------------------------------------------------------------- /source/EMULIB/Hunt.c: -------------------------------------------------------------------------------- 1 | /** EMULib Emulation Library *********************************/ 2 | /** **/ 3 | /** Hunt.c **/ 4 | /** **/ 5 | /** This file implements mechanism for searching possible **/ 6 | /** cheats inside running game data. Also see Hunt.h. **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 2013-2016 **/ 9 | /** You are not allowed to distribute this software **/ 10 | /** commercially. Please, notify me, if you make any **/ 11 | /** changes to this file. **/ 12 | /*************************************************************/ 13 | #include "Hunt.h" 14 | #include 15 | 16 | #if defined(VGBA) 17 | #include "ARM.h" 18 | #define MEMREAD32(A) QRdARM(A) 19 | #define MEMREAD16(A) WRdARM(A) 20 | #define MEMREAD8(A) BRdARM(A) 21 | #elif defined(INES) 22 | #include "M6502.h" 23 | #define MEMREAD32(A) (Rd6502(A)+((int)Rd6502(A+1)<<8)+((int)Rd6502(A+2)<<16)+((int)Rd6502(A+3)<<24)) 24 | #define MEMREAD16(A) (Rd6502(A)+((int)Rd6502(A+1)<<8)) 25 | #define MEMREAD8(A) Rd6502(A) 26 | #elif defined(VGB) || defined(MG) || defined(COLEM) || defined(SPECCY) || defined(FMSX) 27 | #include "Z80.h" 28 | #define MEMREAD32(A) (RdZ80(A)+((int)RdZ80(A+1)<<8)+((int)RdZ80(A+2)<<16)+((int)RdZ80(A+3)<<24)) 29 | #define MEMREAD16(A) (RdZ80(A)+((int)RdZ80(A+1)<<8)) 30 | #define MEMREAD8(A) RdZ80(A) 31 | #else 32 | #define MEMREAD32(A) (0) 33 | #define MEMREAD16(A) (0) 34 | #define MEMREAD8(A) (0) 35 | #endif 36 | 37 | static HUNTEntry Buf[HUNT_BUFSIZE]; 38 | static int Count; 39 | 40 | /** InitHUNT() ***********************************************/ 41 | /** Initialize cheat search, clearing all data. **/ 42 | /*************************************************************/ 43 | void InitHUNT(void) { Count=0; } 44 | 45 | /** TotalHUNT() **********************************************/ 46 | /** Get total number of currently watched locations. **/ 47 | /*************************************************************/ 48 | int TotalHUNT(void) { return(Count); } 49 | 50 | /** GetHUNT() ************************************************/ 51 | /** Get Nth memory location. Returns 0 for invalid N. **/ 52 | /*************************************************************/ 53 | HUNTEntry *GetHUNT(int N) 54 | { return((N>=0)&&(N=0x10000)||(NewValue>=0x10000)) 67 | Flags = (Flags&~HUNT_MASK_SIZE)|HUNT_32BIT; 68 | else if((Value>=0x100)||(NewValue>=0x100)) 69 | Flags = (Flags&~HUNT_MASK_SIZE)|HUNT_16BIT; 70 | 71 | /* Compute mask for given value size and truncate value */ 72 | M = Flags&HUNT_32BIT? 0xFFFFFFFF:Flags&HUNT_16BIT? 0xFFFF:0x00FF; 73 | 74 | #ifdef VGBA 75 | /* ARM aligns data to the size boundary */ 76 | if(M>0xFFFF) Addr&=~3; else if(M>0xFF) Addr&=~1; 77 | #endif 78 | 79 | /* Scan memory for given value */ 80 | for(Size+=Addr,I=0;(Addr0xFFFF? MEMREAD32(Addr):M>0xFF? MEMREAD16(Addr):MEMREAD8(Addr))&M; 83 | 84 | if((J==Value)||(J==((Value-1)&M))) 85 | { 86 | Buf[Count].Addr = Addr; 87 | Buf[Count].Flags = Flags; 88 | Buf[Count].Value = J; 89 | Buf[Count].Orig = J==Value? NewValue:((NewValue-1)&M); 90 | Buf[Count].Count = 0; 91 | ++Count; 92 | ++I; 93 | } 94 | 95 | #ifdef VGBA 96 | /* ARM aligns data to the size boundary */ 97 | if(M>0xFFFF) Addr+=3; else if(M>0xFF) Addr+=1; 98 | #endif 99 | } 100 | 101 | /* Return the number of matches found */ 102 | return(I); 103 | } 104 | 105 | /** ScanHUNT() ***********************************************/ 106 | /** Scan memory for changed values and update search data. **/ 107 | /** Returns number of memory locations updated. **/ 108 | /*************************************************************/ 109 | int ScanHUNT(void) 110 | { 111 | unsigned int K,L; 112 | int J,I; 113 | 114 | /* Scan active search entries */ 115 | for(J=I=0;J0xFFFF? MEMREAD32(Buf[J].Addr):L>0xFF? MEMREAD16(Buf[J].Addr):MEMREAD8(Buf[J].Addr))&L; 119 | 120 | /* Check for expected changes */ 121 | switch(Buf[J].Flags&HUNT_MASK_CHANGE) 122 | { 123 | case HUNT_PLUSONE: L = K==((Buf[J].Value+1)&L);break; 124 | case HUNT_PLUSMANY: L = K>Buf[J].Value;break; 125 | case HUNT_MINUSONE: L = K==((Buf[J].Value-1)&L);break; 126 | case HUNT_MINUSMANY: L = KFlags&HUNT_16BIT? '2':'0', 168 | (HE->Addr&0x000FFFFF)|((HE->Addr&0x0F000000)>>4), 169 | HE->Orig 170 | ); 171 | return(Buf); 172 | 173 | case HUNT_GBA_CB: 174 | /* 2AAAAAAA XXXX - 16bit RAM Write */ 175 | /* 3AAAAAAA 00XX - 8bit RAM Write */ 176 | sprintf(Buf,"%c%07X %04X", 177 | HE->Flags&HUNT_16BIT? '2':'3', 178 | HE->Addr&0x0FFFFFFF, 179 | HE->Orig 180 | ); 181 | return(Buf); 182 | 183 | /** GameBoy **************************************************/ 184 | /** GameBoy has GameShark and GameGenie, but only GameShark **/ 185 | /** can modify RAM. **/ 186 | /*************************************************************/ 187 | case HUNT_GB_GS: 188 | /* 00DDAAAA - 8bit RAM Write, No Bank */ 189 | sprintf(Buf,"00%02X%02X%02X",(HE->Orig)&0xFF,HE->Addr&0x00FF,(HE->Addr&0xFF00)>>8); 190 | if(HE->Flags&HUNT_16BIT) 191 | sprintf(Buf+8,";00%02X%02X%02X",HE->Orig>>8,(HE->Addr+1)&0x00FF,((HE->Addr+1)&0xFF00)>>8); 192 | return(Buf); 193 | 194 | /** NES ******************************************************/ 195 | /** NES has both Pro Action Replay and GameGenie, but only **/ 196 | /** Pro Action Replay can modify RAM. **/ 197 | /*************************************************************/ 198 | case HUNT_NES_AR: 199 | /* 00AAAADD - 8bit RAM Write */ 200 | sprintf(Buf,"00%04X%02X",HE->Addr&0xFFFF,HE->Orig&0xFF); 201 | if(HE->Flags&HUNT_16BIT) 202 | sprintf(Buf+8,";00%04X%02X",(HE->Addr+1)&0xFFFF,HE->Orig>>8); 203 | return(Buf); 204 | 205 | /** Sega MasterSystem and GameGear ***************************/ 206 | /** MasterSystem has Pro Action Replay, while GameGear has **/ 207 | /** GameGenie. Only Pro Action Replay can modify RAM. **/ 208 | /*************************************************************/ 209 | case HUNT_SMS_AR: 210 | /* 00AA-AADD - 8bit RAM Write */ 211 | sprintf(Buf,"00%02X-%02X%02X",(HE->Addr&0xFF00)>>8,HE->Addr&0x00FF,HE->Orig&0xFF); 212 | if(HE->Flags&HUNT_16BIT) 213 | sprintf(Buf+9,";00%02X-%02X%02X",((HE->Addr+1)&0xFF00)>>8,(HE->Addr+1)&0x00FF,HE->Orig>>8); 214 | return(Buf); 215 | 216 | /** ColecoVision, MSX, ZX Spectrum ***************************/ 217 | /** There was no official cheating hardware for these **/ 218 | /** systems, so we come up with our own "hardware". **/ 219 | /*************************************************************/ 220 | case HUNT_MSX: 221 | case HUNT_ZXS: 222 | case HUNT_COLECO: 223 | /* AAAA-DD[DD] - 8bit[16bit] RAM Write */ 224 | if(HE->Flags&HUNT_16BIT) 225 | sprintf(Buf,"%04X-%04X",HE->Addr,HE->Orig&0xFFFF); 226 | else 227 | sprintf(Buf,"%04X-%02X",HE->Addr,HE->Orig&0x00FF); 228 | return(Buf); 229 | } 230 | 231 | /* Invalid cheat type */ 232 | return(0); 233 | } 234 | -------------------------------------------------------------------------------- /source/EMULIB/Hunt.h: -------------------------------------------------------------------------------- 1 | /** EMULib Emulation Library *********************************/ 2 | /** **/ 3 | /** Hunt.h **/ 4 | /** **/ 5 | /** This file declares functions to search for possible **/ 6 | /** cheats inside running game data. Also see Hunt.c. **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 2013-2016 **/ 9 | /** You are not allowed to distribute this software **/ 10 | /** commercially. Please, notify me, if you make any **/ 11 | /** changes to this file. **/ 12 | /*************************************************************/ 13 | #ifndef HUNT_H 14 | #define HUNT_H 15 | 16 | #define HUNT_BUFSIZE 1024 17 | 18 | /** Flags used in AddHUNT() **********************************/ 19 | #define HUNT_MASK_ID 0x00FF 20 | #define HUNT_MASK_CHANGE 0x0700 21 | #define HUNT_CONSTANT 0x0000 22 | #define HUNT_PLUSONE 0x0100 23 | #define HUNT_PLUSMANY 0x0200 24 | #define HUNT_MINUSONE 0x0300 25 | #define HUNT_MINUSMANY 0x0400 26 | #define HUNT_MASK_SIZE 0x1800 27 | #define HUNT_8BIT 0x0000 28 | #define HUNT_16BIT 0x0800 29 | #define HUNT_32BIT 0x1000 30 | 31 | /** Types used in HUNT2Cheat() *******************************/ 32 | #define HUNT_GBA_GS 0 /* GBA GameShark Advance */ 33 | #define HUNT_GBA_CB 1 /* GBA CodeBreaker Advance */ 34 | #define HUNT_SMS_AR 2 /* SMS Pro Action Replay */ 35 | #define HUNT_NES_AR 3 /* NES Pro Action Replay */ 36 | #define HUNT_GB_GS 4 /* GB GameShark */ 37 | #define HUNT_COLECO 5 /* ColecoVision cheats */ 38 | #define HUNT_MSX 6 /* MSX cheats */ 39 | #define HUNT_ZXS 7 /* ZX Spectrum cheats */ 40 | 41 | /** HUNTEntry ************************************************/ 42 | /** Search entry containing data on one memory location. **/ 43 | /*************************************************************/ 44 | typedef struct 45 | { 46 | unsigned int Addr; /* Memory location address */ 47 | unsigned int Orig; /* Original value at the address */ 48 | unsigned int Value; /* Current value at the address */ 49 | unsigned short Flags; /* Options supplied in AddHUNT() */ 50 | unsigned short Count; /* Number of detected changes */ 51 | } HUNTEntry; 52 | 53 | /** InitHUNT() ***********************************************/ 54 | /** Initialize cheat search, clearing all data. **/ 55 | /*************************************************************/ 56 | void InitHUNT(void); 57 | 58 | /** AddHUNT() ************************************************/ 59 | /** Add a new value to search for, with the address range **/ 60 | /** to search in. Returns number of memory locations found. **/ 61 | /*************************************************************/ 62 | int AddHUNT(unsigned int Addr,unsigned int Size,unsigned int Value,unsigned int NewValue,unsigned int Flags); 63 | 64 | /** ScanHUNT() ***********************************************/ 65 | /** Scan memory for changed values and update search data. **/ 66 | /** Returns number of memory locations updated. **/ 67 | /*************************************************************/ 68 | int ScanHUNT(void); 69 | 70 | /** TotalHUNT() **********************************************/ 71 | /** Get total number of currently watched locations. **/ 72 | /*************************************************************/ 73 | int TotalHUNT(void); 74 | 75 | /** GetHUNT() ************************************************/ 76 | /** Get Nth memory location. Returns 0 for invalid N. **/ 77 | /*************************************************************/ 78 | HUNTEntry *GetHUNT(int N); 79 | 80 | /** HUNT2Cheat() *********************************************/ 81 | /** Create cheat code from Nth hunt entry. Returns 0 if the **/ 82 | /** entry is invalid. **/ 83 | /*************************************************************/ 84 | const char *HUNT2Cheat(int N,unsigned int Type); 85 | 86 | #endif /* HUNT_H */ 87 | -------------------------------------------------------------------------------- /source/EMULIB/I8255.c: -------------------------------------------------------------------------------- 1 | /** EMULib Emulation Library *********************************/ 2 | /** **/ 3 | /** I8255.c **/ 4 | /** **/ 5 | /** This file contains emulation for the i8255 parallel **/ 6 | /** port interface (PPI) chip from Intel. See I8255.h for **/ 7 | /** declarations. **/ 8 | /** **/ 9 | /** Copyright (C) Marat Fayzullin 2001-2016 **/ 10 | /** You are not allowed to distribute this software **/ 11 | /** commercially. Please, notify me, if you make any **/ 12 | /** changes to this file. **/ 13 | /*************************************************************/ 14 | #include "I8255.h" 15 | 16 | /** Reset8255 ************************************************/ 17 | /** Reset the chip. Set all data to 0x00. Set all ports to **/ 18 | /** "input" mode. **/ 19 | /*************************************************************/ 20 | void Reset8255(register I8255 *D) 21 | { 22 | /* Initialize all registers and ports */ 23 | D->R[0]=D->Rout[0]=D->Rin[0]=0x00; 24 | D->R[1]=D->Rout[1]=D->Rin[1]=0x00; 25 | D->R[2]=D->Rout[2]=D->Rin[2]=0x00; 26 | D->R[3]=0x9B; 27 | } 28 | 29 | /** Write8255 ************************************************/ 30 | /** Write value V into i8255 register A. Returns 0 when A **/ 31 | /** is out of range, 1 otherwise. **/ 32 | /*************************************************************/ 33 | byte Write8255(register I8255 *D,register byte A,register byte V) 34 | { 35 | switch(A) 36 | { 37 | case 0: 38 | case 1: 39 | case 2: 40 | /* Data registers */ 41 | D->R[A]=V; 42 | break; 43 | case 3: 44 | /* Control register */ 45 | if(V&0x80) D->R[A]=V; 46 | else 47 | { 48 | A=1<<((V&0x0E)>>1); 49 | if(V&0x01) D->R[2]|=A; else D->R[2]&=~A; 50 | } 51 | break; 52 | default: 53 | /* Invalid register */ 54 | return(0); 55 | } 56 | 57 | /* Set output ports */ 58 | V=D->R[3]; 59 | D->Rout[0] = V&0x10? 0x00:D->R[0]; 60 | D->Rout[1] = V&0x02? 0x00:D->R[1]; 61 | D->Rout[2] = ((V&0x01? 0x00:D->R[2])&0x0F) 62 | | ((V&0x08? 0x00:D->R[2])&0xF0); 63 | 64 | /* Done */ 65 | return(1); 66 | } 67 | 68 | /** Read8255 *************************************************/ 69 | /** Read value from an i8255 register A. Returns 0 when A **/ 70 | /** is out of range. **/ 71 | /*************************************************************/ 72 | byte Read8255(register I8255 *D,register byte A) 73 | { 74 | switch(A) 75 | { 76 | case 0: return(D->R[3]&0x10? D->Rin[0]:D->R[0]); 77 | case 1: return(D->R[3]&0x02? D->Rin[1]:D->R[1]); 78 | case 2: return 79 | ( 80 | ((D->R[3]&0x01? D->Rin[2]:D->R[2])&0x0F)| 81 | ((D->R[3]&0x08? D->Rin[2]:D->R[2])&0xF0) 82 | ); 83 | case 3: return(D->R[3]); 84 | } 85 | 86 | /* Invalid address */ 87 | return(0x00); 88 | } 89 | -------------------------------------------------------------------------------- /source/EMULIB/I8255.h: -------------------------------------------------------------------------------- 1 | /** EMULib Emulation Library *********************************/ 2 | /** **/ 3 | /** I8255.h **/ 4 | /** **/ 5 | /** This file contains emulation for the i8255 parallel **/ 6 | /** port interface (PPI) chip from Intel. See I8255.h for **/ 7 | /** the actual code. **/ 8 | /** **/ 9 | /** Copyright (C) Marat Fayzullin 2001-2016 **/ 10 | /** You are not allowed to distribute this software **/ 11 | /** commercially. Please, notify me, if you make any **/ 12 | /** changes to this file. **/ 13 | /*************************************************************/ 14 | #ifndef I8255_H 15 | #define I8255_H 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | #ifndef BYTE_TYPE_DEFINED 21 | #define BYTE_TYPE_DEFINED 22 | typedef unsigned char byte; 23 | #endif 24 | 25 | /** I8255 ****************************************************/ 26 | /** This data structure stores i8255 state and port values. **/ 27 | /*************************************************************/ 28 | typedef struct 29 | { 30 | byte R[4]; /* Registers */ 31 | byte Rout[3]; /* Output ports */ 32 | byte Rin[3]; /* Input ports */ 33 | } I8255; 34 | 35 | /** Reset8255 ************************************************/ 36 | /** Reset the i8255 chip. Set all data to 0x00. Set all **/ 37 | /** ports to "input" mode. **/ 38 | /*************************************************************/ 39 | void Reset8255(register I8255 *D); 40 | 41 | /** Write8255 ************************************************/ 42 | /** Write value V into i8255 register A. Returns 0 when A **/ 43 | /** is out of range, 1 otherwise. **/ 44 | /*************************************************************/ 45 | byte Write8255(register I8255 *D,register byte A,register byte V); 46 | 47 | /** Read8255 *************************************************/ 48 | /** Read value from an i8255 register A. Returns 0 when A **/ 49 | /** is out of range. **/ 50 | /*************************************************************/ 51 | byte Read8255(register I8255 *D,register byte A); 52 | 53 | #ifdef __cplusplus 54 | } 55 | #endif 56 | #endif /* I8255_H */ 57 | -------------------------------------------------------------------------------- /source/EMULIB/IPS.c: -------------------------------------------------------------------------------- 1 | /** EMULib Emulation Library *********************************/ 2 | /** **/ 3 | /** IPS.c **/ 4 | /** **/ 5 | /** This file contains support for the .IPS patch file **/ 6 | /** format. See IPS.h for declarations. **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 1996-2017 **/ 9 | /** You are not allowed to distribute this software **/ 10 | /** commercially. Please, notify me, if you make any **/ 11 | /** changes to this file. **/ 12 | /*************************************************************/ 13 | #include "IPS.h" 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #if defined(ANDROID) 21 | #include "MemFS.h" 22 | #define fopen mopen 23 | #define fclose mclose 24 | #define fread mread 25 | #define fseek mseek 26 | #elif defined(ZLIB) 27 | #include 28 | #define fopen(F,M) (FILE *)gzopen(F,M) 29 | #define fclose(F) gzclose((gzFile)(F)) 30 | #define fread(B,N,L,F) gzread((gzFile)(F),B,(L)*(N)) 31 | #define fseek(F,N,W) (gzseek((gzFile)(F),N,W)<0? -1:0) 32 | #endif 33 | 34 | /** MeasureIPS() *********************************************/ 35 | /** Find total data size assumed by a given .IPS file. **/ 36 | /*************************************************************/ 37 | unsigned int MeasureIPS(const char *FileName) 38 | { 39 | return(ApplyIPS(FileName,0,0)); 40 | } 41 | 42 | /** ApplyIPS() ***********************************************/ 43 | /** Loads patches from an .IPS file and applies them to the **/ 44 | /** given data buffer. Returns number of patches applied. **/ 45 | /*************************************************************/ 46 | unsigned int ApplyIPS(const char *FileName,unsigned char *Data,unsigned int Size) 47 | { 48 | unsigned char Buf[16]; 49 | unsigned int Result,Count,J,N; 50 | int F; 51 | F = ps4LinkOpen(FileName,O_RDONLY,0); 52 | if(!F) return(0); 53 | 54 | /* Verify file header */ 55 | if(ps4LinkRead(F,Buf,5)!=5) { ps4LinkClose(F);return(0); } 56 | if(memcmp(Buf,"PATCH",5)) { ps4LinkClose(F);return(0); } 57 | 58 | for(Result=0,Count=1;ps4LinkRead(F,Buf,5)==5;++Count) 59 | { 60 | J = Buf[2]+((unsigned int)Buf[1]<<8)+((unsigned int)Buf[0]<<16); 61 | N = Buf[4]+((unsigned int)Buf[3]<<8); 62 | 63 | /* Apparently, these may signal the end of .IPS file */ 64 | if((J==0xFFFFFF) || !memcmp(Buf,"EOF",3)) break; 65 | 66 | /* If patching with a block of data... */ 67 | if(N) 68 | { 69 | /* Copying data */ 70 | 71 | if(!Data) 72 | { 73 | /* Just measuring patch size */ 74 | if(ResultSize) 78 | { 79 | debugNetPrintf(3,"IPS: Failed applying COPY patch #%d to 0x%X..0x%X of 0x%X bytes.\n",Count,J,J+N-1,Size); 80 | if(ps4LinkLseek(F,N,SEEK_CUR)<0) break; 81 | } 82 | else if(ps4LinkRead(F,Data+J,N)==N) 83 | { 84 | // debugNetPrintf(3,"IPS: Applied COPY patch #%d to 0x%X..0x%X.\n",Count,J,J+N-1); 85 | ++Result; 86 | } 87 | else 88 | { 89 | debugNetPrintf(3,"IPS: Failed reading COPY patch #%d from the file.\n",Count); 90 | break; 91 | } 92 | } 93 | else 94 | { 95 | /* Filling with a value */ 96 | 97 | if(ps4LinkRead(F,Buf,3)!=3) 98 | { 99 | if(Data) debugNetPrintf(3,"IPS: Failed reading FILL patch #%d from the file.\n",Count); 100 | break; 101 | } 102 | 103 | /* Compute fill length */ 104 | N = ((unsigned int)Buf[0]<<8)+Buf[1]; 105 | 106 | if(!Data) 107 | { 108 | if(ResultSize)) 111 | { 112 | debugNetPrintf(3,"IPS: Failed applying FILL patch #%d (0x%02X) to 0x%X..0x%X of 0x%X bytes.\n",Count,Buf[1],J,J+N-1,Size); 113 | } 114 | else 115 | { 116 | // debugNetPrintf(3,"IPS: Applied FILL patch #%d (0x%02X) to 0x%X..0x%X.\n",Count,Buf[1],J,J+N-1); 117 | memset(Data+J,Buf[2],N); 118 | ++Result; 119 | } 120 | } 121 | } 122 | 123 | ps4LinkClose(F); 124 | return(Result); 125 | } 126 | 127 | #if defined(ZLIB) || defined(ANDROID) 128 | #undef fopen 129 | #undef fclose 130 | #undef fread 131 | #undef fseek 132 | #endif 133 | -------------------------------------------------------------------------------- /source/EMULIB/IPS.h: -------------------------------------------------------------------------------- 1 | /** EMULib Emulation Library *********************************/ 2 | /** **/ 3 | /** IPS.h **/ 4 | /** **/ 5 | /** This file contains declarations for the .IPS patch file **/ 6 | /** support. See IPS.c for implementation. **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 1996-2017 **/ 9 | /** You are not allowed to distribute this software **/ 10 | /** commercially. Please, notify me, if you make any **/ 11 | /** changes to this file. **/ 12 | /*************************************************************/ 13 | #ifndef IPS_H 14 | #define IPS_H 15 | 16 | /** ApplyIPS() ***********************************************/ 17 | /** Loads patches from an .IPS file and applies them to the **/ 18 | /** given data buffer. Returns number of patches applied. **/ 19 | /*************************************************************/ 20 | unsigned int ApplyIPS(const char *FileName,unsigned char *Data,unsigned int Size); 21 | 22 | /** MeasureIPS() *********************************************/ 23 | /** Find total data size assumed by a given .IPS file. **/ 24 | /*************************************************************/ 25 | unsigned int MeasureIPS(const char *FileName); 26 | 27 | #endif /* IPS_H */ 28 | -------------------------------------------------------------------------------- /source/EMULIB/MCF.h: -------------------------------------------------------------------------------- 1 | /** EMULib Emulation Library *********************************/ 2 | /** **/ 3 | /** MCF.h **/ 4 | /** **/ 5 | /** This file contains declarations for the .MCF cheat file **/ 6 | /** support. See MCF.c for implementation. **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 2017 **/ 9 | /** You are not allowed to distribute this software **/ 10 | /** commercially. Please, notify me, if you make any **/ 11 | /** changes to this file. **/ 12 | /*************************************************************/ 13 | #ifndef MCF_H 14 | #define MCF_H 15 | 16 | /** MCFEntry *************************************************/ 17 | /** Definition of a single MCF entry representing a cheat. **/ 18 | /*************************************************************/ 19 | typedef struct 20 | { 21 | unsigned int Addr; // Address to apply cheat to 22 | unsigned int Data; // Data to write to Addr 23 | unsigned char Size; // Size of Data in bytes (1/2/4) 24 | char Note[116]; // Description of the cheat 25 | } MCFEntry; 26 | 27 | /** LoadFileMCF() ********************************************/ 28 | /** Load cheats from .MCF file. Returns number of loaded **/ 29 | /** cheat entries or 0 on failure. **/ 30 | /*************************************************************/ 31 | int LoadFileMCF(const char *Name,MCFEntry *Cheats,int MaxCheats); 32 | 33 | /** SaveFileMCF() ********************************************/ 34 | /** Save cheats to .MCF file. Returns number of loaded **/ 35 | /** cheat entries or 0 on failure. **/ 36 | /*************************************************************/ 37 | int SaveFileMCF(const char *Name,const MCFEntry *Cheats,int CheatCount); 38 | 39 | #endif /* MCF_H */ 40 | -------------------------------------------------------------------------------- /source/EMULIB/Orbis/LibOrbis.h: -------------------------------------------------------------------------------- 1 | /** EMULib Emulation Library *********************************/ 2 | /** **/ 3 | /** LibOrbis.h **/ 4 | /** **/ 5 | /** This file contains Orbis-dependent definitions and **/ 6 | /** declarations for the emulation library. **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 1996-2016 **/ 9 | /** Copyright (C) Akop Karapetyan 2007 **/ 10 | /** You are not allowed to distribute this software **/ 11 | /** commercially. Please, notify me, if you make any **/ 12 | /** changes to this file. **/ 13 | /** Copyright (c) Antonio Jose Ramos Marquez 2017 **/ 14 | /*************************************************************/ 15 | #ifndef LIBORBIS_H 16 | #define LIBORBIS_H 17 | 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #define SND_CHANNELS 16 /* Number of sound channels */ 24 | #define SND_BITS 8 25 | #define SND_BUFSIZE 256 //(1<>16)&0xFF)+((P>>8)&0xFF)+(P&0xFF))/3) 33 | #define RMASK 0xFF0000 34 | #define GMASK 0x00FF00 35 | #define BMASK 0x0000FF 36 | 37 | #elif defined(BPP16) 38 | #define PIXEL(R,G,B) (pixel)(((31*(R)/255)<<11)|((63*(G)/255)<<5)|(31*(B)/255)) 39 | //#define RGB(r,g,b) (((((b)>>3)&0x1F)<<10)|((((g)>>3)&0x1F)<<5)|(((r)>>3)&0x1F)|0x8000) 40 | #define PIXEL2MONO(P) (522*(((P)&31)+(((P)>>5)&63)+(((P)>>11)&31))>>8) 41 | #define RMASK 0xF800 42 | #define GMASK 0x07E0 43 | #define BMASK 0x001F 44 | 45 | #elif defined(BPP8) 46 | #define PIXEL(R,G,B) (pixel)(((7*(R)/255)<<5)|((7*(G)/255)<<2)|(3*(B)/255)) 47 | #define PIXEL2MONO(P) (3264*((((P)<<1)&7)+(((P)>>2)&7)+(((P)>>5)&7))>>8) 48 | #define RMASK 0xE0 49 | #define GMASK 0x1C 50 | #define BMASK 0x03 51 | #endif 52 | 53 | int ARGC; 54 | char **ARGV; 55 | 56 | /** InitUnix() ***********************************************/ 57 | /** Initialize Unix/X11 resources and set initial window. **/ 58 | /** title and dimensions. **/ 59 | /*************************************************************/ 60 | int InitOrbis(const char *Title,int Width,int Height); 61 | 62 | /** TrashUnix() **********************************************/ 63 | /** Free resources allocated in InitUnix() **/ 64 | /*************************************************************/ 65 | void TrashOrbis(void); 66 | 67 | /** InitAudio() **********************************************/ 68 | /** Initialize sound. Returns rate (Hz) on success, else 0. **/ 69 | /** Rate=0 to skip initialization (will be silent). **/ 70 | /*************************************************************/ 71 | unsigned int InitAudio(unsigned int Rate,unsigned int Latency); 72 | 73 | /** StopSound() **********************************************/ 74 | /** Temporarily suspend sound. **/ 75 | /*************************************************************/ 76 | void StopSound(void); 77 | 78 | /** StopSound() **********************************************/ 79 | /** Reset sound chips. **/ 80 | /*************************************************************/ 81 | void ResetSound(void); 82 | 83 | /** ResumeSound() ********************************************/ 84 | /** Resume sound after StopSound(). **/ 85 | /*************************************************************/ 86 | void ResumeSound(void); 87 | 88 | /** TrashAudio() *********************************************/ 89 | /** Free resources allocated by InitAudio(). **/ 90 | /*************************************************************/ 91 | void TrashAudio(void); 92 | 93 | /** PauseAudio() *********************************************/ 94 | /** Pause/resume audio playback. **/ 95 | /*************************************************************/ 96 | int PauseAudio(int Switch); 97 | 98 | /** X11Window() **********************************************/ 99 | /** Open a window of a given size with a given title. **/ 100 | /*************************************************************/ 101 | //Window X11Window(const char *Title,int Width,int Height); 102 | 103 | /** X11GetColor **********************************************/ 104 | /** Get pixel for the current screen depth based on the RGB **/ 105 | /** values. **/ 106 | /*************************************************************/ 107 | unsigned int OrbisGetColor(unsigned char R,unsigned char G,unsigned char B); 108 | 109 | #if defined(FMSX) && defined(ALTSOUND) 110 | void WritePSG(int R,int V); 111 | void WriteSNG(int R,int V); 112 | void Write2212(int R,int V); 113 | void WriteOPLL(int R,int V); 114 | void WriteAUDIO(int R,int V); 115 | int ReadAUDIO(int R); 116 | int ReadPSG(int R); 117 | #endif 118 | 119 | #ifdef __cplusplus 120 | } 121 | #endif 122 | #endif /* LIBORBIS_H */ 123 | -------------------------------------------------------------------------------- /source/EMULIB/Orbis/SndOrbis.c: -------------------------------------------------------------------------------- 1 | /** EMULib Emulation Library *********************************/ 2 | /** **/ 3 | /** SndOrbis.c **/ 4 | /** **/ 5 | /** This file contains standard sound generation routines **/ 6 | /** for Playstation Vita console **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 1996-2008 **/ 9 | /** Akop Karapetyan 2008 **/ 10 | /** Vincent van Dam 2002 **/ 11 | /** Antonio Jose Ramos Marquez 2015-2017 **/ 12 | /** You are not allowed to distribute this software **/ 13 | /** commercially. Please, notify me, if you make any **/ 14 | /** changes to this file. **/ 15 | /*************************************************************/ 16 | 17 | #include 18 | 19 | #if defined(FMSX) && defined(ALTSOUND) 20 | #include "fmopl.h" 21 | #include "emu2149.h" 22 | #include "emu2212.h" 23 | #include "emu2413.h" 24 | #endif 25 | 26 | #include 27 | #include "Sound.h" 28 | #include 29 | static void MixAudio(short *buffer, unsigned int length); 30 | static void AudioCallback(OrbisAudioSample *buf, unsigned int samples, void *userdata); 31 | 32 | #if defined(FMSX) && defined(ALTSOUND) 33 | #define MSX_CLK 3579545 34 | 35 | static OPLL *opll; 36 | static FM_OPL *fm_opl; 37 | static PSG *psg; 38 | static SCC *scc; 39 | 40 | int Use2413 = 1; /* MSX-MUSIC emulation (1=enable) */ 41 | int Use8950 = 1; /* MSX-AUDIO emulation (1=enable) */ 42 | 43 | float FactorPSG = 3.00; /* Volume percentage of PSG */ 44 | float FactorSCC = 3.00; /* Volume percentage of SCC */ 45 | float Factor2413 = 3.00; /* Volume percentage of MSX-MUSIC */ 46 | float Factor8950 = 2.25; /* Volume percentage of MSX-AUDIO */ 47 | #else 48 | static sample SndData[SND_BUFSIZE]; 49 | static int MixBuffer[SND_BUFSIZE]; 50 | static int WPtr = 0; 51 | #endif 52 | 53 | static int SndRate = 0; /* Audio sampling rate */ 54 | 55 | /** StopSound() **********************************************/ 56 | /** Temporarily suspend sound. **/ 57 | /*************************************************************/ 58 | void StopSound(void) { orbisAudioPause(0); } 59 | 60 | /** ResumeSound() ********************************************/ 61 | /** Resume sound after StopSound(). **/ 62 | /*************************************************************/ 63 | void ResumeSound(void) { orbisAudioResume(0); } 64 | 65 | /** InitAudio() **********************************************/ 66 | /** Initialize sound. Returns rate (Hz) on success, else 0. **/ 67 | /** Rate=0 to skip initialization (will be silent). **/ 68 | /*************************************************************/ 69 | unsigned int InitAudio(unsigned int Rate,unsigned int Latency) 70 | { 71 | TrashAudio(); 72 | 73 | orbisAudioSetCallback(0, AudioCallback, 0); 74 | 75 | /* Only 44100 supported */ 76 | if(Rate != 44100) return(SndRate = 0); 77 | 78 | #if defined(FMSX) && defined(ALTSOUND) 79 | /* MSX-MUSIC emulation */ 80 | debugNetPrintf(3,"AQUISSSSSSSS \n"); 81 | if (Use2413) 82 | { 83 | OPLL_init(MSX_CLK,Rate); 84 | opll=OPLL_new(); 85 | OPLL_reset(opll); 86 | OPLL_reset_patch(opll,0); 87 | } 88 | 89 | /* MSX-AUDIO emulation */ 90 | if (Use8950) 91 | { 92 | fm_opl=OPLCreate(OPL_TYPE_Y8950,MSX_CLK,Rate,256); 93 | OPLResetChip(fm_opl); 94 | } 95 | 96 | /* PSG/SCC emulation */ 97 | PSG_init(MSX_CLK,Rate); 98 | psg=PSG_new(); 99 | PSG_reset(psg); 100 | PSG_setVolumeMode(psg,2); 101 | 102 | SCC_init(MSX_CLK,Rate); 103 | scc=SCC_new(); 104 | SCC_reset(scc); 105 | #else 106 | WPtr=0; 107 | memset(SndData,0,sizeof(SndData)); 108 | memset(MixBuffer,0,sizeof(MixBuffer)); 109 | #endif 110 | 111 | /* Done */ 112 | return(SndRate = Rate); 113 | } 114 | 115 | /** ResetSound() *********************************************/ 116 | /** Reset sound chips. **/ 117 | /*************************************************************/ 118 | void ResetSound() 119 | { 120 | #if defined(FMSX) && defined(ALTSOUND) 121 | PSG_reset(psg); 122 | SCC_reset(scc); 123 | if (Use2413) OPLL_reset(opll); 124 | if (Use8950) OPLResetChip(fm_opl); 125 | #endif 126 | } 127 | 128 | /** TrashAudio() *********************************************/ 129 | /** Free resources allocated by InitAudio(). **/ 130 | /*************************************************************/ 131 | void TrashAudio(void) 132 | { 133 | if (!SndRate) return; 134 | SndRate = 0; 135 | 136 | /* Shutdown wave audio */ 137 | StopSound(); 138 | 139 | #if defined(FMSX) && defined(ALTSOUND) 140 | /* clean up MSXMUSIC */ 141 | if (Use2413) 142 | { 143 | OPLL_close(); 144 | OPLL_delete(opll); 145 | } 146 | 147 | /* clean up MSXAUDIO */ 148 | if (Use8950) OPLDestroy(fm_opl); 149 | 150 | /* clean up PSG/SCC */ 151 | PSG_delete(psg); 152 | SCC_delete(scc); 153 | #endif 154 | } 155 | 156 | /** AudioCallback() ******************************************/ 157 | /** Called by the system to render sound **/ 158 | /*************************************************************/ 159 | static void AudioCallback(OrbisAudioSample *buf, unsigned int samples, void *userdata) 160 | { 161 | MixAudio((short*)buf, samples); 162 | } 163 | 164 | /** AudioCallback() ******************************************/ 165 | /** Writes sound to the output buffer, **/ 166 | /** mixing as necessary **/ 167 | /*************************************************************/ 168 | static void MixAudio(short *buffer, unsigned int length) 169 | { 170 | register int J; 171 | 172 | #if defined(FMSX) && defined(ALTSOUND) 173 | register int R; 174 | register INT16 P,O,A,S; 175 | 176 | /* Mix sound */ 177 | for(J=0;J32767)?32767:(R<-32768)?-32768:R; 187 | } 188 | #else 189 | /* Mix sound */ 190 | memset(MixBuffer,0,sizeof(MixBuffer)); 191 | RenderAudio(MixBuffer,length); 192 | PlayAudio(MixBuffer,length); 193 | 194 | /* Write to output buffer */ 195 | for(J=0;JSND_BUFSIZE) return(0); 224 | 225 | /* Copy sample data and increment buffer position */ 226 | memcpy(SndData+WPtr*sizeof(sample),Data,Length*sizeof(sample)); 227 | if ((WPtr+=Length)>=SND_BUFSIZE) WPtr=0; 228 | 229 | /* Return number of samples copied */ 230 | return(Length); 231 | #endif 232 | } 233 | 234 | #if defined(FMSX) && defined(ALTSOUND) 235 | /* wrapper functions to actual sound emulation */ 236 | void WriteOPLL (int R,int V) { OPLL_writeReg(opll,R,V); } 237 | void WriteAUDIO(int R,int V) { OPLWrite(fm_opl,R,V); } 238 | void Write2212 (int R,int V) { SCC_write(scc,R,V); } 239 | void WritePSG (int R,int V) { PSG_writeReg(psg,R,V); } 240 | int ReadAUDIO (int R) { return OPLRead(fm_opl,R); } 241 | int ReadPSG (int R) { return PSG_readReg(psg,R); } 242 | #endif 243 | -------------------------------------------------------------------------------- /source/EMULIB/Record.h: -------------------------------------------------------------------------------- 1 | /** EMULib Emulation Library *********************************/ 2 | /** **/ 3 | /** Record.h **/ 4 | /** **/ 5 | /** This file contains routines for gameplay recording and **/ 6 | /** replay. **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 2013-2016 **/ 9 | /** The contents of this file are property of Marat **/ 10 | /** Fayzullin and should only be used as agreed with **/ 11 | /** him. The file is confidential. Absolutely no **/ 12 | /** distribution allowed. **/ 13 | /*************************************************************/ 14 | #ifndef RECORD_H 15 | #define RECORD_H 16 | 17 | #include "EMULib.h" 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** RPLPlay()/RPLRecord() arguments **************************/ 24 | #define RPL_OFF 0xFFFFFFFF /* Disable */ 25 | #define RPL_ON 0xFFFFFFFE /* Enable */ 26 | #define RPL_TOGGLE 0xFFFFFFFD /* Toggle */ 27 | #define RPL_RESET 0xFFFFFFFC /* Reset and enable */ 28 | #define RPL_NEXT 0xFFFFFFFB /* Play the next record */ 29 | #define RPL_QUERY 0xFFFFFFFA /* Query state */ 30 | 31 | /** RPLPlay(RPL_NEXT) results ********************************/ 32 | #define RPL_ENDED 0xFFFFFFFF /* Finished or stopped */ 33 | 34 | /** RPLInit() ************************************************/ 35 | /** Initialize record/relay subsystem. **/ 36 | /*************************************************************/ 37 | void RPLInit(unsigned int (*SaveHandler)(unsigned char *,unsigned int),unsigned int (*LoadHandler)(unsigned char *,unsigned int),unsigned int MaxSize); 38 | 39 | /** RPLTrash() ***********************************************/ 40 | /** Free all record/replay resources. **/ 41 | /*************************************************************/ 42 | void RPLTrash(void); 43 | 44 | /** RPLRecord() **********************************************/ 45 | /** Record emulation state and joystick input for replaying **/ 46 | /** it back later. **/ 47 | /*************************************************************/ 48 | int RPLRecord(unsigned int JoyState); 49 | 50 | /** RPLRecordKeys() ******************************************/ 51 | /** Record emulation state, keys, and joystick input for **/ 52 | /** replaying them back later. **/ 53 | /*************************************************************/ 54 | int RPLRecordKeys(unsigned int JoyState,const unsigned char *Keys,unsigned int KeySize); 55 | 56 | /** RPLPlay() ************************************************/ 57 | /** Replay gameplay saved with RPLRecord(). **/ 58 | /*************************************************************/ 59 | unsigned int RPLPlay(int Cmd); 60 | 61 | /** RPLPlayKeys() ********************************************/ 62 | /** Replay gameplay saved with RPLRecordKeys(). **/ 63 | /*************************************************************/ 64 | unsigned int RPLPlayKeys(int Cmd,unsigned char *Keys,unsigned int KeySize); 65 | 66 | /** RPLShow() ************************************************/ 67 | /** Draw replay icon when active. **/ 68 | /*************************************************************/ 69 | void RPLShow(Image *Img,int X,int Y); 70 | 71 | /** SaveRPL() ************************************************/ 72 | /** Save gameplay recording into given file. **/ 73 | /*************************************************************/ 74 | int SaveRPL(const char *FileName); 75 | 76 | /** LoadRPL() ************************************************/ 77 | /** Load gameplay recording from given file. **/ 78 | /*************************************************************/ 79 | int LoadRPL(const char *FileName); 80 | 81 | #ifdef __cplusplus 82 | } 83 | #endif 84 | #endif /* RECORD_H */ 85 | -------------------------------------------------------------------------------- /source/EMULIB/SCC.c: -------------------------------------------------------------------------------- 1 | /** EMULib Emulation Library *********************************/ 2 | /** **/ 3 | /** SCC.c **/ 4 | /** **/ 5 | /** This file contains emulation for the SCC sound chip **/ 6 | /** produced by Konami. **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 1996-2016 **/ 9 | /** You are not allowed to distribute this software **/ 10 | /** commercially. Please, notify me, if you make any **/ 11 | /** changes to this file. **/ 12 | /*************************************************************/ 13 | 14 | #include "SCC.h" 15 | #include "Sound.h" 16 | #include 17 | 18 | /** ResetSCC() ***********************************************/ 19 | /** Reset the sound chip and use sound channels from the **/ 20 | /** one given in First. **/ 21 | /*************************************************************/ 22 | void ResetSCC(register SCC *D,int First) 23 | { 24 | int J; 25 | 26 | /* Reset registers */ 27 | memset(D->R,0x00,sizeof(D->R)); 28 | 29 | /* Set instruments, frequencies, volumes */ 30 | for(J=0;JFreq[J]=D->Volume[J]=0; 34 | } 35 | 36 | D->First = First; 37 | D->Sync = SCC_ASYNC; 38 | D->Changed = 0x00; 39 | D->WChanged = 0x00; 40 | } 41 | 42 | /** ReadSCC() ************************************************/ 43 | /** Call this function to read contents of the generic SCC **/ 44 | /** sound chip registers. **/ 45 | /*************************************************************/ 46 | byte ReadSCC(register SCC *D,register byte R) 47 | { 48 | return(R<0x80? D->R[R]:0xFF); 49 | } 50 | 51 | /** ReadSCCP() ***********************************************/ 52 | /** Call this function to read contents of the newer SCC+ **/ 53 | /** sound chip registers. **/ 54 | /*************************************************************/ 55 | byte ReadSCCP(register SCC *D,register byte R) 56 | { 57 | return(R<0xA0? D->R[R]:0xFF); 58 | } 59 | 60 | /** WriteSCC() ***********************************************/ 61 | /** Call this function to output a value V into the generic **/ 62 | /** SCC sound chip. **/ 63 | /*************************************************************/ 64 | void WriteSCC(register SCC *D,register byte R,register byte V) 65 | { 66 | /* Prevent rollover */ 67 | if(R>=0xE0) return; 68 | /* Generic SCC has one waveform less than SCC+ */ 69 | if(R>=0x80) { WriteSCCP(D,R+0x20,V);return; } 70 | /* The last waveform applies to both channels 3 and 4 */ 71 | if(R>=0x60) { WriteSCCP(D,R,V);WriteSCCP(D,R+0x20,V);return; } 72 | /* Other waveforms are the same */ 73 | WriteSCCP(D,R,V); 74 | } 75 | 76 | /** WriteSCCP() **********************************************/ 77 | /** Call this function to output a value V into the newer **/ 78 | /** SCC+ sound chip. **/ 79 | /*************************************************************/ 80 | void WriteSCCP(register SCC *D,register byte R,register byte V) 81 | { 82 | register int J; 83 | register byte I; 84 | 85 | /* Exit if no change */ 86 | if(V==D->R[R]) return; 87 | 88 | if((R&0xE0)==0xA0) 89 | { 90 | /* Emulate melodic features */ 91 | 92 | /* Save active channel mask in I */ 93 | I=D->R[0xAF]; 94 | /* Write to a register */ 95 | R&=0xEF; 96 | D->R[R]=D->R[R+0x10]=V; 97 | 98 | /* Melodic register number 0..15 */ 99 | R&=0x0F; 100 | switch(R) 101 | { 102 | case 0: case 1: case 2: case 3: case 4: 103 | case 5: case 6: case 7: case 8: case 9: 104 | /* Exit if the channel is silenced */ 105 | if(!(I&(1<<(R>>1)))) return; 106 | /* Go to the first register of the pair */ 107 | R=(R&0xFE)+0xA0; 108 | /* Compute frequency */ 109 | J=((int)(D->R[R+1]&0x0F)<<8)+D->R[R]; 110 | /* Compute channel number */ 111 | R=(R&0x0F)>>1; 112 | /* Assign frequency */ 113 | D->Freq[R]=J? SCC_BASE/J:0; 114 | /* Compute changed channels mask */ 115 | D->Changed|=1<Volume[R]=255*(V&0x0F)/15; 123 | /* Compute changed channels mask */ 124 | D->Changed|=(1<Changed|=R; 131 | /* Update frequencies */ 132 | for(I=0;R&&(I>=1,V>>=1) 133 | if(R&1) 134 | { 135 | if(!(V&1)) D->Freq[I]=0; 136 | else 137 | { 138 | J=I*2+0xA0; 139 | J=((int)(D->R[J+1]&0x0F)<<8)+D->R[J]; 140 | D->Freq[I]=J? SCC_BASE/J:0; 141 | } 142 | } 143 | break; 144 | 145 | default: 146 | /* Wrong register, do nothing */ 147 | return; 148 | } 149 | } 150 | else 151 | { 152 | /* Emulate wave table features */ 153 | 154 | /* Write data to SCC */ 155 | D->R[R]=V; 156 | /* Wrong register, do nothing */ 157 | if(R>=0xA0) return; 158 | /* Mark channel waveform as changed */ 159 | D->WChanged|=1<<(R>>5); 160 | } 161 | 162 | /* For asynchronous mode, make Sound() calls right away */ 163 | if(!D->Sync&&(D->Changed||D->WChanged)) SyncSCC(D,SCC_FLUSH); 164 | } 165 | 166 | /** SyncSCC() ************************************************/ 167 | /** Flush all accumulated changes by issuing Sound() calls **/ 168 | /** and set the synchronization on/off. The second argument **/ 169 | /** should be SCC_SYNC/SCC_ASYNC to set/reset sync, or **/ 170 | /** SCC_FLUSH to leave sync mode as it is. **/ 171 | /*************************************************************/ 172 | void SyncSCC(register SCC *D,register byte Sync) 173 | { 174 | register int J,I; 175 | 176 | if(Sync!=SCC_FLUSH) D->Sync=Sync; 177 | 178 | /* Modify waveforms */ 179 | for(J=0,I=D->WChanged;I&&(J>=1) 180 | if(I&1) SetWave(J+D->First,(signed char *)(D->R+(J<<5)),32,0); 181 | 182 | /* Modify frequencies and volumes */ 183 | for(J=0,I=D->Changed;I&&(J>=1) 184 | if(I&1) Sound(J+D->First,D->Freq[J],D->Volume[J]); 185 | 186 | D->Changed=D->WChanged=0x00; 187 | } 188 | -------------------------------------------------------------------------------- /source/EMULIB/SCC.h: -------------------------------------------------------------------------------- 1 | /** EMULib Emulation Library *********************************/ 2 | /** **/ 3 | /** SCC.h **/ 4 | /** **/ 5 | /** This file contains definitions and declarations for **/ 6 | /** routines in SCC.c. **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 1996-2016 **/ 9 | /** You are not allowed to distribute this software **/ 10 | /** commercially. Please, notify me, if you make any **/ 11 | /** changes to this file. **/ 12 | /*************************************************************/ 13 | #ifndef SCC_H 14 | #define SCC_H 15 | 16 | #define SCC_BASE 111861 /* Base frequency for SCC */ 17 | #define SCC_CHANNELS 5 /* 5 melodic channels */ 18 | 19 | #define SCC_ASYNC 0 /* Asynchronous emulation */ 20 | #define SCC_SYNC 1 /* Synchronous emulation mode */ 21 | #define SCC_FLUSH 2 /* Flush buffers only */ 22 | 23 | #ifndef BYTE_TYPE_DEFINED 24 | #define BYTE_TYPE_DEFINED 25 | typedef unsigned char byte; 26 | #endif 27 | 28 | /** SCC ******************************************************/ 29 | /** This data structure stores SCC state. **/ 30 | /*************************************************************/ 31 | typedef struct 32 | { 33 | byte R[256]; /* SCC register contents */ 34 | int Freq[SCC_CHANNELS]; /* Frequencies (0 for off) */ 35 | int Volume[SCC_CHANNELS]; /* Volumes (0..255) */ 36 | int First; /* First used Sound() channel */ 37 | byte Changed; /* Bitmap of changed channels */ 38 | byte WChanged; /* Bitmap of changed waveforms */ 39 | byte Sync; /* SCC_SYNC/SCC_ASYNC */ 40 | } SCC; 41 | 42 | /** ResetSCC() ***********************************************/ 43 | /** Reset the sound chip and use sound channels from the **/ 44 | /** one given in First. **/ 45 | /*************************************************************/ 46 | void ResetSCC(register SCC *D,int First); 47 | 48 | /** ReadSCC() ************************************************/ 49 | /** Call this function to read contents of the generic SCC **/ 50 | /** sound chip registers. **/ 51 | /*************************************************************/ 52 | byte ReadSCC(register SCC *D,register byte R); 53 | 54 | /** ReadSCCP() ***********************************************/ 55 | /** Call this function to read contents of the newer SCC+ **/ 56 | /** sound chip registers. **/ 57 | /*************************************************************/ 58 | byte ReadSCCP(register SCC *D,register byte R); 59 | 60 | /** WriteSCC() ***********************************************/ 61 | /** Call this function to output a value V into the generic **/ 62 | /** SCC sound chip. **/ 63 | /*************************************************************/ 64 | void WriteSCC(register SCC *D,register byte R,register byte V); 65 | 66 | /** WriteSCCP() **********************************************/ 67 | /** Call this function to output a value V into the newer **/ 68 | /** SCC+ sound chip. **/ 69 | /*************************************************************/ 70 | void WriteSCCP(register SCC *D,register byte R,register byte V); 71 | 72 | /** SyncSCC() ************************************************/ 73 | /** Flush all accumulated changes by issuing Sound() calls **/ 74 | /** and set the synchronization on/off. The second argument **/ 75 | /** should be SCC_SYNC/SCC_ASYNC to set/reset sync, or **/ 76 | /** SCC_FLUSH to leave sync mode as it is. **/ 77 | /*************************************************************/ 78 | void SyncSCC(register SCC *D,register byte Sync); 79 | 80 | #endif /* SCC_H */ 81 | -------------------------------------------------------------------------------- /source/EMULIB/SHA1.c: -------------------------------------------------------------------------------- 1 | #include "SHA1.h" 2 | 3 | #define ROTATE(Data,Shift) \ 4 | ((((Data)<<(Shift))|((Data)>>(32-(Shift))))&0xFFFFFFFF) 5 | 6 | static void ProcessSHA1(SHA1 *State) 7 | { 8 | static const unsigned int K[] = { 0x5A827999,0x6ED9EBA1,0x8F1BBCDC,0xCA62C1D6 }; 9 | unsigned int A,B,C,D,E,T,W[80]; 10 | int J; 11 | 12 | for(J=0;J<64;J+=4) 13 | W[J>>2] = 14 | (((int)State->Buf[J])<<24) 15 | | (((int)State->Buf[J+1])<<16) 16 | | (((int)State->Buf[J+2])<<8) 17 | | State->Buf[J+3]; 18 | 19 | for(J=16;J<80;++J) 20 | { 21 | T = W[J-3]^W[J-8]^W[J-14]^W[J-16]; 22 | W[J] = ROTATE(T,1); 23 | } 24 | 25 | A = State->Msg[0]; 26 | B = State->Msg[1]; 27 | C = State->Msg[2]; 28 | D = State->Msg[3]; 29 | E = State->Msg[4]; 30 | 31 | for(J=0;J<20;++J) 32 | { 33 | T = (ROTATE(A,5) + ((B&C)|(~B&D)) + E + W[J] + K[0]) & 0xFFFFFFFF; 34 | E = D; 35 | D = C; 36 | C = ROTATE(B,30); 37 | B = A; 38 | A = T; 39 | } 40 | 41 | for(J=20;J<40;++J) 42 | { 43 | T = (ROTATE(A,5) + (B^C^D) + E + W[J] + K[1]) & 0xFFFFFFFF; 44 | E = D; 45 | D = C; 46 | C = ROTATE(B,30); 47 | B = A; 48 | A = T; 49 | } 50 | 51 | for(J=40;J<60;++J) 52 | { 53 | T = (ROTATE(A,5) + ((B&C)|(B&D)|(C&D)) + E + W[J] + K[2]) & 0xFFFFFFFF; 54 | E = D; 55 | D = C; 56 | C = ROTATE(B,30); 57 | B = A; 58 | A = T; 59 | } 60 | 61 | for(J=60;J<80;++J) 62 | { 63 | T = (ROTATE(A,5) + (B^C^D) + E + W[J] + K[3]) & 0xFFFFFFFF; 64 | E = D; 65 | D = C; 66 | C = ROTATE(B,30); 67 | B = A; 68 | A = T; 69 | } 70 | 71 | State->Msg[0] = (State->Msg[0] + A) & 0xFFFFFFFF; 72 | State->Msg[1] = (State->Msg[1] + B) & 0xFFFFFFFF; 73 | State->Msg[2] = (State->Msg[2] + C) & 0xFFFFFFFF; 74 | State->Msg[3] = (State->Msg[3] + D) & 0xFFFFFFFF; 75 | State->Msg[4] = (State->Msg[4] + E) & 0xFFFFFFFF; 76 | 77 | State->Ptr = 0; 78 | } 79 | 80 | void ResetSHA1(SHA1 *State) 81 | { 82 | State->LenL = 0; 83 | State->LenH = 0; 84 | State->Ptr = 0; 85 | State->Done = 0; 86 | State->Error = 0; 87 | 88 | State->Msg[0] = 0x67452301; 89 | State->Msg[1] = 0xEFCDAB89; 90 | State->Msg[2] = 0x98BADCFE; 91 | State->Msg[3] = 0x10325476; 92 | State->Msg[4] = 0xC3D2E1F0; 93 | } 94 | 95 | int ComputeSHA1(SHA1 *State) 96 | { 97 | if(State->Error) return(0); 98 | 99 | // 100 | // Padding digest to required number of bits 101 | // 102 | 103 | State->Buf[State->Ptr++] = 0x80; 104 | 105 | if(State->Ptr>56) 106 | { 107 | while(State->PtrBuf)) 108 | State->Buf[State->Ptr++] = 0; 109 | 110 | ProcessSHA1(State); 111 | } 112 | 113 | while(State->Ptr<56) 114 | State->Buf[State->Ptr++] = 0; 115 | 116 | // Store the message length as the last 8 octets 117 | State->Buf[56] = (State->LenH>>24) & 0xFF; 118 | State->Buf[57] = (State->LenH>>16) & 0xFF; 119 | State->Buf[58] = (State->LenH>>8) & 0xFF; 120 | State->Buf[59] = (State->LenH) & 0xFF; 121 | State->Buf[60] = (State->LenL>>24) & 0xFF; 122 | State->Buf[61] = (State->LenL>>16) & 0xFF; 123 | State->Buf[62] = (State->LenL>>8) & 0xFF; 124 | State->Buf[63] = (State->LenL) & 0xFF; 125 | 126 | ProcessSHA1(State); 127 | 128 | // Done 129 | State->Done = 1; 130 | return(1); 131 | } 132 | 133 | int InputSHA1(SHA1 *State,const unsigned char *Data,unsigned int Size) 134 | { 135 | if(State->Done || State->Error) 136 | { 137 | State->Error = 1; 138 | return(0); 139 | } 140 | 141 | if(!Size) return(1); 142 | 143 | while(!State->Error && Size--) 144 | { 145 | State->Buf[State->Ptr++] = *Data++ & 0xFF; 146 | State->LenL = (State->LenL+8) & 0xFFFFFFFF; 147 | 148 | if(!State->LenL) 149 | { 150 | State->LenH = (State->LenH+1)&0xFFFFFFFF; 151 | if(!State->LenH) 152 | { 153 | State->Error = 1; 154 | return(0); 155 | } 156 | } 157 | 158 | if(State->Ptr==sizeof(State->Buf)) ProcessSHA1(State); 159 | } 160 | 161 | return(1); 162 | } 163 | -------------------------------------------------------------------------------- /source/EMULIB/SHA1.h: -------------------------------------------------------------------------------- 1 | #ifndef SHA1_H 2 | #define SHA1_H 3 | 4 | typedef struct 5 | { 6 | unsigned int Done; 7 | unsigned int Error; 8 | unsigned int LenL,LenH; 9 | unsigned int Ptr; 10 | unsigned char Buf[64]; 11 | unsigned int Msg[5]; 12 | } SHA1; 13 | 14 | void ResetSHA1(SHA1 *State); 15 | int ComputeSHA1(SHA1 *State); 16 | int InputSHA1(SHA1 *State,const unsigned char *Data,unsigned int Size); 17 | 18 | #endif /* SHA1_H */ 19 | -------------------------------------------------------------------------------- /source/EMULIB/Sound.h: -------------------------------------------------------------------------------- 1 | /** EMULib Emulation Library *********************************/ 2 | /** **/ 3 | /** Sound.h **/ 4 | /** **/ 5 | /** This file defines standard sound generation API and **/ 6 | /** functions needed to log soundtrack into a MIDI file. **/ 7 | /** See Sound.c and the sound drivers for the code. **/ 8 | /** **/ 9 | /** Copyright (C) Marat Fayzullin 1996-2016 **/ 10 | /** You are not allowed to distribute this software **/ 11 | /** commercially. Please, notify me, if you make any **/ 12 | /** changes to this file. **/ 13 | /*************************************************************/ 14 | #ifndef SOUND_H 15 | #define SOUND_H 16 | 17 | #include "EMULib.h" 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /* SetSound() arguments: */ 24 | #define SND_MELODIC 0 /* Melodic sound (default) */ 25 | #define SND_RECTANGLE 0 /* Rectangular wave */ 26 | #define SND_TRIANGLE 1 /* Triangular wave (1/2 rect.)*/ 27 | #define SND_NOISE 2 /* White noise */ 28 | #define SND_PERIODIC 3 /* Periodic noise (not im-ed) */ 29 | #define SND_WAVE 4 /* Wave sound set by SetWave()*/ 30 | #define SND_MIDI 0x100 /* MIDI instrument (ORable) */ 31 | 32 | /* Drum() arguments: */ 33 | #define DRM_CLICK 0 /* Click (default) */ 34 | #define DRM_MIDI 0x100 /* MIDI drum (ORable) */ 35 | 36 | /* MIDI characteristics: */ 37 | #define MIDI_CHANNELS 16 /* Number of MIDI channels */ 38 | #define MIDI_MINFREQ 9 /* Min MIDI frequency (Hz) */ 39 | #define MIDI_MAXFREQ 12285 /* Max MIDI frequency (Hz) */ 40 | #define MIDI_DIVISIONS 1000 /* Number of ticks per second */ 41 | 42 | /* MIDILogging() arguments: */ 43 | #define MIDI_OFF 0 /* Turn MIDI logging off */ 44 | #define MIDI_ON 1 /* Turn MIDI logging on */ 45 | #define MIDI_TOGGLE 2 /* Toggle MIDI logging */ 46 | #define MIDI_QUERY 3 /* Query MIDI logging status */ 47 | 48 | /** InitSound() **********************************************/ 49 | /** Initialize RenderSound() with given parameters. **/ 50 | /*************************************************************/ 51 | unsigned int InitSound(unsigned int Rate,unsigned int Latency); 52 | 53 | /** TrashSound() *********************************************/ 54 | /** Shut down RenderSound() driver. **/ 55 | /*************************************************************/ 56 | void TrashSound(void); 57 | 58 | /** RenderAudio() ********************************************/ 59 | /** Render given number of melodic sound samples into an **/ 60 | /** integer buffer for mixing. **/ 61 | /*************************************************************/ 62 | void RenderAudio(int *Wave,unsigned int Samples); 63 | 64 | /** PlayAudio() **********************************************/ 65 | /** Normalize and play given number of samples from the mix **/ 66 | /** buffer. Returns the number of samples actually played. **/ 67 | /*************************************************************/ 68 | unsigned int PlayAudio(int *Wave,unsigned int Samples); 69 | 70 | /** RenderAndPlayAudio() *************************************/ 71 | /** Render and play a given number of samples. Returns the **/ 72 | /** number of samples actually played. **/ 73 | /*************************************************************/ 74 | unsigned int RenderAndPlayAudio(unsigned int Samples); 75 | 76 | /** Sound() **************************************************/ 77 | /** Generate sound of given frequency (Hz) and volume **/ 78 | /** (0..255) via given channel. Setting Freq=0 or Volume=0 **/ 79 | /** turns sound off. **/ 80 | /*************************************************************/ 81 | void Sound(int Channel,int Freq,int Volume); 82 | 83 | /** Drum() ***************************************************/ 84 | /** Hit a drum of given type with given force (0..255). **/ 85 | /** MIDI drums can be used by ORing their numbers with **/ 86 | /** SND_MIDI. **/ 87 | /*************************************************************/ 88 | void Drum(int Type,int Force); 89 | 90 | /** SetSound() ***********************************************/ 91 | /** Set sound type at a given channel. MIDI instruments can **/ 92 | /** be set directly by ORing their numbers with SND_MIDI. **/ 93 | /*************************************************************/ 94 | void SetSound(int Channel,int NewType); 95 | 96 | /** SetChannels() ********************************************/ 97 | /** Set master volume (0..255) and switch channels on/off. **/ 98 | /** Each channel N has corresponding bit 2^N in Switch. Set **/ 99 | /** or reset this bit to turn the channel on or off. **/ 100 | /*************************************************************/ 101 | void SetChannels(int Volume,int Switch); 102 | 103 | /** SetNoise() ***********************************************/ 104 | /** Initialize random noise generator to the given Seed and **/ 105 | /** then take random output from OUTBit and XOR it with **/ 106 | /** XORBit. **/ 107 | /*************************************************************/ 108 | void SetNoise(int Seed,int OUTBit,int XORBit); 109 | 110 | /** SetWave() ************************************************/ 111 | /** Set waveform for a given channel. The channel will be **/ 112 | /** marked with sound type SND_WAVE. Set Rate=0 if you want **/ 113 | /** waveform to be an instrument or set it to the waveform **/ 114 | /** own playback rate. **/ 115 | /*************************************************************/ 116 | void SetWave(int Channel,const signed char *Data,int Length,int Rate); 117 | 118 | /** GetWave() ************************************************/ 119 | /** Get current read position for the buffer set with the **/ 120 | /** SetWave() call. Returns 0 if no buffer has been set, or **/ 121 | /** if there is no playrate set (i.e. wave is instrument). **/ 122 | /*************************************************************/ 123 | const signed char *GetWave(int Channel); 124 | 125 | /** GetSndRate() *********************************************/ 126 | /** Get current sampling rate used for synthesis. **/ 127 | /*************************************************************/ 128 | unsigned int GetSndRate(void); 129 | 130 | /** InitMIDI() ***********************************************/ 131 | /** Initialize soundtrack logging into MIDI file FileName. **/ 132 | /** Repeated calls to InitMIDI() will close current MIDI **/ 133 | /** file and continue logging into a new one. **/ 134 | /*************************************************************/ 135 | void InitMIDI(const char *FileName); 136 | 137 | /** TrashMIDI() **********************************************/ 138 | /** Finish logging soundtrack and close the MIDI file. **/ 139 | /*************************************************************/ 140 | void TrashMIDI(void); 141 | 142 | /** MIDILogging() ********************************************/ 143 | /** Turn soundtrack logging on/off and return its current **/ 144 | /** status. Possible values of Switch are MIDI_OFF (turn **/ 145 | /** logging off), MIDI_ON (turn logging on), MIDI_TOGGLE **/ 146 | /** (toggle logging), and MIDI_QUERY (just return current **/ 147 | /** state of logging). **/ 148 | /*************************************************************/ 149 | int MIDILogging(int Switch); 150 | 151 | /** MIDITicks() **********************************************/ 152 | /** Log N 1ms MIDI ticks. **/ 153 | /*************************************************************/ 154 | void MIDITicks(int N); 155 | 156 | #if !defined(MSDOS) & !defined(UNIX) &!defined(ORBIS) & !defined(MAEMO) & !defined(WINDOWS) & !defined(S60) & !defined(UIQ) && !defined(ANDROID) 157 | #define SND_CHANNELS MIDI_CHANNELS /* Default number */ 158 | #endif 159 | 160 | /** SndDriver ************************************************/ 161 | /** Each sound driver should fill this structure with **/ 162 | /** pointers to hardware-dependent handlers. This has to be **/ 163 | /** done inside the InitSound() function. **/ 164 | /*************************************************************/ 165 | struct SndDriverStruct 166 | { 167 | void (*SetSound)(int Channel,int NewType); 168 | void (*Drum)(int Type,int Force); 169 | void (*SetChannels)(int Volume,int Switch); 170 | void (*Sound)(int Channel,int NewFreq,int NewVolume); 171 | void (*SetWave)(int Channel,const signed char *Data,int Length,int Freq); 172 | const signed char *(*GetWave)(int Channel); 173 | }; 174 | extern struct SndDriverStruct SndDriver; 175 | 176 | #ifdef __cplusplus 177 | } 178 | #endif 179 | #endif /* SOUND_H */ 180 | -------------------------------------------------------------------------------- /source/EMULIB/WD1793.h: -------------------------------------------------------------------------------- 1 | /** EMULib Emulation Library *********************************/ 2 | /** **/ 3 | /** WD1793.h **/ 4 | /** **/ 5 | /** This file contains emulation for the WD1793/2793 disk **/ 6 | /** controller produced by Western Digital. See WD1793.c **/ 7 | /** for implementation. **/ 8 | /** **/ 9 | /** Copyright (C) Marat Fayzullin 2005-2016 **/ 10 | /** You are not allowed to distribute this software **/ 11 | /** commercially. Please, notify me, if you make any **/ 12 | /** changes to this file. **/ 13 | /*************************************************************/ 14 | #ifndef WD1793_H 15 | #define WD1793_H 16 | 17 | #include "FDIDisk.h" 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #define WD1793_KEEP 0 24 | #define WD1793_INIT 1 25 | #define WD1793_EJECT 2 26 | 27 | #define WD1793_COMMAND 0 28 | #define WD1793_STATUS 0 29 | #define WD1793_TRACK 1 30 | #define WD1793_SECTOR 2 31 | #define WD1793_DATA 3 32 | #define WD1793_SYSTEM 4 33 | #define WD1793_READY 4 34 | 35 | #define WD1793_IRQ 0x80 36 | #define WD1793_DRQ 0x40 37 | 38 | /* Common status bits: */ 39 | #define F_BUSY 0x01 /* Controller is executing a command */ 40 | #define F_READONLY 0x40 /* The disk is write-protected */ 41 | #define F_NOTREADY 0x80 /* The drive is not ready */ 42 | 43 | /* Type-1 command status: */ 44 | #define F_INDEX 0x02 /* Index mark detected */ 45 | #define F_TRACK0 0x04 /* Head positioned at track #0 */ 46 | #define F_CRCERR 0x08 /* CRC error in ID field */ 47 | #define F_SEEKERR 0x10 /* Seek error, track not verified */ 48 | #define F_HEADLOAD 0x20 /* Head loaded */ 49 | 50 | /* Type-2 and Type-3 command status: */ 51 | #define F_DRQ 0x02 /* Data request pending */ 52 | #define F_LOSTDATA 0x04 /* Data has been lost (missed DRQ) */ 53 | #define F_ERRCODE 0x18 /* Error code bits: */ 54 | #define F_BADDATA 0x08 /* 1 = bad data CRC */ 55 | #define F_NOTFOUND 0x10 /* 2 = sector not found */ 56 | #define F_BADID 0x18 /* 3 = bad ID field CRC */ 57 | #define F_DELETED 0x20 /* Deleted data mark (when reading) */ 58 | #define F_WRFAULT 0x20 /* Write fault (when writing) */ 59 | 60 | #define C_DELMARK 0x01 61 | #define C_SIDECOMP 0x02 62 | #define C_STEPRATE 0x03 63 | #define C_VERIFY 0x04 64 | #define C_WAIT15MS 0x04 65 | #define C_LOADHEAD 0x08 66 | #define C_SIDE 0x08 67 | #define C_IRQ 0x08 68 | #define C_SETTRACK 0x10 69 | #define C_MULTIREC 0x10 70 | 71 | #define S_DRIVE 0x03 72 | #define S_RESET 0x04 73 | #define S_HALT 0x08 74 | #define S_SIDE 0x10 75 | #define S_DENSITY 0x20 76 | 77 | #ifndef BYTE_TYPE_DEFINED 78 | #define BYTE_TYPE_DEFINED 79 | typedef unsigned char byte; 80 | #endif 81 | 82 | typedef struct 83 | { 84 | FDIDisk *Disk[4]; /* Disk images */ 85 | 86 | byte R[5]; /* Registers */ 87 | byte Drive; /* Current disk # */ 88 | byte Side; /* Current side # */ 89 | byte Track[4]; /* Current track # */ 90 | byte LastS; /* Last STEP direction */ 91 | byte IRQ; /* 0x80: IRQ pending, 0x40: DRQ pending */ 92 | byte Wait; /* Expiration counter */ 93 | byte Cmd; /* Last command */ 94 | 95 | int WRLength; /* Data left to write */ 96 | int RDLength; /* Data left to read */ 97 | byte *Ptr; /* Pointer to data */ 98 | 99 | byte Verbose; /* 1: Print debugging messages */ 100 | } WD1793; 101 | 102 | /** Reset1793() **********************************************/ 103 | /** Reset WD1793. When Disks=WD1793_INIT, also initialize **/ 104 | /** disks. When Disks=WD1793_EJECT, eject inserted disks, **/ 105 | /** freeing memory. **/ 106 | /*************************************************************/ 107 | void Reset1793(register WD1793 *D,FDIDisk *Disks,register byte Eject); 108 | 109 | /** Read1793() ***********************************************/ 110 | /** Read value from a WD1793 register A. Returns read data **/ 111 | /** on success or 0xFF on failure (bad register address). **/ 112 | /*************************************************************/ 113 | byte Read1793(register WD1793 *D,register byte A); 114 | 115 | /** Write1793() **********************************************/ 116 | /** Write value V into WD1793 register A. Returns DRQ/IRQ **/ 117 | /** values. **/ 118 | /*************************************************************/ 119 | byte Write1793(register WD1793 *D,register byte A,register byte V); 120 | 121 | #ifdef __cplusplus 122 | } 123 | #endif 124 | #endif /* WD1793_H */ 125 | -------------------------------------------------------------------------------- /source/EMULIB/YM2413.h: -------------------------------------------------------------------------------- 1 | /** EMULib Emulation Library *********************************/ 2 | /** **/ 3 | /** YM2413.h **/ 4 | /** **/ 5 | /** This file contains emulation for the OPLL sound chip **/ 6 | /** produced by Yamaha (also see OPL2, OPL3, OPL4 chips). **/ 7 | /** See YM2413.h for the code. **/ 8 | /** **/ 9 | /** Copyright (C) Marat Fayzullin 1996-2016 **/ 10 | /** You are not allowed to distribute this software **/ 11 | /** commercially. Please, notify me, if you make any **/ 12 | /** changes to this file. **/ 13 | /*************************************************************/ 14 | #ifndef YM2413_H 15 | #define YM2413_H 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | #define YM2413_BASE 3125 /* Base frequency for OPLL */ 21 | #define YM2413_CHANNELS 9 /* 9 melodic channels */ 22 | 23 | #define YM2413_ASYNC 0 /* Asynchronous emulation */ 24 | #define YM2413_SYNC 1 /* Synchronous emulation mode */ 25 | #define YM2413_FLUSH 2 /* Flush buffers only */ 26 | 27 | #define YM2413_DRUMS(D) ((D)->R[0x0E]&0x20) 28 | 29 | #ifndef BYTE_TYPE_DEFINED 30 | #define BYTE_TYPE_DEFINED 31 | typedef unsigned char byte; 32 | #endif 33 | 34 | /** YM2413 ***************************************************/ 35 | /** This data structure stores OPLL state. **/ 36 | /*************************************************************/ 37 | typedef struct 38 | { 39 | byte R[64]; /* OPLL register contents */ 40 | int Freq[YM2413_CHANNELS]; /* Frequencies (0 for off) */ 41 | int Volume[YM2413_CHANNELS]; /* Volumes (0..255) */ 42 | int First; /* First used Sound() channel */ 43 | int Changed; /* Bitmap of changed channels */ 44 | int PChanged; /* Bitmap of changed patches */ 45 | int DChanged; /* Bitmap of changed drums */ 46 | byte Sync; /* YM2413_SYNC/YM2413_ASYNC */ 47 | byte Latch; /* Latch for the register num */ 48 | } YM2413; 49 | 50 | /** Reset2413() **********************************************/ 51 | /** Reset the sound chip and use sound channels from the **/ 52 | /** one given in First. **/ 53 | /*************************************************************/ 54 | void Reset2413(register YM2413 *D,int First); 55 | 56 | /** WrCtrl2413() *********************************************/ 57 | /** Write a value V to the OPLL Control Port. **/ 58 | /*************************************************************/ 59 | void WrCtrl2413(register YM2413 *D,register byte V); 60 | 61 | /** WrData2413() *********************************************/ 62 | /** Write a value V to the OPLL Data Port. **/ 63 | /*************************************************************/ 64 | void WrData2413(register YM2413 *D,register byte V); 65 | 66 | /** Write2413() **********************************************/ 67 | /** Call this function to output a value V into given OPLL **/ 68 | /** register R. **/ 69 | /*************************************************************/ 70 | void Write2413(register YM2413 *D,register byte R,register byte V); 71 | 72 | /** Sync2413() ***********************************************/ 73 | /** Flush all accumulated changes by issuing Sound() calls **/ 74 | /** and set the synchronization on/off. The second argument **/ 75 | /** should be YM2413_SYNC/YM2413_ASYNC to set/reset sync, **/ 76 | /** or YM2413_FLUSH to leave sync mode as it is. **/ 77 | /*************************************************************/ 78 | void Sync2413(register YM2413 *D,register byte Sync); 79 | 80 | #ifdef __cplusplus 81 | } 82 | #endif 83 | #endif /* YM2413_H */ 84 | -------------------------------------------------------------------------------- /source/Z80/CodesED.h: -------------------------------------------------------------------------------- 1 | /** Z80: portable Z80 emulator *******************************/ 2 | /** **/ 3 | /** CodesED.h **/ 4 | /** **/ 5 | /** This file contains implementation for the ED table of **/ 6 | /** Z80 commands. It is included from Z80.c. **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 1994-2017 **/ 9 | /** You are not allowed to distribute this software **/ 10 | /** commercially. Please, notify me, if you make any **/ 11 | /** changes to this file. **/ 12 | /*************************************************************/ 13 | 14 | /** This is a special patch for emulating BIOS calls: ********/ 15 | case DB_FE: PatchZ80(R);break; 16 | /*************************************************************/ 17 | 18 | case ADC_HL_BC: M_ADCW(BC);break; 19 | case ADC_HL_DE: M_ADCW(DE);break; 20 | case ADC_HL_HL: M_ADCW(HL);break; 21 | case ADC_HL_SP: M_ADCW(SP);break; 22 | 23 | case SBC_HL_BC: M_SBCW(BC);break; 24 | case SBC_HL_DE: M_SBCW(DE);break; 25 | case SBC_HL_HL: M_SBCW(HL);break; 26 | case SBC_HL_SP: M_SBCW(SP);break; 27 | 28 | case LD_xWORDe_HL: 29 | J.B.l=OpZ80(R->PC.W++); 30 | J.B.h=OpZ80(R->PC.W++); 31 | WrZ80(J.W++,R->HL.B.l); 32 | WrZ80(J.W,R->HL.B.h); 33 | break; 34 | case LD_xWORDe_DE: 35 | J.B.l=OpZ80(R->PC.W++); 36 | J.B.h=OpZ80(R->PC.W++); 37 | WrZ80(J.W++,R->DE.B.l); 38 | WrZ80(J.W,R->DE.B.h); 39 | break; 40 | case LD_xWORDe_BC: 41 | J.B.l=OpZ80(R->PC.W++); 42 | J.B.h=OpZ80(R->PC.W++); 43 | WrZ80(J.W++,R->BC.B.l); 44 | WrZ80(J.W,R->BC.B.h); 45 | break; 46 | case LD_xWORDe_SP: 47 | J.B.l=OpZ80(R->PC.W++); 48 | J.B.h=OpZ80(R->PC.W++); 49 | WrZ80(J.W++,R->SP.B.l); 50 | WrZ80(J.W,R->SP.B.h); 51 | break; 52 | 53 | case LD_HL_xWORDe: 54 | J.B.l=OpZ80(R->PC.W++); 55 | J.B.h=OpZ80(R->PC.W++); 56 | R->HL.B.l=RdZ80(J.W++); 57 | R->HL.B.h=RdZ80(J.W); 58 | break; 59 | case LD_DE_xWORDe: 60 | J.B.l=OpZ80(R->PC.W++); 61 | J.B.h=OpZ80(R->PC.W++); 62 | R->DE.B.l=RdZ80(J.W++); 63 | R->DE.B.h=RdZ80(J.W); 64 | break; 65 | case LD_BC_xWORDe: 66 | J.B.l=OpZ80(R->PC.W++); 67 | J.B.h=OpZ80(R->PC.W++); 68 | R->BC.B.l=RdZ80(J.W++); 69 | R->BC.B.h=RdZ80(J.W); 70 | break; 71 | case LD_SP_xWORDe: 72 | J.B.l=OpZ80(R->PC.W++); 73 | J.B.h=OpZ80(R->PC.W++); 74 | R->SP.B.l=RdZ80(J.W++); 75 | R->SP.B.h=RdZ80(J.W); 76 | break; 77 | 78 | case RRD: 79 | I=RdZ80(R->HL.W); 80 | J.B.l=(I>>4)|(R->AF.B.h<<4); 81 | WrZ80(R->HL.W,J.B.l); 82 | R->AF.B.h=(I&0x0F)|(R->AF.B.h&0xF0); 83 | R->AF.B.l=PZSTable[R->AF.B.h]|(R->AF.B.l&C_FLAG); 84 | break; 85 | case RLD: 86 | I=RdZ80(R->HL.W); 87 | J.B.l=(I<<4)|(R->AF.B.h&0x0F); 88 | WrZ80(R->HL.W,J.B.l); 89 | R->AF.B.h=(I>>4)|(R->AF.B.h&0xF0); 90 | R->AF.B.l=PZSTable[R->AF.B.h]|(R->AF.B.l&C_FLAG); 91 | break; 92 | 93 | case LD_A_I: 94 | R->AF.B.h=R->I; 95 | R->AF.B.l=(R->AF.B.l&C_FLAG)|(R->IFF&IFF_2? P_FLAG:0)|ZSTable[R->AF.B.h]; 96 | break; 97 | 98 | case LD_A_R: 99 | R->AF.B.h=R->R; 100 | R->AF.B.l=(R->AF.B.l&C_FLAG)|(R->IFF&IFF_2? P_FLAG:0)|ZSTable[R->AF.B.h]; 101 | break; 102 | 103 | case LD_I_A: R->I=R->AF.B.h;break; 104 | case LD_R_A: R->R=R->AF.B.h;break; 105 | 106 | case IM_0: R->IFF&=~(IFF_IM1|IFF_IM2);break; 107 | case IM_1: R->IFF=(R->IFF&~IFF_IM2)|IFF_IM1;break; 108 | case IM_2: R->IFF=(R->IFF&~IFF_IM1)|IFF_IM2;break; 109 | 110 | case RETI: 111 | case RETN: if(R->IFF&IFF_2) R->IFF|=IFF_1; else R->IFF&=~IFF_1; 112 | M_RET;break; 113 | 114 | case NEG: I=R->AF.B.h;R->AF.B.h=0;M_SUB(I);break; 115 | 116 | case IN_B_xC: M_IN(R->BC.B.h);break; 117 | case IN_C_xC: M_IN(R->BC.B.l);break; 118 | case IN_D_xC: M_IN(R->DE.B.h);break; 119 | case IN_E_xC: M_IN(R->DE.B.l);break; 120 | case IN_H_xC: M_IN(R->HL.B.h);break; 121 | case IN_L_xC: M_IN(R->HL.B.l);break; 122 | case IN_A_xC: M_IN(R->AF.B.h);break; 123 | case IN_F_xC: M_IN(J.B.l);break; 124 | 125 | case OUT_xC_B: OutZ80(R->BC.W,R->BC.B.h);break; 126 | case OUT_xC_C: OutZ80(R->BC.W,R->BC.B.l);break; 127 | case OUT_xC_D: OutZ80(R->BC.W,R->DE.B.h);break; 128 | case OUT_xC_E: OutZ80(R->BC.W,R->DE.B.l);break; 129 | case OUT_xC_H: OutZ80(R->BC.W,R->HL.B.h);break; 130 | case OUT_xC_L: OutZ80(R->BC.W,R->HL.B.l);break; 131 | case OUT_xC_A: OutZ80(R->BC.W,R->AF.B.h);break; 132 | case OUT_xC_F: OutZ80(R->BC.W,0);break; 133 | 134 | case INI: 135 | WrZ80(R->HL.W++,InZ80(R->BC.W)); 136 | --R->BC.B.h; 137 | R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG); 138 | break; 139 | 140 | case INIR: 141 | WrZ80(R->HL.W++,InZ80(R->BC.W)); 142 | if(--R->BC.B.h) { R->AF.B.l=N_FLAG;R->ICount-=21;R->PC.W-=2; } 143 | else { R->AF.B.l=Z_FLAG|N_FLAG;R->ICount-=16; } 144 | break; 145 | 146 | case IND: 147 | WrZ80(R->HL.W--,InZ80(R->BC.W)); 148 | --R->BC.B.h; 149 | R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG); 150 | break; 151 | 152 | case INDR: 153 | WrZ80(R->HL.W--,InZ80(R->BC.W)); 154 | if(!--R->BC.B.h) { R->AF.B.l=N_FLAG;R->ICount-=21;R->PC.W-=2; } 155 | else { R->AF.B.l=Z_FLAG|N_FLAG;R->ICount-=16; } 156 | break; 157 | 158 | case OUTI: 159 | --R->BC.B.h; 160 | I=RdZ80(R->HL.W++); 161 | OutZ80(R->BC.W,I); 162 | R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG)|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0); 163 | break; 164 | 165 | case OTIR: 166 | --R->BC.B.h; 167 | I=RdZ80(R->HL.W++); 168 | OutZ80(R->BC.W,I); 169 | if(R->BC.B.h) 170 | { 171 | R->AF.B.l=N_FLAG|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0); 172 | R->ICount-=21; 173 | R->PC.W-=2; 174 | } 175 | else 176 | { 177 | R->AF.B.l=Z_FLAG|N_FLAG|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0); 178 | R->ICount-=16; 179 | } 180 | break; 181 | 182 | case OUTD: 183 | --R->BC.B.h; 184 | I=RdZ80(R->HL.W--); 185 | OutZ80(R->BC.W,I); 186 | R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG)|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0); 187 | break; 188 | 189 | case OTDR: 190 | --R->BC.B.h; 191 | I=RdZ80(R->HL.W--); 192 | OutZ80(R->BC.W,I); 193 | if(R->BC.B.h) 194 | { 195 | R->AF.B.l=N_FLAG|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0); 196 | R->ICount-=21; 197 | R->PC.W-=2; 198 | } 199 | else 200 | { 201 | R->AF.B.l=Z_FLAG|N_FLAG|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0); 202 | R->ICount-=16; 203 | } 204 | break; 205 | 206 | case LDI: 207 | WrZ80(R->DE.W++,RdZ80(R->HL.W++)); 208 | --R->BC.W; 209 | R->AF.B.l=(R->AF.B.l&~(N_FLAG|H_FLAG|P_FLAG))|(R->BC.W? P_FLAG:0); 210 | break; 211 | 212 | case LDIR: 213 | WrZ80(R->DE.W++,RdZ80(R->HL.W++)); 214 | if(--R->BC.W) 215 | { 216 | R->AF.B.l=(R->AF.B.l&~(H_FLAG|P_FLAG))|N_FLAG; 217 | R->ICount-=21; 218 | R->PC.W-=2; 219 | } 220 | else 221 | { 222 | R->AF.B.l&=~(N_FLAG|H_FLAG|P_FLAG); 223 | R->ICount-=16; 224 | } 225 | break; 226 | 227 | case LDD: 228 | WrZ80(R->DE.W--,RdZ80(R->HL.W--)); 229 | --R->BC.W; 230 | R->AF.B.l=(R->AF.B.l&~(N_FLAG|H_FLAG|P_FLAG))|(R->BC.W? P_FLAG:0); 231 | break; 232 | 233 | case LDDR: 234 | WrZ80(R->DE.W--,RdZ80(R->HL.W--)); 235 | R->AF.B.l&=~(N_FLAG|H_FLAG|P_FLAG); 236 | if(--R->BC.W) 237 | { 238 | R->AF.B.l=(R->AF.B.l&~(H_FLAG|P_FLAG))|N_FLAG; 239 | R->ICount-=21; 240 | R->PC.W-=2; 241 | } 242 | else 243 | { 244 | R->AF.B.l&=~(N_FLAG|H_FLAG|P_FLAG); 245 | R->ICount-=16; 246 | } 247 | break; 248 | 249 | case CPI: 250 | I=RdZ80(R->HL.W++); 251 | J.B.l=R->AF.B.h-I; 252 | --R->BC.W; 253 | R->AF.B.l = 254 | N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]| 255 | ((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0); 256 | break; 257 | 258 | case CPIR: 259 | I=RdZ80(R->HL.W++); 260 | J.B.l=R->AF.B.h-I; 261 | if(--R->BC.W&&J.B.l) { R->ICount-=21;R->PC.W-=2; } else R->ICount-=16; 262 | R->AF.B.l = 263 | N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]| 264 | ((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0); 265 | break; 266 | 267 | case CPD: 268 | I=RdZ80(R->HL.W--); 269 | J.B.l=R->AF.B.h-I; 270 | --R->BC.W; 271 | R->AF.B.l = 272 | N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]| 273 | ((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0); 274 | break; 275 | 276 | case CPDR: 277 | I=RdZ80(R->HL.W--); 278 | J.B.l=R->AF.B.h-I; 279 | if(--R->BC.W&&J.B.l) { R->ICount-=21;R->PC.W-=2; } else R->ICount-=16; 280 | R->AF.B.l = 281 | N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]| 282 | ((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0); 283 | break; 284 | -------------------------------------------------------------------------------- /source/Z80/CodesXCB.h: -------------------------------------------------------------------------------- 1 | /** Z80: portable Z80 emulator *******************************/ 2 | /** **/ 3 | /** CodesXCB.h **/ 4 | /** **/ 5 | /** This file contains implementation for FD/DD-CB tables **/ 6 | /** of Z80 commands. It is included from Z80.c. **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 1994-2017 **/ 9 | /** You are not allowed to distribute this software **/ 10 | /** commercially. Please, notify me, if you make any **/ 11 | /** changes to this file. **/ 12 | /*************************************************************/ 13 | 14 | case RLC_xHL: I=RdZ80(J.W);M_RLC(I);WrZ80(J.W,I);break; 15 | case RRC_xHL: I=RdZ80(J.W);M_RRC(I);WrZ80(J.W,I);break; 16 | case RL_xHL: I=RdZ80(J.W);M_RL(I);WrZ80(J.W,I);break; 17 | case RR_xHL: I=RdZ80(J.W);M_RR(I);WrZ80(J.W,I);break; 18 | case SLA_xHL: I=RdZ80(J.W);M_SLA(I);WrZ80(J.W,I);break; 19 | case SRA_xHL: I=RdZ80(J.W);M_SRA(I);WrZ80(J.W,I);break; 20 | case SLL_xHL: I=RdZ80(J.W);M_SLL(I);WrZ80(J.W,I);break; 21 | case SRL_xHL: I=RdZ80(J.W);M_SRL(I);WrZ80(J.W,I);break; 22 | 23 | case BIT0_B: case BIT0_C: case BIT0_D: case BIT0_E: 24 | case BIT0_H: case BIT0_L: case BIT0_A: 25 | case BIT0_xHL: I=RdZ80(J.W);M_BIT(0,I);break; 26 | case BIT1_B: case BIT1_C: case BIT1_D: case BIT1_E: 27 | case BIT1_H: case BIT1_L: case BIT1_A: 28 | case BIT1_xHL: I=RdZ80(J.W);M_BIT(1,I);break; 29 | case BIT2_B: case BIT2_C: case BIT2_D: case BIT2_E: 30 | case BIT2_H: case BIT2_L: case BIT2_A: 31 | case BIT2_xHL: I=RdZ80(J.W);M_BIT(2,I);break; 32 | case BIT3_B: case BIT3_C: case BIT3_D: case BIT3_E: 33 | case BIT3_H: case BIT3_L: case BIT3_A: 34 | case BIT3_xHL: I=RdZ80(J.W);M_BIT(3,I);break; 35 | case BIT4_B: case BIT4_C: case BIT4_D: case BIT4_E: 36 | case BIT4_H: case BIT4_L: case BIT4_A: 37 | case BIT4_xHL: I=RdZ80(J.W);M_BIT(4,I);break; 38 | case BIT5_B: case BIT5_C: case BIT5_D: case BIT5_E: 39 | case BIT5_H: case BIT5_L: case BIT5_A: 40 | case BIT5_xHL: I=RdZ80(J.W);M_BIT(5,I);break; 41 | case BIT6_B: case BIT6_C: case BIT6_D: case BIT6_E: 42 | case BIT6_H: case BIT6_L: case BIT6_A: 43 | case BIT6_xHL: I=RdZ80(J.W);M_BIT(6,I);break; 44 | case BIT7_B: case BIT7_C: case BIT7_D: case BIT7_E: 45 | case BIT7_H: case BIT7_L: case BIT7_A: 46 | case BIT7_xHL: I=RdZ80(J.W);M_BIT(7,I);break; 47 | 48 | case RES0_xHL: I=RdZ80(J.W);M_RES(0,I);WrZ80(J.W,I);break; 49 | case RES1_xHL: I=RdZ80(J.W);M_RES(1,I);WrZ80(J.W,I);break; 50 | case RES2_xHL: I=RdZ80(J.W);M_RES(2,I);WrZ80(J.W,I);break; 51 | case RES3_xHL: I=RdZ80(J.W);M_RES(3,I);WrZ80(J.W,I);break; 52 | case RES4_xHL: I=RdZ80(J.W);M_RES(4,I);WrZ80(J.W,I);break; 53 | case RES5_xHL: I=RdZ80(J.W);M_RES(5,I);WrZ80(J.W,I);break; 54 | case RES6_xHL: I=RdZ80(J.W);M_RES(6,I);WrZ80(J.W,I);break; 55 | case RES7_xHL: I=RdZ80(J.W);M_RES(7,I);WrZ80(J.W,I);break; 56 | 57 | case SET0_xHL: I=RdZ80(J.W);M_SET(0,I);WrZ80(J.W,I);break; 58 | case SET1_xHL: I=RdZ80(J.W);M_SET(1,I);WrZ80(J.W,I);break; 59 | case SET2_xHL: I=RdZ80(J.W);M_SET(2,I);WrZ80(J.W,I);break; 60 | case SET3_xHL: I=RdZ80(J.W);M_SET(3,I);WrZ80(J.W,I);break; 61 | case SET4_xHL: I=RdZ80(J.W);M_SET(4,I);WrZ80(J.W,I);break; 62 | case SET5_xHL: I=RdZ80(J.W);M_SET(5,I);WrZ80(J.W,I);break; 63 | case SET6_xHL: I=RdZ80(J.W);M_SET(6,I);WrZ80(J.W,I);break; 64 | case SET7_xHL: I=RdZ80(J.W);M_SET(7,I);WrZ80(J.W,I);break; 65 | -------------------------------------------------------------------------------- /source/Z80/Z80.h: -------------------------------------------------------------------------------- 1 | /** Z80: portable Z80 emulator *******************************/ 2 | /** **/ 3 | /** Z80.h **/ 4 | /** **/ 5 | /** This file contains declarations relevant to emulation **/ 6 | /** of Z80 CPU. **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 1994-2017 **/ 9 | /** You are not allowed to distribute this software **/ 10 | /** commercially. Please, notify me, if you make any **/ 11 | /** changes to this file. **/ 12 | /*************************************************************/ 13 | #ifndef Z80_H 14 | #define Z80_H 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | /* Compilation options: */ 21 | /* #define DEBUG */ /* Compile debugging version */ 22 | /* #define LSB_FIRST */ /* Compile for low-endian CPU */ 23 | /* #define MSB_FIRST */ /* Compile for hi-endian CPU */ 24 | 25 | /* LoopZ80() may return: */ 26 | #define INT_RST00 0x00C7 /* RST 00h */ 27 | #define INT_RST08 0x00CF /* RST 08h */ 28 | #define INT_RST10 0x00D7 /* RST 10h */ 29 | #define INT_RST18 0x00DF /* RST 18h */ 30 | #define INT_RST20 0x00E7 /* RST 20h */ 31 | #define INT_RST28 0x00EF /* RST 28h */ 32 | #define INT_RST30 0x00F7 /* RST 30h */ 33 | #define INT_RST38 0x00FF /* RST 38h */ 34 | #define INT_IRQ INT_RST38 /* Default IRQ opcode is FFh */ 35 | #define INT_NMI 0xFFFD /* Non-maskable interrupt */ 36 | #define INT_NONE 0xFFFF /* No interrupt required */ 37 | #define INT_QUIT 0xFFFE /* Exit the emulation */ 38 | 39 | /* Bits in Z80 F register: */ 40 | #define S_FLAG 0x80 /* 1: Result negative */ 41 | #define Z_FLAG 0x40 /* 1: Result is zero */ 42 | #define H_FLAG 0x10 /* 1: Halfcarry/Halfborrow */ 43 | #define P_FLAG 0x04 /* 1: Result is even */ 44 | #define V_FLAG 0x04 /* 1: Overflow occured */ 45 | #define N_FLAG 0x02 /* 1: Subtraction occured */ 46 | #define C_FLAG 0x01 /* 1: Carry/Borrow occured */ 47 | 48 | /* Bits in IFF flip-flops: */ 49 | #define IFF_1 0x01 /* IFF1 flip-flop */ 50 | #define IFF_IM1 0x02 /* 1: IM1 mode */ 51 | #define IFF_IM2 0x04 /* 1: IM2 mode */ 52 | #define IFF_2 0x08 /* IFF2 flip-flop */ 53 | #define IFF_EI 0x20 /* 1: EI pending */ 54 | #define IFF_HALT 0x80 /* 1: CPU HALTed */ 55 | 56 | /** Simple Datatypes *****************************************/ 57 | /** NOTICE: sizeof(byte)=1 and sizeof(word)=2 **/ 58 | /*************************************************************/ 59 | #ifndef BYTE_TYPE_DEFINED 60 | #define BYTE_TYPE_DEFINED 61 | typedef unsigned char byte; 62 | #endif 63 | #ifndef WORD_TYPE_DEFINED 64 | #define WORD_TYPE_DEFINED 65 | typedef unsigned short word; 66 | #endif 67 | typedef signed char offset; 68 | 69 | /** Structured Datatypes *************************************/ 70 | /** NOTICE: #define LSB_FIRST for machines where least **/ 71 | /** signifcant byte goes first. **/ 72 | /*************************************************************/ 73 | typedef union 74 | { 75 | #ifdef LSB_FIRST 76 | struct { byte l,h; } B; 77 | #else 78 | struct { byte h,l; } B; 79 | #endif 80 | word W; 81 | } pair; 82 | 83 | typedef struct 84 | { 85 | pair AF,BC,DE,HL,IX,IY,PC,SP; /* Main registers */ 86 | pair AF1,BC1,DE1,HL1; /* Shadow registers */ 87 | byte IFF,I; /* Interrupt registers */ 88 | byte R; /* Refresh register */ 89 | 90 | int IPeriod,ICount; /* Set IPeriod to number of CPU cycles */ 91 | /* between calls to LoopZ80() */ 92 | int IBackup; /* Private, don't touch */ 93 | word IRequest; /* Set to address of pending IRQ */ 94 | byte IAutoReset; /* Set to 1 to autom. reset IRequest */ 95 | byte TrapBadOps; /* Set to 1 to warn of illegal opcodes */ 96 | word Trap; /* Set Trap to address to trace from */ 97 | byte Trace; /* Set Trace=1 to start tracing */ 98 | void *User; /* Arbitrary user data (ID,RAM*,etc.) */ 99 | } Z80; 100 | 101 | /** ResetZ80() ***********************************************/ 102 | /** This function can be used to reset the registers before **/ 103 | /** starting execution with RunZ80(). It sets registers to **/ 104 | /** their initial values. **/ 105 | /*************************************************************/ 106 | void ResetZ80(register Z80 *R); 107 | 108 | /** ExecZ80() ************************************************/ 109 | /** This function will execute given number of Z80 cycles. **/ 110 | /** It will then return the number of cycles left, possibly **/ 111 | /** negative, and current register values in R. **/ 112 | /*************************************************************/ 113 | #ifdef EXECZ80 114 | int ExecZ80(register Z80 *R,register int RunCycles); 115 | #endif 116 | 117 | /** IntZ80() *************************************************/ 118 | /** This function will generate interrupt of given vector. **/ 119 | /*************************************************************/ 120 | void IntZ80(register Z80 *R,register word Vector); 121 | 122 | /** RunZ80() *************************************************/ 123 | /** This function will run Z80 code until an LoopZ80() call **/ 124 | /** returns INT_QUIT. It will return the PC at which **/ 125 | /** emulation stopped, and current register values in R. **/ 126 | /*************************************************************/ 127 | #ifndef EXECZ80 128 | word RunZ80(register Z80 *R); 129 | #endif 130 | 131 | /** RdZ80()/WrZ80() ******************************************/ 132 | /** These functions are called when access to RAM occurs. **/ 133 | /** They allow to control memory access. **/ 134 | /************************************ TO BE WRITTEN BY USER **/ 135 | void WrZ80(register word Addr,register byte Value); 136 | byte RdZ80(register word Addr); 137 | 138 | /** InZ80()/OutZ80() *****************************************/ 139 | /** Z80 emulation calls these functions to read/write from **/ 140 | /** I/O ports. There can be 65536 I/O ports, but only first **/ 141 | /** 256 are usually used. **/ 142 | /************************************ TO BE WRITTEN BY USER **/ 143 | void OutZ80(register word Port,register byte Value); 144 | byte InZ80(register word Port); 145 | 146 | /** PatchZ80() ***********************************************/ 147 | /** Z80 emulation calls this function when it encounters a **/ 148 | /** special patch command (ED FE) provided for user needs. **/ 149 | /** For example, it can be called to emulate BIOS calls, **/ 150 | /** such as disk and tape access. Replace it with an empty **/ 151 | /** macro for no patching. **/ 152 | /************************************ TO BE WRITTEN BY USER **/ 153 | void PatchZ80(register Z80 *R); 154 | 155 | /** DebugZ80() ***********************************************/ 156 | /** This function should exist if DEBUG is #defined. When **/ 157 | /** Trace!=0, it is called after each command executed by **/ 158 | /** the CPU, and given the Z80 registers. Emulation exits **/ 159 | /** if DebugZ80() returns 0. **/ 160 | /*************************************************************/ 161 | #ifdef DEBUG 162 | byte DebugZ80(register Z80 *R); 163 | #endif 164 | 165 | /** LoopZ80() ************************************************/ 166 | /** Z80 emulation calls this function periodically to check **/ 167 | /** if the system hardware requires any interrupts. This **/ 168 | /** function must return an address of the interrupt vector **/ 169 | /** (0x0038, 0x0066, etc.) or INT_NONE for no interrupt. **/ 170 | /** Return INT_QUIT to exit the emulation loop. **/ 171 | /************************************ TO BE WRITTEN BY USER **/ 172 | word LoopZ80(register Z80 *R); 173 | 174 | /** JumpZ80() ************************************************/ 175 | /** Z80 emulation calls this function when it executes a **/ 176 | /** JP, JR, CALL, RST, or RET. You can use JumpZ80() to **/ 177 | /** trap these opcodes and switch memory layout. **/ 178 | /************************************ TO BE WRITTEN BY USER **/ 179 | #ifndef JUMPZ80 180 | #define JumpZ80(PC) 181 | #else 182 | void JumpZ80(word PC); 183 | #endif 184 | 185 | #ifdef __cplusplus 186 | } 187 | #endif 188 | #endif /* Z80_H */ 189 | -------------------------------------------------------------------------------- /source/browser.c: -------------------------------------------------------------------------------- 1 | /* 2 | * browser for PlayStation 4 3 | * Copyright (C) 2017 Antonio Jose Ramos Marquez (aka bigboss) @psxdev on twitter 4 | * Repository https://github.com/psxdev/fmsx 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "menu.h" 13 | #include "browser.h" 14 | #include "MSX.h" 15 | 16 | int notSelected=1; 17 | int comeBack=0; 18 | extern int64_t flipArg; 19 | int displayNumber=0; 20 | int extension; 21 | int slot=0; 22 | int drive=0; 23 | char path[256]; 24 | int posy=2; 25 | int posx=0; 26 | 27 | extern Orbis2dTexture *browserTexture; 28 | extern Orbis2dTexture *folderTexture; 29 | extern Orbis2dTexture *fileTexture; 30 | 31 | 32 | int flagfolder=0; 33 | OrbisFileBrowserListEntry *currentEntry; 34 | 35 | void browserUpdateController() 36 | { 37 | int ret; 38 | unsigned int buttons=0; 39 | OrbisFileBrowserListEntry *entry; 40 | ret=orbisPadUpdate(); 41 | if(ret==0) 42 | { 43 | if(orbisPadGetButtonPressed(ORBISPAD_UP)) 44 | { 45 | debugNetPrintf(DEBUG,"Up pressed\n"); 46 | orbisFileBrowserEntryUp(); 47 | currentEntry=orbisFileBrowserListGetNthEntry(orbisFileBrowserGetBasePos()+orbisFileBrowserGetRelPos()); 48 | if(currentEntry!=NULL) 49 | { 50 | debugNetPrintf(INFO,"current entry %s\n",currentEntry->dir->name); 51 | } 52 | } 53 | if(orbisPadGetButtonPressed(ORBISPAD_DOWN)) 54 | { 55 | 56 | debugNetPrintf(DEBUG,"Down pressed\n"); 57 | debugNetPrintf(DEBUG," before entry down level=%d base=%d rel=%d\n",orbisFileBrowserGetDirLevel(),orbisFileBrowserGetBasePos(),orbisFileBrowserGetRelPos()); 58 | 59 | orbisFileBrowserEntryDown(); 60 | debugNetPrintf(DEBUG," after entry down level=%d base=%d rel=%d\n",orbisFileBrowserGetDirLevel(),orbisFileBrowserGetBasePos(),orbisFileBrowserGetRelPos()); 61 | 62 | currentEntry=orbisFileBrowserListGetNthEntry(orbisFileBrowserGetBasePos()+orbisFileBrowserGetRelPos()); 63 | if(currentEntry!=NULL) 64 | { 65 | debugNetPrintf(INFO,"current entry %s\n",currentEntry->dir->name); 66 | } 67 | else 68 | { 69 | debugNetPrintf(INFO,"current entry chunga\n"); 70 | 71 | } 72 | } 73 | if(orbisPadGetButtonPressed(ORBISPAD_CIRCLE)) 74 | { 75 | debugNetPrintf(DEBUG,"Circle pressed come back to msx\n"); 76 | comeBack=1; 77 | } 78 | if(orbisPadGetButtonPressed(ORBISPAD_TRIANGLE)) 79 | { 80 | debugNetPrintf(DEBUG,"Triangle pressed posy=%d\n",++posy); 81 | showSettings(); 82 | } 83 | if(orbisPadGetButtonPressed(ORBISPAD_SQUARE)) 84 | { 85 | debugNetPrintf(DEBUG,"Square pressed posx=%d\n",++posx); 86 | } 87 | if(orbisPadGetButtonPressed(ORBISPAD_CROSS)) 88 | { 89 | debugNetPrintf(DEBUG,"Cross pressed\n"); 90 | notSelected=0; 91 | debugNetPrintf(DEBUG,"cross level=%d base=%d rel=%d\n",orbisFileBrowserGetDirLevel(),orbisFileBrowserGetBasePos(),orbisFileBrowserGetRelPos()); 92 | 93 | //entry=orbisFileBrowserListGetNthEntry(orbisFileBrowserGetBasePos()+orbisFileBrowserGetRelPos()); 94 | currentEntry=orbisFileBrowserListGetNthEntry(orbisFileBrowserGetBasePos()+orbisFileBrowserGetRelPos()); 95 | 96 | if(currentEntry!=NULL) 97 | { 98 | 99 | debugNetPrintf(INFO,"cross current entry %s customtype=%d\n",currentEntry->dir->name,currentEntry->dir->customtype); 100 | 101 | switch(currentEntry->dir->customtype) 102 | { 103 | case FILE_TYPE_FOLDER: 104 | notSelected=1; 105 | //if(strcmp(currentEntry->dir->name, ".") == 0) 106 | //{ 107 | // flagfolder=1; 108 | //} 109 | //else 110 | //{ 111 | //if(strcmp(currentEntry->dir->name, ".")!=0) 112 | //{ 113 | debugNetPrintf(DEBUG,"cross selected folder level=%d base=%d rel=%d\n",orbisFileBrowserGetDirLevel(),orbisFileBrowserGetBasePos(),orbisFileBrowserGetRelPos()); 114 | 115 | //orbisFileBrowserDirLevelUp(currentEntry->dir->name); 116 | //debugNetPrintf(DEBUG,"cross selected folder level=%d base=%d rel=%d\n",orbisFileBrowserGetDirLevel(),orbisFileBrowserGetBasePos(),orbisFileBrowserGetRelPos()); 117 | flagfolder=1; 118 | //} 119 | //} 120 | break; 121 | case FILE_TYPE_GAME_ROM: 122 | 123 | //if(extension==FILE_TYPE_GAME_ROM) 124 | //{ 125 | sprintf(path,"%s/%s",orbisFileBrowserGetListPath(),currentEntry->dir->name); 126 | debugNetPrintf(DEBUG,"cross selected entry game %s\n",path); 127 | 128 | LoadCart(path,slot,MAP_GUESS); 129 | //} 130 | //else 131 | //{ 132 | // debugNetPrintf(INFO,"wrong extension choose the right one\n"); 133 | //} 134 | break; 135 | case FILE_TYPE_GAME_DSK: 136 | //if(extension==FILE_TYPE_GAME_DSK) 137 | //{ 138 | 139 | sprintf(path,"%s/%s",orbisFileBrowserGetListPath(),currentEntry->dir->name); 140 | LoadFileDrive(path,drive); 141 | //} 142 | //else 143 | //{ 144 | // debugNetPrintf(INFO,"wrong extension choose the right one\n"); 145 | //} 146 | break; 147 | case FILE_TYPE_CAS: 148 | // if(extension==FILE_TYPE_CAS) 149 | // { 150 | sprintf(path,"%s/%s",orbisFileBrowserGetListPath(),currentEntry->dir->name); 151 | ChangeTape(path); 152 | // } 153 | // else 154 | // { 155 | // debugNetPrintf(INFO,"wrong extension choose the right one\n"); 156 | // } 157 | break; 158 | default: 159 | comeBack=1; 160 | break; 161 | } 162 | } 163 | } 164 | } 165 | } 166 | void getSizeString(char string[16], uint64_t size) 167 | { 168 | double double_size = (double)size; 169 | 170 | int i = 0; 171 | static char *units[] = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }; 172 | while (double_size >= 1024.0) { 173 | double_size /= 1024.0; 174 | i++; 175 | } 176 | 177 | snprintf(string, 16, "%.*f %s", (i == 0) ? 0 : 2, double_size, units[i]); 178 | } 179 | 180 | void browserDraw() 181 | { 182 | int i=0; 183 | uint32_t f1 ,f2; 184 | char dateString[20]; 185 | char sizeString[16]; 186 | if(flagfolder==1 && currentEntry) 187 | { 188 | if(strcmp(currentEntry->dir->name,".")!=0) 189 | { 190 | debugNetPrintf(DEBUG,"go to new directory %s\n",currentEntry->dir->name); 191 | //char rootpath[256]; 192 | //sprintf(rootpath,"%s/%s",orbisFileBrowserGetListPath(),currentEntry->dir->name); 193 | //debugNetPrintf(DEBUG,"go to new directory %s\n",rootpath); 194 | if(strcmp(currentEntry->dir->name,"..")!=0) 195 | { 196 | orbisFileBrowserDirLevelUp(currentEntry->dir->name); 197 | } 198 | else 199 | { 200 | orbisFileBrowserDirLevelDown(); 201 | } 202 | debugNetPrintf(DEBUG,"after orbisFileBrowserDirLevelUp\n"); 203 | } 204 | else 205 | { 206 | orbisFileBrowserListRefresh(); 207 | } 208 | flagfolder=0; 209 | 210 | } 211 | OrbisFileBrowserListEntry *entry=orbisFileBrowserListGetNthEntry(orbisFileBrowserGetBasePos()); 212 | 213 | 214 | 215 | while(entry && idir->customtype==FILE_TYPE_FOLDER) 219 | { 220 | if(folderTexture) 221 | { 222 | orbis2dDrawTexture(folderTexture,30,90+i*20); 223 | } 224 | sprintf(sizeString,"%s","FOLDER"); 225 | 226 | } 227 | else 228 | { 229 | if(fileTexture) 230 | { 231 | orbis2dDrawTexture(fileTexture,30,90+i*20+2); 232 | } 233 | getSizeString(sizeString,entry->dir->size); 234 | } 235 | //debugNetPrintf(DEBUG,("%s %d\n",entry->name,entry->type); 236 | if(i==orbisFileBrowserGetRelPos()) 237 | { 238 | 239 | f1 = 0xFF24FFBD; 240 | f2 = 0xFF24FFBD; 241 | update_gradient(&f1, &f2); 242 | 243 | } 244 | else 245 | { 246 | f1 = 0x80FFFFFF; 247 | f2 = 0x80FFFFFF; 248 | update_gradient(&f1, &f2); 249 | } 250 | //print_text(50+posx,90+i*20+posy,entry->dir->name); 251 | print_text(60,90+i*20+1,entry->dir->name); 252 | 253 | sprintf(dateString,"%02d/%02d/%04d %02d:%02d %s", 254 | entry->dir->mtime.day, 255 | entry->dir->mtime.month, 256 | entry->dir->mtime.year, 257 | entry->dir->mtime.hour>12?entry->dir->mtime.hour-12:entry->dir->mtime.hour, 258 | entry->dir->mtime.minute, 259 | entry->dir->mtime.hour>=12? "PM" : "AM"); 260 | print_text(960+8,90+i*20+1,dateString); 261 | print_text(960-8-16*strlen(sizeString)-posx,90+i*20+1,sizeString); 262 | 263 | 264 | entry=entry->next; 265 | i++; 266 | 267 | } 268 | f1 = 0xFF24FFBD,f2 = 0xFF24FFBD; 269 | update_gradient(&f1, &f2); 270 | print_text(30,52,orbisFileBrowserGetListPath()); 271 | 272 | } 273 | void showBrowser() 274 | { 275 | orbisAudioPause(0); 276 | 277 | uint32_t f1 = 0x80FFFFFF,f2 = 0x80FFFFFF; 278 | update_gradient(&f1, &f2); 279 | //debugNetPrintf(INFO,"in showBrowser %d\n",m); 280 | //orbisFileBrowserListRefresh(); 281 | /*switch(m) 282 | { 283 | case MENU_MEGAROM1: 284 | extension=FILE_TYPE_GAME_ROM; 285 | slot=0; 286 | break; 287 | case MENU_MEGAROM2: 288 | extension=FILE_TYPE_GAME_ROM; 289 | slot=1; 290 | break; 291 | case MENU_DISKA: 292 | extension=FILE_TYPE_GAME_DSK; 293 | drive=0; 294 | break; 295 | case MENU_DISKB: 296 | extension=FILE_TYPE_GAME_DSK; 297 | drive=1; 298 | break; 299 | case MENU_TAPE: 300 | extension=FILE_TYPE_CAS; 301 | break; 302 | default: 303 | break; 304 | }*/ 305 | while(notSelected==1 && comeBack==0 && displayNumber!=0) 306 | { 307 | browserUpdateController(); 308 | //wait for current display buffer 309 | orbis2dStartDrawing(); 310 | 311 | // clear with background (default white) to the current display buffer 312 | orbis2dClearBuffer(0); 313 | 314 | if(browserTexture) 315 | { 316 | orbis2dDrawTexture(browserTexture,0,0); 317 | } 318 | //default red is here press X to random color 319 | //orbis2dDrawRectColor(x,w,y,h,color); 320 | if(displayNumber==1) 321 | browserDraw(); 322 | //flush and flip 323 | orbis2dFinishDrawing(flipArg); 324 | 325 | //swap buffers 326 | orbis2dSwapBuffers(); 327 | flipArg++; 328 | } 329 | notSelected=1; 330 | comeBack=0; 331 | //msx go go 332 | displayNumber=0; 333 | } -------------------------------------------------------------------------------- /source/credits.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "menu.h" 5 | #include "browser.h" 6 | #include "MSX.h" 7 | 8 | extern int displayNumber; 9 | extern int64_t flipArg; 10 | extern Orbis2dTexture *creditsTexture; 11 | 12 | 13 | 14 | void creditsUpdateController() 15 | { 16 | int ret; 17 | unsigned int buttons=0; 18 | ret=orbisPadUpdate(); 19 | if(ret==0) 20 | { 21 | 22 | if(orbisPadGetButtonPressed(ORBISPAD_UP)) 23 | { 24 | debugNetPrintf(DEBUG,"Up pressed\n"); 25 | displayNumber=2; 26 | } 27 | if(orbisPadGetButtonPressed(ORBISPAD_DOWN)) 28 | { 29 | debugNetPrintf(DEBUG,"Down pressed\n"); 30 | displayNumber=2; 31 | } 32 | if(orbisPadGetButtonPressed(ORBISPAD_RIGHT)) 33 | { 34 | debugNetPrintf(DEBUG,"Right pressed\n"); 35 | displayNumber=2; 36 | } 37 | if(orbisPadGetButtonPressed(ORBISPAD_LEFT)) 38 | { 39 | debugNetPrintf(DEBUG,"Left pressed\n"); 40 | displayNumber=2; 41 | } 42 | if(orbisPadGetButtonPressed(ORBISPAD_TRIANGLE)) 43 | { 44 | debugNetPrintf(DEBUG,"Triangle pressed exit\n"); 45 | displayNumber=2; 46 | } 47 | if(orbisPadGetButtonPressed(ORBISPAD_CIRCLE)) 48 | { 49 | debugNetPrintf(DEBUG,"Circle pressed come back to browser\n"); 50 | displayNumber=2; 51 | } 52 | if(orbisPadGetButtonPressed(ORBISPAD_CROSS)) 53 | { 54 | debugNetPrintf(DEBUG,"Cross pressed\n"); 55 | displayNumber=2; 56 | } 57 | if(orbisPadGetButtonPressed(ORBISPAD_SQUARE)) 58 | { 59 | debugNetPrintf(DEBUG,"Square pressed\n"); 60 | displayNumber=1; 61 | } 62 | } 63 | } 64 | void showCredits() 65 | { 66 | displayNumber=3; 67 | int f1=0x80000000; 68 | int f2=0x80000000; 69 | while(displayNumber==3) 70 | { 71 | creditsUpdateController(); 72 | 73 | //wait for current display buffer 74 | orbis2dStartDrawing(); 75 | 76 | // clear with background (default white) to the current display buffer 77 | orbis2dClearBuffer(0); 78 | 79 | //default red is here press X to random color 80 | //orbis2dDrawRectColor(x,w,y,h,color); 81 | //draw credits texture 82 | if(creditsTexture) 83 | { 84 | orbis2dDrawTexture(creditsTexture,0,0); 85 | } 86 | 87 | //flush and flip 88 | orbis2dFinishDrawing(flipArg); 89 | 90 | //swap buffers 91 | orbis2dSwapBuffers(); 92 | flipArg++; 93 | 94 | } 95 | } -------------------------------------------------------------------------------- /source/fMSX/Boot.h: -------------------------------------------------------------------------------- 1 | /** fMSX: portable MSX emulator ******************************/ 2 | /** **/ 3 | /** Boot.h **/ 4 | /** **/ 5 | /** This file contains MSX boot sector image used to create **/ 6 | /** new disk images during FORMAT operation. **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 1994-2017 **/ 9 | /** You are not allowed to distribute this software **/ 10 | /** commercially. Please, notify me, if you make any **/ 11 | /** changes to this file. **/ 12 | /*************************************************************/ 13 | 14 | static byte BootBlock[] = 15 | { 16 | 0xEB,0xFE,0x90,0x56,0x46,0x42,0x2D,0x31,0x39,0x38,0x39,0x00,0x02,0x02,0x01,0x00, 17 | 0x02,0x70,0x00,0xA0,0x05,0xF9,0x03,0x00,0x09,0x00,0x02,0x00,0x00,0x00,0xD0,0xED, 18 | 0x53,0x58,0xC0,0x32,0xC2,0xC0,0x36,0x55,0x23,0x36,0xC0,0x31,0x1F,0xF5,0x11,0x9D, 19 | 0xC0,0x0E,0x0F,0xCD,0x7D,0xF3,0x3C,0x28,0x28,0x11,0x00,0x01,0x0E,0x1A,0xCD,0x7D, 20 | 0xF3,0x21,0x01,0x00,0x22,0xAB,0xC0,0x21,0x00,0x3F,0x11,0x9D,0xC0,0x0E,0x27,0xCD, 21 | 0x7D,0xF3,0xC3,0x00,0x01,0x57,0xC0,0xCD,0x00,0x00,0x79,0xE6,0xFE,0xFE,0x02,0x20, 22 | 0x07,0x3A,0xC2,0xC0,0xA7,0xCA,0x22,0x40,0x11,0x77,0xC0,0x0E,0x09,0xCD,0x7D,0xF3, 23 | 0x0E,0x07,0xCD,0x7D,0xF3,0x18,0xB4,0x42,0x6F,0x6F,0x74,0x20,0x65,0x72,0x72,0x6F, 24 | 0x72,0x0D,0x0A,0x50,0x72,0x65,0x73,0x73,0x20,0x61,0x6E,0x79,0x20,0x6B,0x65,0x79, 25 | 0x20,0x66,0x6F,0x72,0x20,0x72,0x65,0x74,0x72,0x79,0x0D,0x0A,0x24,0x00,0x4D,0x53, 26 | 0x58,0x44,0x4F,0x53,0x20,0x20,0x53,0x59,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 27 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 28 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF3,0x2A, 29 | 0x51,0xF3,0x11,0x00,0x01,0x19,0x01,0x00,0x01,0x11,0x00,0xC1,0xED,0xB0,0x3A,0xEE, 30 | 0xC0,0x47,0x11,0xEF,0xC0,0x21,0x00,0x00,0xCD,0x51,0x52,0xF3,0x76,0xC9,0x18,0x64, 31 | 0x3A,0xAF,0x80,0xF9,0xCA,0x6D,0x48,0xD3,0xA5,0x0C,0x8C,0x2F,0x9C,0xCB,0xE9,0x89, 32 | 0xD2,0x00,0x32,0x26,0x40,0x94,0x61,0x19,0x20,0xE6,0x80,0x6D,0x8A,0x00,0x00,0x00, 33 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 34 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 35 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 36 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 37 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 38 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 39 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 40 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 41 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 42 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 43 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 44 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 45 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 46 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 47 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 48 | }; 49 | -------------------------------------------------------------------------------- /source/fMSX/CommonMux.h: -------------------------------------------------------------------------------- 1 | /** fMSX: portable MSX emulator ******************************/ 2 | /** **/ 3 | /** CommonMux.h **/ 4 | /** **/ 5 | /** This file instantiates MSX screen drivers for every **/ 6 | /** possible screen depth. It includes common driver code **/ 7 | /** from Common.h and Wide.h. **/ 8 | /** **/ 9 | /** Copyright (C) Marat Fayzullin 1994-2017 **/ 10 | /** You are not allowed to distribute this software **/ 11 | /** commercially. Please, notify me, if you make any **/ 12 | /** changes to this file. **/ 13 | /*************************************************************/ 14 | #ifndef COMMONMUX_H 15 | #define COMMONMUX_H 16 | 17 | #include "Common.h" 18 | #include "Wide.h" 19 | 20 | #undef BPP8 21 | #undef BPP16 22 | #undef BPP24 23 | #undef BPP32 24 | 25 | /** Screen Mode Handlers [number of screens + 1] *************/ 26 | extern void (*RefreshLine[MAXSCREEN+2])(byte Y); 27 | 28 | #define BPP8 29 | #define pixel unsigned char 30 | #define FirstLine FirstLine_8 31 | #define Sprites Sprites_8 32 | #define ColorSprites ColorSprites_8 33 | #define RefreshBorder RefreshBorder_8 34 | #define RefreshBorder512 RefreshBorder512_8 35 | #define ClearLine ClearLine_8 36 | #define ClearLine512 ClearLine512_8 37 | #define YJKColor YJKColor_8 38 | #define RefreshScreen RefreshScreen_8 39 | #define RefreshLineF RefreshLineF_8 40 | #define RefreshLine0 RefreshLine0_8 41 | #define RefreshLine1 RefreshLine1_8 42 | #define RefreshLine2 RefreshLine2_8 43 | #define RefreshLine3 RefreshLine3_8 44 | #define RefreshLine4 RefreshLine4_8 45 | #define RefreshLine5 RefreshLine5_8 46 | #define RefreshLine6 RefreshLine6_8 47 | #define RefreshLine7 RefreshLine7_8 48 | #define RefreshLine8 RefreshLine8_8 49 | #define RefreshLine10 RefreshLine10_8 50 | #define RefreshLine12 RefreshLine12_8 51 | #define RefreshLineTx80 RefreshLineTx80_8 52 | #include "Common.h" 53 | #include "Wide.h" 54 | #undef pixel 55 | #undef FirstLine 56 | #undef Sprites 57 | #undef ColorSprites 58 | #undef RefreshBorder 59 | #undef RefreshBorder512 60 | #undef ClearLine 61 | #undef ClearLine512 62 | #undef YJKColor 63 | #undef RefreshScreen 64 | #undef RefreshLineF 65 | #undef RefreshLine0 66 | #undef RefreshLine1 67 | #undef RefreshLine2 68 | #undef RefreshLine3 69 | #undef RefreshLine4 70 | #undef RefreshLine5 71 | #undef RefreshLine6 72 | #undef RefreshLine7 73 | #undef RefreshLine8 74 | #undef RefreshLine10 75 | #undef RefreshLine12 76 | #undef RefreshLineTx80 77 | #undef BPP8 78 | 79 | #define BPP16 80 | #define pixel unsigned short 81 | #define FirstLine FirstLine_16 82 | #define Sprites Sprites_16 83 | #define ColorSprites ColorSprites_16 84 | #define RefreshBorder RefreshBorder_16 85 | #define RefreshBorder512 RefreshBorder512_16 86 | #define ClearLine ClearLine_16 87 | #define ClearLine512 ClearLine512_16 88 | #define YJKColor YJKColor_16 89 | #define RefreshScreen RefreshScreen_16 90 | #define RefreshLineF RefreshLineF_16 91 | #define RefreshLine0 RefreshLine0_16 92 | #define RefreshLine1 RefreshLine1_16 93 | #define RefreshLine2 RefreshLine2_16 94 | #define RefreshLine3 RefreshLine3_16 95 | #define RefreshLine4 RefreshLine4_16 96 | #define RefreshLine5 RefreshLine5_16 97 | #define RefreshLine6 RefreshLine6_16 98 | #define RefreshLine7 RefreshLine7_16 99 | #define RefreshLine8 RefreshLine8_16 100 | #define RefreshLine10 RefreshLine10_16 101 | #define RefreshLine12 RefreshLine12_16 102 | #define RefreshLineTx80 RefreshLineTx80_16 103 | #include "Common.h" 104 | #include "Wide.h" 105 | #undef pixel 106 | #undef FirstLine 107 | #undef Sprites 108 | #undef ColorSprites 109 | #undef RefreshBorder 110 | #undef RefreshBorder512 111 | #undef ClearLine 112 | #undef ClearLine512 113 | #undef YJKColor 114 | #undef RefreshScreen 115 | #undef RefreshLineF 116 | #undef RefreshLine0 117 | #undef RefreshLine1 118 | #undef RefreshLine2 119 | #undef RefreshLine3 120 | #undef RefreshLine4 121 | #undef RefreshLine5 122 | #undef RefreshLine6 123 | #undef RefreshLine7 124 | #undef RefreshLine8 125 | #undef RefreshLine10 126 | #undef RefreshLine12 127 | #undef RefreshLineTx80 128 | #undef BPP16 129 | 130 | #define BPP32 131 | #define pixel unsigned int 132 | #define FirstLine FirstLine_32 133 | #define Sprites Sprites_32 134 | #define ColorSprites ColorSprites_32 135 | #define RefreshBorder RefreshBorder_32 136 | #define RefreshBorder512 RefreshBorder512_32 137 | #define ClearLine ClearLine_32 138 | #define ClearLine512 ClearLine512_32 139 | #define YJKColor YJKColor_32 140 | #define RefreshScreen RefreshScreen_32 141 | #define RefreshLineF RefreshLineF_32 142 | #define RefreshLine0 RefreshLine0_32 143 | #define RefreshLine1 RefreshLine1_32 144 | #define RefreshLine2 RefreshLine2_32 145 | #define RefreshLine3 RefreshLine3_32 146 | #define RefreshLine4 RefreshLine4_32 147 | #define RefreshLine5 RefreshLine5_32 148 | #define RefreshLine6 RefreshLine6_32 149 | #define RefreshLine7 RefreshLine7_32 150 | #define RefreshLine8 RefreshLine8_32 151 | #define RefreshLine10 RefreshLine10_32 152 | #define RefreshLine12 RefreshLine12_32 153 | #define RefreshLineTx80 RefreshLineTx80_32 154 | #include "Common.h" 155 | #include "Wide.h" 156 | #undef pixel 157 | #undef FirstLine 158 | #undef Sprites 159 | #undef ColorSprites 160 | #undef RefreshBorder 161 | #undef RefreshBorder512 162 | #undef ClearLine 163 | #undef ClearLine512 164 | #undef YJKColor 165 | #undef RefreshScreen 166 | #undef RefreshLineF 167 | #undef RefreshLine0 168 | #undef RefreshLine1 169 | #undef RefreshLine2 170 | #undef RefreshLine3 171 | #undef RefreshLine4 172 | #undef RefreshLine5 173 | #undef RefreshLine6 174 | #undef RefreshLine7 175 | #undef RefreshLine8 176 | #undef RefreshLine10 177 | #undef RefreshLine12 178 | #undef RefreshLineTx80 179 | #undef BPP32 180 | 181 | /** SetScreenDepth() *****************************************/ 182 | /** Fill fMSX screen driver array with pointers matching **/ 183 | /** the given image depth. **/ 184 | /*************************************************************/ 185 | int SetScreenDepth(int Depth) 186 | { 187 | if(Depth<=8) 188 | { 189 | Depth=8; 190 | RefreshLine[0] = RefreshLine0_8; 191 | RefreshLine[1] = RefreshLine1_8; 192 | RefreshLine[2] = RefreshLine2_8; 193 | RefreshLine[3] = RefreshLine3_8; 194 | RefreshLine[4] = RefreshLine4_8; 195 | RefreshLine[5] = RefreshLine5_8; 196 | RefreshLine[6] = RefreshLine6_8; 197 | RefreshLine[7] = RefreshLine7_8; 198 | RefreshLine[8] = RefreshLine8_8; 199 | RefreshLine[9] = 0; 200 | RefreshLine[10] = RefreshLine10_8; 201 | RefreshLine[11] = RefreshLine10_8; 202 | RefreshLine[12] = RefreshLine12_8; 203 | RefreshLine[13] = RefreshLineTx80_8; 204 | } 205 | else if(Depth<=16) 206 | { 207 | Depth=16; 208 | RefreshLine[0] = RefreshLine0_16; 209 | RefreshLine[1] = RefreshLine1_16; 210 | RefreshLine[2] = RefreshLine2_16; 211 | RefreshLine[3] = RefreshLine3_16; 212 | RefreshLine[4] = RefreshLine4_16; 213 | RefreshLine[5] = RefreshLine5_16; 214 | RefreshLine[6] = RefreshLine6_16; 215 | RefreshLine[7] = RefreshLine7_16; 216 | RefreshLine[8] = RefreshLine8_16; 217 | RefreshLine[9] = 0; 218 | RefreshLine[10] = RefreshLine10_16; 219 | RefreshLine[11] = RefreshLine10_16; 220 | RefreshLine[12] = RefreshLine12_16; 221 | RefreshLine[13] = RefreshLineTx80_16; 222 | } 223 | else if(Depth<=32) 224 | { 225 | Depth=32; 226 | RefreshLine[0] = RefreshLine0_32; 227 | RefreshLine[1] = RefreshLine1_32; 228 | RefreshLine[2] = RefreshLine2_32; 229 | RefreshLine[3] = RefreshLine3_32; 230 | RefreshLine[4] = RefreshLine4_32; 231 | RefreshLine[5] = RefreshLine5_32; 232 | RefreshLine[6] = RefreshLine6_32; 233 | RefreshLine[7] = RefreshLine7_32; 234 | RefreshLine[8] = RefreshLine8_32; 235 | RefreshLine[9] = 0; 236 | RefreshLine[10] = RefreshLine10_32; 237 | RefreshLine[11] = RefreshLine10_32; 238 | RefreshLine[12] = RefreshLine12_32; 239 | RefreshLine[13] = RefreshLineTx80_32; 240 | } 241 | else 242 | { 243 | /* Wrong screen depth */ 244 | Depth=0; 245 | } 246 | 247 | /* Done */ 248 | return(Depth); 249 | } 250 | 251 | #endif /* COMMONMUX_H */ 252 | -------------------------------------------------------------------------------- /source/fMSX/Help.h: -------------------------------------------------------------------------------- 1 | /** fMSX: portable MSX emulator ******************************/ 2 | /** **/ 3 | /** Help.h **/ 4 | /** **/ 5 | /** This file contains help information printed out by the **/ 6 | /** main() routine when started with option "-help". **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 1994-2017 **/ 9 | /** You are not allowed to distribute this software **/ 10 | /** commercially. Please, notify me, if you make any **/ 11 | /** changes to this file. **/ 12 | /*************************************************************/ 13 | 14 | static const char *HelpText[] = 15 | { 16 | "Usage: fmsx [-option1 [-option2...]] [filename1] [filename2]", 17 | "[filename1] = name of file to load as cartridge A", 18 | "[filename2] = name of file to load as cartridge B", 19 | #if defined(ZLIB) 20 | " This program will transparently uncompress singular GZIPped", 21 | " and PKZIPped files.", 22 | #endif 23 | "[-option] =", 24 | " -verbose - Select debugging messages [1]", 25 | " 0 - Silent 1 - Startup messages", 26 | " 2 - V9938 ops 4 - Disk/Tape", 27 | " 8 - Memory 16 - Illegal Z80 ops", 28 | " 32 - I/O", 29 | " -skip - Percentage of frames to skip [25]", 30 | " -pal/-ntsc - Set PAL/NTSC HBlank/VBlank periods [NTSC]", 31 | " -help - Print this help page", 32 | " -home - Set directory with system ROM files [off]", 33 | " -printer - Redirect printer output to file [stdout]", 34 | " -serial - Redirect serial I/O to a file [stdin/stdout]", 35 | " -diska - Set disk image used for drive A: [DRIVEA.DSK]", 36 | " (multiple -diska options accepted)", 37 | " -diskb - Set disk image used for drive B: [DRIVEB.DSK]", 38 | " (multiple -diskb options accepted)", 39 | " -tape - Set tape image file [off]", 40 | " -font - Set fixed font for text modes [DEFAULT.FNT]", 41 | " -logsnd - Set soundtrack log file [LOG.MID]", 42 | " -state - Set emulation state save file [automatic]", 43 | " -auto/-noauto - Use autofire on SPACE [off]", 44 | " -ram - Number of 16kB RAM pages [4/8/8]", 45 | " -vram - Number of 16kB VRAM pages [2/8/8]", 46 | " -rom - Select MegaROM mapper types [8,8]", 47 | " (two -rom options accepted)", 48 | " 0 - Generic 8kB 1 - Generic 16kB (MSXDOS2)", 49 | " 2 - Konami5 8kB 3 - Konami4 8kB", 50 | " 4 - ASCII 8kB 5 - ASCII 16kB", 51 | " 6 - GameMaster2 7 - FMPAC", 52 | " >7 - Try guessing mapper type", 53 | " -msx1/-msx2/-msx2+ - Select MSX model [-msx2]", 54 | " -joy - Select joystick types [0,0]", 55 | " (two -joy options accepted)", 56 | " 0 - No joystick", 57 | " 1 - Normal joystick", 58 | " 2 - Mouse in joystick mode", 59 | " 3 - Mouse in real mode", 60 | " -simbdos/-wd1793 - Simulate DiskROM disk access calls [-wd1793]", 61 | " -sound [] - Sound emulation quality (Hz) [44100]", 62 | " -nosound - Same as '-sound 0'", 63 | 64 | #if defined(DEBUG) 65 | " -trap
- Trap execution when PC reaches address [FFFFh]", 66 | " (when keyword 'now' is used in place of the", 67 | "
, execution will trap immediately)", 68 | #endif /* DEBUG */ 69 | 70 | #if defined(MSDOS) || defined(UNIX) || defined(MAEMO) 71 | " -sync - Sync screen updates to [60]", 72 | " -nosync - Do not sync screen updates", 73 | " -tv/-lcd/-raster - Simulate TV scanlines or LCD raster [off]", 74 | " -soft/-eagle - Scale display with 2xSaI or EAGLE [off]", 75 | " -epx/-scale2x - Scale display with EPX or Scale2X [off]", 76 | " -cmy/-rgb - Simulate CMY/RGB pixel raster [off]", 77 | " -mono/-sepia - Simulate monochrome or sepia CRT [off]", 78 | " -green/-amber - Simulate green or amber CRT [off]", 79 | " -4x3 - Force 4:3 television screen ratio [off]", 80 | #endif /* MSDOS || UNIX || MAEMO */ 81 | 82 | #if defined(UNIX) || defined(MAEMO) 83 | " -saver/-nosaver - Save CPU when inactive [-saver]", 84 | #endif /* UNIX || MAEMO */ 85 | 86 | #if defined(UNIX) 87 | #ifdef MITSHM 88 | " -shm/-noshm - Use MIT SHM extensions for X [-shm]", 89 | #endif 90 | " -scale - Scale window by [2]", 91 | #endif /* UNIX */ 92 | 93 | #if defined(MSDOS) 94 | " -vsync - Sync screen updates to VBlank [-vsync]", 95 | #if defined(BPP8) 96 | " -static/-nostatic - Use static color palette [-nostatic]", 97 | #endif 98 | #if defined(NARROW) 99 | " -480/-200 - Use 640x480 or 320x200 VGA mode [-200]", 100 | #endif 101 | #endif /* MSDOS */ 102 | 103 | "\nKeyboard bindings:", 104 | " [CONTROL] - CONTROL (also: joystick FIRE-A button)", 105 | " [SHIFT] - SHIFT (also: joystick FIRE-B button)", 106 | " [ALT] - GRAPH (also: swap joysticks)", 107 | " [INSERT] - INSERT", 108 | " [DELETE] - DELETE", 109 | " [HOME] - HOME/CLS", 110 | " [END] - SELECT", 111 | " [PGUP] - STOP/BREAK", 112 | " [PGDOWN] - COUNTRY", 113 | " [F6] - Load emulation from .STA file", 114 | " [F7] - Save emulation state to .STA file", 115 | " [F8] - Rewind emulation back in time", 116 | " [F9] - Fast-forward emulation", 117 | " [F10] - Invoke built-in configuration menu", 118 | " [F11] - Reset hardware", 119 | " [F12] - Quit emulation", 120 | " [CONTROL]+[F8] - Toggle scanlines on/off", 121 | " [ALT]+[F8] - Toggle screen softening on/off", 122 | #if defined(DEBUG) 123 | " [CONTROL]+[F10] - Go into the built-in debugger", 124 | #endif 125 | 0 126 | }; 127 | -------------------------------------------------------------------------------- /source/fMSX/I8251.c: -------------------------------------------------------------------------------- 1 | /** EMULib Emulation Library *********************************/ 2 | /** **/ 3 | /** I8251.c **/ 4 | /** **/ 5 | /** This file contains emulation for the Intel 8251 UART **/ 6 | /** chip and the 8253 timer chip implementing a generic **/ 7 | /** RS232 interface. **/ 8 | /** **/ 9 | /** Copyright (C) Marat Fayzullin 2004-2017 **/ 10 | /** Maarten ter Huurne 2000 **/ 11 | /** You are not allowed to distribute this software **/ 12 | /** commercially. Please, notify me, if you make any **/ 13 | /** changes to this file. **/ 14 | /*************************************************************/ 15 | 16 | #include "I8251.h" 17 | 18 | /** Reset8251 ************************************************/ 19 | /** Reset 8251 chip, assigning In and Out to the input and **/ 20 | /** output streams. **/ 21 | /*************************************************************/ 22 | void Reset8251(register I8251 *D,FILE *In,FILE *Out) 23 | { 24 | D->IRQMask = 0x0F; /* All interrupts on */ 25 | D->IRQs = 0x00; /* No interrupts yet */ 26 | D->Mode = 1; /* Setting mode next */ 27 | D->Flow = 0x00; /* Flow control off */ 28 | D->NextChr = -1; /* No data yet */ 29 | 30 | /* Assign input and output streams */ 31 | D->In = In? In:stdin; 32 | D->Out = Out? Out:stdout; 33 | } 34 | 35 | /** Rd8251 ***************************************************/ 36 | /** Read a byte from a given 8251 register. All values of R **/ 37 | /** will be truncated to 3 bits as there are only 8 regs. **/ 38 | /*************************************************************/ 39 | byte Rd8251(register I8251 *D,register byte R) 40 | { 41 | register int J; 42 | 43 | /* We only have 8 addressable ports */ 44 | R&=0x07; 45 | 46 | switch(R) 47 | { 48 | case 0: /* Data */ 49 | if(D->Flow) 50 | { 51 | if(D->NextChr<0) D->NextChr=fgetc(D->In); 52 | J=D->NextChr; 53 | D->NextChr=-1; 54 | return((J<0? 0xFF:J)&((0x20<<((D->Control&0x0C)>>2))-1)); 55 | } 56 | return(0xFF); 57 | 58 | case 1: /* Status */ 59 | if(D->NextChr<0) D->NextChr=fgetc(D->In); 60 | return(D->Flow&&(D->NextChr>=0)? 0x87:0x85); 61 | /* 62 | 76543210 63 | 1....... data set ready (dsr) 64 | .1...... sync detect, sync only 65 | ..1..... framing error (fe), async only 66 | ...1.... overrun error (oe) 67 | ....1... parity error (pe) 68 | .....1.. transmitter empty 69 | ......1. receiver ready 70 | .......1 transmitter ready 71 | 72 | D->Flow is checked first, so that stdin input doesn't block 73 | fMSX until it's actually being read by the emulated MSX. 74 | */ 75 | 76 | case 0x82: /* Status of CTS, timer/counter 2, RI and CD */ 77 | return(0x7F); 78 | /* 79 | 76543210 80 | 1....... CTS (Clear To Send) 0=asserted 81 | .1...... timer/counter output-2 from 8253 82 | ..XXXX.. reserved 83 | ......1. RI (Ring Indicator) 0=asserted 84 | .......1 CD (Carrier Detect) 0=asserted 85 | 86 | RI and CD are optional. If only one of them is implemented, 87 | it must be CD. Implemented like this: 88 | - CTS always returns 0 (asserted) 89 | - Everything else is not implemented 90 | */ 91 | } 92 | 93 | /* Other RS232 ports: 94 | 3: not standardised - unused 95 | 4: 8253 counter 0 - not implemented 96 | 5: 8253 counter 1 - not implemented 97 | 6: 8253 counter 2 - not implemented 98 | 7: 8253 mode register - write only 99 | */ 100 | 101 | return(0xFF); 102 | } 103 | 104 | /** Wr8251 ***************************************************/ 105 | /** Write a byte to a given 8251 register. All values of R **/ 106 | /** will be truncated to 3 bits as there are only 8 regs. **/ 107 | /*************************************************************/ 108 | void Wr8251(register I8251 *D,register byte R,register byte V) 109 | { 110 | /* We only have 8 addressable ports */ 111 | R&=0x07; 112 | 113 | switch(R) 114 | { 115 | case 0: /* Data */ 116 | fputc(V&((0x20<<((D->Control&0x0C)>>2))-1),D->Out); 117 | fflush(D->Out); 118 | return; 119 | /* 120 | TODO: Flush the stream at appropriate intervals, instead of 121 | flushing for every single character. If flushing after every 122 | character remains, make the stream unbuffered. 123 | */ 124 | 125 | case 1: /* Command */ 126 | if(D->Mode) 127 | { 128 | D->Control=V; 129 | D->Mode=0; 130 | /* Set mode: 131 | ......00 sync mode 132 | ......01 async, baud rate factor is 1 133 | ......10 async, baud rate factor is 16 134 | ......11 async, baud rate factor is 64 135 | ....00.. character length is 5 bits 136 | ....01.. character length is 6 bits 137 | ....10.. character length is 7 bits 138 | ....11.. character length is 8 bits 139 | ...1.... parity enable 140 | ..1..... even/odd parity 141 | .1...... sync: external sync detect (syndet) is an input/output 142 | 1....... sync: single/double character sync 143 | 00...... async: invalid 144 | 01...... async: 1 stop bit 145 | 10...... async: 1.5 stop bits 146 | 11...... async: 2 stop bits 147 | */ 148 | } 149 | else 150 | { 151 | D->Mode=V&0x40; 152 | D->Flow=(V>>4)&0x02; 153 | /* Execute command: 154 | 76543210 155 | 1....... enter hunt mode (enable search for sync characters) 156 | .1...... internal reset 157 | ..1..... request to send (rts) 158 | ...1.... reset error flags (pe,oe,fe) 159 | ....1... send break character 160 | .....1.. receive enable 161 | ......1. data terminal ready (dtr) 162 | .......1 transmit enable 163 | 164 | Only RESET (bit6) and DTR (bit2) are implemented. 165 | */ 166 | } 167 | return; 168 | 169 | case 2: /* Interrupt mask register */ 170 | D->IRQMask=V; 171 | return; 172 | /* 173 | 76543210 174 | XXXX.... reserved 175 | ....1... timer interrupt from 8253 channel-2 (0=enable int) 176 | .....1.. sync character detect/break detect (0=enable int) 177 | ......1. transmit data ready (TxReady) (0=enable int) 178 | .......1 receive data ready (RxReady) (0=enable int) 179 | 180 | Initially all interrupts are disabled. RxReady interrupt must be 181 | implemented, the others are optional. 182 | 183 | However, currently no interrupt at all is implemented. The result 184 | is that only one character is read per VDP interrupt, so serial 185 | communication is 50/60 baud. 186 | */ 187 | } 188 | 189 | /* Other RS232 ports: 190 | 3: not standardised - unused 191 | 4: 8253 counter 0 - not implemented 192 | 5: 8253 counter 1 - not implemented 193 | 6: 8253 counter 2 - not implemented 194 | 7: 8253 mode register - not implemented 195 | */ 196 | } 197 | -------------------------------------------------------------------------------- /source/fMSX/I8251.h: -------------------------------------------------------------------------------- 1 | /** EMULib Emulation Library *********************************/ 2 | /** **/ 3 | /** I8251.h **/ 4 | /** **/ 5 | /** This file contains definitions and declarations for **/ 6 | /** routines in I8251.c. **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 2004-2017 **/ 9 | /** Maarten ter Huurne 2000 **/ 10 | /** You are not allowed to distribute this software **/ 11 | /** commercially. Please, notify me, if you make any **/ 12 | /** changes to this file. **/ 13 | /*************************************************************/ 14 | #ifndef I8251_H 15 | #define I8251_H 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | #include 21 | 22 | #ifndef BYTE_TYPE_DEFINED 23 | #define BYTE_TYPE_DEFINED 24 | typedef unsigned char byte; 25 | #endif 26 | 27 | /** I8251 ****************************************************/ 28 | /** This data structure stores I8251 state. **/ 29 | /*************************************************************/ 30 | typedef struct 31 | { 32 | byte Control; /* 8251 ACIA control reg. */ 33 | byte IRQMask; /* RS232 interrupt mask */ 34 | byte IRQs; /* RS232 interrupts */ 35 | byte Mode; /* 8251 mode/cmd select */ 36 | byte Flow; /* Flow control state */ 37 | int NextChr; /* Next char or -1 */ 38 | FILE *In; /* Input stream */ 39 | FILE *Out; /* Output stream */ 40 | } I8251; 41 | 42 | /** Reset8251 ************************************************/ 43 | /** Reset 8251 chip, assigning In and Out to the input and **/ 44 | /** output streams. **/ 45 | /*************************************************************/ 46 | void Reset8251(register I8251 *D,FILE *In,FILE *Out); 47 | 48 | /** Rd8251 ***************************************************/ 49 | /** Read a byte from a given 8251 register. All values of R **/ 50 | /** will be truncated to 3 bits as there are only 8 regs. **/ 51 | /*************************************************************/ 52 | byte Rd8251(register I8251 *D,register byte R); 53 | 54 | /** Wr8251 ***************************************************/ 55 | /** Write a byte to a given 8251 register. All values of R **/ 56 | /** will be truncated to 3 bits as there are only 8 regs. **/ 57 | /*************************************************************/ 58 | void Wr8251(register I8251 *D,register byte R,register byte V); 59 | 60 | #ifdef __cplusplus 61 | } 62 | #endif 63 | #endif /* I8251_H */ 64 | -------------------------------------------------------------------------------- /source/fMSX/V9938.h: -------------------------------------------------------------------------------- 1 | /** fMSX: portable MSX emulator ******************************/ 2 | /** **/ 3 | /** V9938.h **/ 4 | /** **/ 5 | /** This file contains declarations for V9938 special **/ 6 | /** graphical operations support implemented in V9938.c. **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 1994-2017 **/ 9 | /** You are not allowed to distribute this software **/ 10 | /** commercially. Please, notify me, if you make any **/ 11 | /** changes to this file. **/ 12 | /*************************************************************/ 13 | #ifndef V9938_H 14 | #define V9938_H 15 | 16 | #include "MSX.h" 17 | 18 | /** VDPWrite() ***********************************************/ 19 | /** Use this function to transfer pixel(s) from CPU to VDP. **/ 20 | /*************************************************************/ 21 | void VDPWrite(register byte V); 22 | 23 | /** VDPRead() ************************************************/ 24 | /** Use this function to transfer pixel(s) from VDP to CPU. **/ 25 | /*************************************************************/ 26 | byte VDPRead(void); 27 | 28 | /** VDPDraw() ************************************************/ 29 | /** Perform a given V9938 graphical operation. **/ 30 | /*************************************************************/ 31 | byte VDPDraw(register byte Op); 32 | 33 | /** LoopVDP() ************************************************/ 34 | /** Perform a number of steps of the active operation **/ 35 | /*************************************************************/ 36 | void LoopVDP(void); 37 | 38 | #endif /* V9938_H */ 39 | -------------------------------------------------------------------------------- /source/fMSX/Wide.h: -------------------------------------------------------------------------------- 1 | /** fMSX: portable MSX emulator ******************************/ 2 | /** **/ 3 | /** Wide.h **/ 4 | /** **/ 5 | /** This file contains wide (512pix) screen refresh drivers **/ 6 | /** common for X11, VGA, and other "chunky" bitmapped video **/ 7 | /** implementations. It also includes dummy sound drivers **/ 8 | /** for fMSX. **/ 9 | /** **/ 10 | /** Copyright (C) Marat Fayzullin 1994-2017 **/ 11 | /** You are not allowed to distribute this software **/ 12 | /** commercially. Please, notify me, if you make any **/ 13 | /** changes to this file. **/ 14 | /*************************************************************/ 15 | #ifndef NARROW 16 | 17 | /** ClearLine512() *******************************************/ 18 | /** Clear 512 pixels from P with color C. **/ 19 | /*************************************************************/ 20 | static void ClearLine512(register pixel *P,register pixel C) 21 | { 22 | register int J; 23 | 24 | for(J=0;J<512;J++) P[J]=C; 25 | } 26 | 27 | /** RefreshBorder512() ***************************************/ 28 | /** This function is called from RefreshLine#() to refresh **/ 29 | /** the screen border. It returns a pointer to the start of **/ 30 | /** scanline Y in XBuf or 0 if scanline is beyond XBuf. **/ 31 | /*************************************************************/ 32 | pixel *RefreshBorder512(register byte Y,register pixel C) 33 | { 34 | register pixel *P; 35 | register int H; 36 | 37 | /* First line number in the buffer */ 38 | if(!Y) FirstLine=(ScanLines212? 8:18)+VAdjust; 39 | 40 | /* Return 0 if we've run out of the screen buffer due to overscan */ 41 | if(Y+FirstLine>=HEIGHT) return(0); 42 | 43 | /* Set up the transparent color */ 44 | XPal[0]=(!BGColor||SolidColor0)? XPal0:XPal[BGColor]; 45 | 46 | /* Start of the buffer */ 47 | P=(pixel *)WBuf; 48 | 49 | /* Paint top of the screen */ 50 | if(!Y) for(H=2*WIDTH*FirstLine-1;H>=0;H--) P[H]=C; 51 | 52 | /* Start of the line */ 53 | P+=2*WIDTH*(FirstLine+Y); 54 | 55 | /* Paint left/right borders */ 56 | for(H=(WIDTH-256)+2*HAdjust;H>0;H--) P[H-1]=C; 57 | for(H=(WIDTH-256)-2*HAdjust;H>0;H--) P[2*WIDTH-H]=C; 58 | 59 | /* Paint bottom of the screen */ 60 | H=ScanLines212? 212:192; 61 | if(Y==H-1) for(H=2*WIDTH*(HEIGHT-H-FirstLine+1)-2;H>=2*WIDTH;H--) P[H]=C; 62 | 63 | /* Return pointer to the scanline in XBuf */ 64 | return(P+WIDTH-256+2*HAdjust); 65 | } 66 | 67 | /** RefreshScr6() ********************************************/ 68 | /** Function to be called to update SCREEN 6. **/ 69 | /*************************************************************/ 70 | void RefreshLine6(register byte Y) 71 | { 72 | register pixel *P; 73 | register byte X,*T,*R,C; 74 | byte ZBuf[304]; 75 | 76 | P=RefreshBorder512(Y,XPal[BGColor&0x03]); 77 | if(!P) return; 78 | 79 | if(!ScreenON) ClearLine512(P,XPal[BGColor&0x03]); 80 | else 81 | { 82 | ColorSprites(Y,ZBuf); 83 | R=ZBuf+32; 84 | T=ChrTab+(((int)(Y+VScroll)<<7)&ChrTabM&0x7FFF); 85 | 86 | for(X=0;X<64;X++) 87 | { 88 | C=R[0];P[0]=XPal[C? C:T[0]>>6]; 89 | C=R[0];P[1]=XPal[C? C:(T[0]>>4)&0x03]; 90 | C=R[1];P[2]=XPal[C? C:(T[0]>>2)&0x03]; 91 | C=R[1];P[3]=XPal[C? C:T[0]&0x03]; 92 | C=R[2];P[4]=XPal[C? C:T[1]>>6]; 93 | C=R[2];P[5]=XPal[C? C:(T[1]>>4)&0x03]; 94 | C=R[3];P[6]=XPal[C? C:(T[1]>>2)&0x03]; 95 | C=R[3];P[7]=XPal[C? C:T[1]&0x03]; 96 | R+=4;P+=8;T+=2; 97 | } 98 | } 99 | } 100 | 101 | /** RefreshScr7() ********************************************/ 102 | /** Function to be called to update SCREEN 7. **/ 103 | /*************************************************************/ 104 | void RefreshLine7(register byte Y) 105 | { 106 | register pixel *P; 107 | register byte C,X,*T,*R; 108 | byte ZBuf[304]; 109 | 110 | P=RefreshBorder512(Y,XPal[BGColor]); 111 | if(!P) return; 112 | 113 | if(!ScreenON) ClearLine512(P,XPal[BGColor]); 114 | else 115 | { 116 | ColorSprites(Y,ZBuf); 117 | R=ZBuf+32; 118 | T=ChrTab+(((int)(Y+VScroll)<<8)&ChrTabM&0xFFFF); 119 | 120 | for(X=0;X<64;X++) 121 | { 122 | C=R[0];P[0]=XPal[C? C:T[0]>>4]; 123 | C=R[0];P[1]=XPal[C? C:T[0]&0x0F]; 124 | C=R[1];P[2]=XPal[C? C:T[1]>>4]; 125 | C=R[1];P[3]=XPal[C? C:T[1]&0x0F]; 126 | C=R[2];P[4]=XPal[C? C:T[2]>>4]; 127 | C=R[2];P[5]=XPal[C? C:T[2]&0x0F]; 128 | C=R[3];P[6]=XPal[C? C:T[3]>>4]; 129 | C=R[3];P[7]=XPal[C? C:T[3]&0x0F]; 130 | R+=4;P+=8;T+=4; 131 | } 132 | } 133 | } 134 | 135 | /** RefreshTx80() ********************************************/ 136 | /** Function to be called to update TEXT80. **/ 137 | /*************************************************************/ 138 | void RefreshLineTx80(register byte Y) 139 | { 140 | register pixel *P,FC,BC; 141 | register byte X,M,*T,*C,*G; 142 | 143 | BC=XPal[BGColor]; 144 | P=RefreshBorder512(Y,BC); 145 | if(!P) return; 146 | 147 | if(!ScreenON) ClearLine512(P,BC); 148 | else 149 | { 150 | G=(FontBuf&&(Mode&MSX_FIXEDFONT)? FontBuf:ChrGen)+(Y&0x07); 151 | T=ChrTab+((80*(Y>>3))&ChrTabM); 152 | C=ColTab+((10*(Y>>3))&ColTabM); 153 | 154 | P[0]=P[1]=P[2]=P[3]=P[4]=P[5]=P[6]=P[7]=P[8]= 155 | P[9]=P[10]=P[11]=P[12]=P[13]=P[14]=P[15]= 156 | P[16]=P[17]=XPal[BGColor]; 157 | P+=18; 158 | 159 | for(X=M=0;X<80;X++,T++,P+=6) 160 | { 161 | if(!(X&0x07)) M=*C++; 162 | if(M&0x80) { FC=XPal[XFGColor];BC=XPal[XBGColor]; } 163 | else { FC=XPal[FGColor];BC=XPal[BGColor]; } 164 | M<<=1; 165 | Y=*(G+((int)*T<<3)); 166 | P[0]=Y&0x80? FC:BC; 167 | P[1]=Y&0x40? FC:BC; 168 | P[2]=Y&0x20? FC:BC; 169 | P[3]=Y&0x10? FC:BC; 170 | P[4]=Y&0x08? FC:BC; 171 | P[5]=Y&0x04? FC:BC; 172 | } 173 | 174 | P[0]=P[1]=P[2]=P[3]=P[4]=P[5]=P[6]=P[7]=P[8]= 175 | P[9]=P[10]=P[11]=P[12]=P[13]=XPal[BGColor]; 176 | } 177 | } 178 | 179 | #endif /* !NARROW */ 180 | -------------------------------------------------------------------------------- /source/fMSX/fMSX.c: -------------------------------------------------------------------------------- 1 | /** fMSX: portable MSX emulator ******************************/ 2 | /** **/ 3 | /** fMSX.c **/ 4 | /** **/ 5 | /** This file contains generic main() procedure statrting **/ 6 | /** the emulation. **/ 7 | /** **/ 8 | /** Copyright (C) Marat Fayzullin 1994-2017 **/ 9 | /** You are not allowed to distribute this software **/ 10 | /** commercially. Please, notify me, if you make any **/ 11 | /** changes to this file. **/ 12 | /*************************************************************/ 13 | 14 | #include "MSX.h" 15 | #include "Help.h" 16 | #include "EMULib.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | static const char *Options[]= 24 | { 25 | "verbose","skip","pal","ntsc","help", 26 | "printer","serial","diska","diskb","tape","font","logsnd","state", 27 | "ram","vram","rom","auto","noauto","msx1","msx2","msx2+","joy", 28 | "home","simbdos","wd1793","sound","nosound","trap","sync","nosync", 29 | "scale","static","nostatic","vsync","480","200", 30 | 0 31 | }; 32 | 33 | extern const char *Title;/* Program title */ 34 | extern int UseSound; /* Sound mode */ 35 | extern int UseZoom; /* Zoom factor (#ifdef UNIX) */ 36 | extern int UseEffects; /* EFF_* bits, ORed (UNIX/MAEMO/MSDOS) */ 37 | extern int UseStatic; /* Use static colors (#ifdef MSDOS) */ 38 | extern int FullScreen; /* Use 640x480 screen (#ifdef MSDOS) */ 39 | extern int SyncFreq; /* Sync scr updates (UNIX/MAEMO/MSDOS) */ 40 | 41 | /** Zero-terminated arrays of disk names for each drive ******/ 42 | extern const char *Disks[2][MAXDISKS+1]; 43 | 44 | /** main() ***************************************************/ 45 | /** This is a main() function used in Unix and MSDOS ports. **/ 46 | /** It parses command line arguments, sets emulation **/ 47 | /** parameters, and passes control to the emulation itself. **/ 48 | /*************************************************************/ 49 | int fmsxInit() 50 | { 51 | int CartCount,TypeCount; 52 | int JoyCount,DiskCount[2]; 53 | int N,J; 54 | 55 | 56 | 57 | 58 | Verbose=1; 59 | SETJOYTYPE(0,1&0x03); 60 | 61 | /* Clear everything */ 62 | CartCount=TypeCount=JoyCount=0; 63 | DiskCount[0]=DiskCount[1]=0; 64 | 65 | /* Default disk images */ 66 | Disks[0][1]=Disks[1][1]=0; 67 | Disks[0][0]=DSKName[0]; 68 | Disks[1][0]=DSKName[1]; 69 | 70 | 71 | 72 | /* Terminate disk lists and set initial disk names */ 73 | if(DiskCount[0]) { Disks[0][DiskCount[0]]=0;DSKName[0]=Disks[0][0]; } 74 | if(DiskCount[1]) { Disks[1][DiskCount[1]]=0;DSKName[1]=Disks[1][0]; } 75 | 76 | /* Start fMSX! */ 77 | if(!InitMachine()) return(1); 78 | StartMSX(Mode,32,4); 79 | TrashMSX(); 80 | TrashMachine(); 81 | return(0); 82 | } 83 | -------------------------------------------------------------------------------- /source/fMSX/msxaudio/fmopl.h: -------------------------------------------------------------------------------- 1 | #ifndef __FMOPL_H_ 2 | #define __FMOPL_H_ 3 | 4 | /* for MSX-AUDIO specifics */ 5 | #define MSX_AUDIO 6 | 7 | /* --- system optimize --- */ 8 | /* select bit size of output : 8 or 16 */ 9 | #define OPL_OUTPUT_BIT 16 10 | 11 | /* compiler dependence */ 12 | #ifndef OSD_CPU_H 13 | #define OSD_CPU_H 14 | typedef unsigned char UINT8; /* unsigned 8bit */ 15 | typedef unsigned short UINT16; /* unsigned 16bit */ 16 | typedef unsigned int UINT32; /* unsigned 32bit */ 17 | typedef signed char INT8; /* signed 8bit */ 18 | typedef signed short INT16; /* signed 16bit */ 19 | typedef signed int INT32; /* signed 32bit */ 20 | #endif 21 | 22 | #if (OPL_OUTPUT_BIT==16) 23 | typedef INT16 OPLSAMPLE; 24 | #endif 25 | #if (OPL_OUTPUT_BIT==8) 26 | typedef unsigned char OPLSAMPLE; 27 | #endif 28 | 29 | #include "ymdeltat.h" 30 | 31 | /* !!!!! here is private section , do not access there member direct !!!!! */ 32 | 33 | #define OPL_TYPE_WAVESEL 0x01 /* waveform select */ 34 | #define OPL_TYPE_ADPCM 0x02 /* DELTA-T ADPCM unit */ 35 | #define OPL_TYPE_KEYBOARD 0x04 /* keyboard interface */ 36 | #define OPL_TYPE_IO 0x08 /* I/O port */ 37 | 38 | /* ---------- OPL one of slot ---------- */ 39 | typedef struct fm_opl_slot { 40 | INT32 TL; /* total level :TL << 8 */ 41 | INT32 TLL; /* adjusted now TL */ 42 | UINT8 KSR; /* key scale rate :(shift down bit) */ 43 | INT32 *AR; /* attack rate :&AR_TABLE[AR<<2] */ 44 | INT32 *DR; /* decay rate :&DR_TALBE[DR<<2] */ 45 | INT32 SL; /* sustin level :SL_TALBE[SL] */ 46 | INT32 *RR; /* release rate :&DR_TABLE[RR<<2] */ 47 | UINT8 ksl; /* keyscale level :(shift down bits) */ 48 | UINT8 ksr; /* key scale rate :kcode>>KSR */ 49 | UINT32 mul; /* multiple :ML_TABLE[ML] */ 50 | UINT32 Cnt; /* frequency count : */ 51 | UINT32 Incr; /* frequency step : */ 52 | /* envelope generator state */ 53 | UINT8 eg_typ; /* envelope type flag */ 54 | UINT8 evm; /* envelope phase */ 55 | INT32 evc; /* envelope counter */ 56 | INT32 eve; /* envelope counter end point */ 57 | INT32 evs; /* envelope counter step */ 58 | INT32 evsa; /* envelope step for AR :AR[ksr] */ 59 | INT32 evsd; /* envelope step for DR :DR[ksr] */ 60 | INT32 evsr; /* envelope step for RR :RR[ksr] */ 61 | /* LFO */ 62 | UINT8 ams; /* ams flag */ 63 | UINT8 vib; /* vibrate flag */ 64 | /* wave selector */ 65 | INT32 **wavetable; 66 | }OPL_SLOT; 67 | 68 | /* ---------- OPL one of channel ---------- */ 69 | typedef struct fm_opl_channel { 70 | OPL_SLOT SLOT[2]; 71 | UINT8 CON; /* connection type */ 72 | UINT8 FB; /* feed back :(shift down bit) */ 73 | INT32 *connect1; /* slot1 output pointer */ 74 | INT32 *connect2; /* slot2 output pointer */ 75 | INT32 op1_out[2]; /* slot1 output for selfeedback */ 76 | /* phase generator state */ 77 | UINT32 block_fnum; /* block+fnum : */ 78 | UINT8 kcode; /* key code : KeyScaleCode */ 79 | UINT32 fc; /* Freq. Increment base */ 80 | UINT32 ksl_base; /* KeyScaleLevel Base step */ 81 | UINT8 keyon; /* key on/off flag */ 82 | } OPL_CH; 83 | 84 | /* OPL state */ 85 | typedef struct fm_opl_f { 86 | UINT8 type; /* chip type */ 87 | int clock; /* master clock (Hz) */ 88 | int rate; /* sampling rate (Hz) */ 89 | double freqbase; /* frequency base */ 90 | double TimerBase; /* Timer base time (==sampling time) */ 91 | UINT8 address; /* address register */ 92 | UINT8 status; /* status flag */ 93 | UINT8 statusmask; /* status mask */ 94 | UINT32 mode; /* Reg.08 : CSM , notesel,etc. */ 95 | /* Timer */ 96 | int T[2]; /* timer counter */ 97 | UINT8 st[2]; /* timer enable */ 98 | /* FM channel slots */ 99 | OPL_CH *P_CH; /* pointer of CH */ 100 | int max_ch; /* maximum channel */ 101 | /* Rythm sention */ 102 | UINT8 rythm; /* Rythm mode , key flag */ 103 | /* Delta-T ADPCM unit (Y8950) */ 104 | YM_DELTAT *deltat; /* DELTA-T ADPCM */ 105 | /* Keyboard / I/O interface unit (Y8950) */ 106 | UINT8 portDirection; 107 | UINT8 portLatch; 108 | /* time tables */ 109 | INT32 AR_TABLE[75]; /* atttack rate tables */ 110 | INT32 DR_TABLE[75]; /* decay rate tables */ 111 | UINT32 FN_TABLE[1024]; /* fnumber -> increment counter */ 112 | /* LFO */ 113 | INT32 *ams_table; 114 | INT32 *vib_table; 115 | INT32 amsCnt; 116 | INT32 amsIncr; 117 | INT32 vibCnt; 118 | INT32 vibIncr; 119 | /* wave selector enable flag */ 120 | UINT8 wavesel; 121 | } FM_OPL; 122 | 123 | /* ---------- Generic interface section ---------- */ 124 | #define OPL_TYPE_YM3526 (0) 125 | #define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL) 126 | #define OPL_TYPE_Y8950 (OPL_TYPE_ADPCM|OPL_TYPE_KEYBOARD|OPL_TYPE_IO) 127 | 128 | FM_OPL *OPLCreate(int type, int clock, int rate, int sampleram); 129 | void OPLDestroy(FM_OPL *OPL); 130 | 131 | void OPLResetChip(FM_OPL *OPL); 132 | int OPLWrite(FM_OPL *OPL,int a,int v); 133 | void OPLWriteReg(FM_OPL *OPL, int r, int v); 134 | unsigned char OPLRead(FM_OPL *OPL,int a); 135 | int OPLTimerOver(FM_OPL *OPL,int c); 136 | 137 | INT16 Y8950UpdateOne(FM_OPL *OPL); 138 | 139 | #endif 140 | -------------------------------------------------------------------------------- /source/fMSX/msxaudio/readme.txt: -------------------------------------------------------------------------------- 1 | This code is taken from Xmame/Xmess 0.36b. Some changes were made for support 2 | of sample loading for the MSX-AUDIO and to make it work in fMSX-SDL. 3 | -------------------------------------------------------------------------------- /source/fMSX/msxaudio/ymdeltat.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** 3 | ** File: ymdeltat.c 4 | ** 5 | ** YAMAHA DELTA-T adpcm sound emulation subroutine 6 | ** used by fmopl.c(v0.36e-) and fm.c(v0.36c-) 7 | ** 8 | ** Base program is YM2610 emulator by Hiromitsu Shioya. 9 | ** Written by Tatsuyuki Satoh 10 | ** 11 | ** sound chips who has this unit 12 | ** 13 | ** YM2608 OPNA 14 | ** YM2610/B OPNB 15 | ** Y8950 MSX AUDIO 16 | ** 17 | ** 18 | */ 19 | 20 | #include "ymdeltat.h" 21 | 22 | UINT8 *ym_deltat_memory; /* memory pointer */ 23 | 24 | /* Forecast to next Forecast (rate = *8) */ 25 | /* 1/8 , 3/8 , 5/8 , 7/8 , 9/8 , 11/8 , 13/8 , 15/8 */ 26 | const INT32 ym_deltat_decode_tableB1[16] = { 27 | 1, 3, 5, 7, 9, 11, 13, 15, 28 | -1, -3, -5, -7, -9, -11, -13, -15, 29 | }; 30 | /* delta to next delta (rate= *64) */ 31 | /* 0.9 , 0.9 , 0.9 , 0.9 , 1.2 , 1.6 , 2.0 , 2.4 */ 32 | const INT32 ym_deltat_decode_tableB2[16] = { 33 | 57, 57, 57, 57, 77, 102, 128, 153, 34 | 57, 57, 57, 57, 77, 102, 128, 153 35 | }; 36 | 37 | 38 | /* DELTA-T-ADPCM write register */ 39 | void YM_DELTAT_ADPCM_Write(YM_DELTAT *DELTAT,int r,int v) 40 | { 41 | if(r>=0x10) return; 42 | DELTAT->reg[r] = v; /* stock data */ 43 | DELTAT->memread=0; /* reset mem->cpu transfer */ 44 | switch( r ){ 45 | case 0x00: /* START,REC,MEMDATA,REPEAT,SPOFF,--,--,RESET */ 46 | case 0x60: /* write buffer MEMORY from PCM data port */ 47 | case 0x20: /* read buffer MEMORY to PCM data port */ 48 | if( v&0x80 ){ 49 | DELTAT->portstate = v&0x90; /* start req,memory mode,repeat flag copy */ 50 | /**** start ADPCM ****/ 51 | DELTAT->volume_w_step = (double)DELTAT->volume * DELTAT->step / (1<now_addr = (DELTAT->start)<<1; 53 | DELTAT->now_step = (1<step; 54 | /*adpcm->adpcmm = 0;*/ 55 | DELTAT->adpcmx = 0; 56 | DELTAT->adpcml = 0; 57 | DELTAT->adpcmd = YM_DELTAT_DELTA_DEF; 58 | DELTAT->next_leveling=0; 59 | DELTAT->flag = 1; /* start ADPCM */ 60 | DELTAT->eos = 0; 61 | 62 | if( !DELTAT->step ) 63 | { 64 | DELTAT->flag = 0; 65 | DELTAT->eos = 1; 66 | DELTAT->portstate = 0x00; 67 | } 68 | /**** PCM memory check & limit check ****/ 69 | if(DELTAT->memory_size == 0){ /* Check memory Mapped */ 70 | DELTAT->flag = 0; 71 | DELTAT->eos = 1; 72 | //DELTAT->portstate = 0x00; 73 | }else{ 74 | if( DELTAT->end >= DELTAT->memory_size ) 75 | { /* Check End in Range */ 76 | DELTAT->end = DELTAT->memory_size - 1; 77 | } 78 | if( DELTAT->start >= DELTAT->memory_size ) 79 | { /* Check Start in Range */ 80 | DELTAT->flag = 0; 81 | DELTAT->eos = 1; 82 | DELTAT->portstate = 0x00; 83 | } 84 | } 85 | } else if( v&0x01 ){ 86 | DELTAT->flag = 0; 87 | DELTAT->eos = 1; 88 | //DELTAT->start = 0; 89 | //DELTAT->end = 0; 90 | //DELTAT->read_pointer = 0; 91 | //DELTAT->write_pointer = 0; 92 | DELTAT->portstate = 0x00; 93 | } 94 | break; 95 | case 0x01: /* L,R,-,-,SAMPLE,DA/AD,RAMTYPE,ROM */ 96 | DELTAT->portcontrol = v&0xff; 97 | DELTAT->pan = &DELTAT->output_pointer[(v>>6)&0x03]; 98 | break; 99 | case 0x02: /* Start Address L */ 100 | case 0x03: /* Start Address H */ 101 | DELTAT->start = (DELTAT->reg[0x3]*0x0100 | DELTAT->reg[0x2]) << DELTAT->portshift; 102 | DELTAT->write_pointer = 0; 103 | DELTAT->read_pointer = 0; 104 | break; 105 | case 0x04: /* Stop Address L */ 106 | case 0x05: /* Stop Address H */ 107 | DELTAT->end = (DELTAT->reg[0x5]*0x0100 | DELTAT->reg[0x4]) << DELTAT->portshift; 108 | DELTAT->end += (1<portshift) - 1; 109 | break; 110 | case 0x06: /* Prescale L (PCM and Recoard frq) */ 111 | case 0x07: /* Proscale H */ 112 | break; 113 | case 0x08: /* ADPCM data */ 114 | if ( (DELTAT->start+DELTAT->write_pointer) < DELTAT->memory_size && 115 | (DELTAT->start+DELTAT->write_pointer) <= DELTAT->end ) 116 | { 117 | DELTAT->memory[DELTAT->start+DELTAT->write_pointer] = v; 118 | DELTAT->write_pointer++; 119 | DELTAT->eos=0; 120 | } 121 | else 122 | { 123 | DELTAT->write_pointer=0; 124 | DELTAT->start=0; 125 | DELTAT->eos=1; 126 | } 127 | break; 128 | case 0x09: /* DELTA-N L (ADPCM Playback Prescaler) */ 129 | case 0x0a: /* DELTA-N H */ 130 | DELTAT->delta = (DELTAT->reg[0xa]*0x0100 | DELTAT->reg[0x9]); 131 | DELTAT->step = (UINT32)((double)(DELTAT->delta*(1<<(YM_DELTAT_SHIFT-16)))*(DELTAT->freqbase)); 132 | DELTAT->volume_w_step = (double)DELTAT->volume * DELTAT->step / (1<volume; 137 | DELTAT->volume = (v&0xff)*(DELTAT->output_range/256) / YM_DELTAT_DECODE_RANGE; 138 | if( oldvol != 0 ) 139 | { 140 | DELTAT->adpcml = (int)((double)DELTAT->adpcml / (double)oldvol * (double)DELTAT->volume); 141 | DELTAT->sample_step = (int)((double)DELTAT->sample_step / (double)oldvol * (double)DELTAT->volume); 142 | } 143 | DELTAT->volume_w_step = (int)((double)DELTAT->volume * (double)DELTAT->step / (double)(1<memread<2) 155 | { 156 | DELTAT->eos=0; 157 | DELTAT->memread++; 158 | return 0; 159 | } 160 | if ( (DELTAT->start+DELTAT->read_pointer) < DELTAT->memory_size && 161 | (DELTAT->start+DELTAT->read_pointer) <= DELTAT->end ) 162 | { 163 | v = DELTAT->memory[DELTAT->start+DELTAT->read_pointer]; 164 | DELTAT->read_pointer++; 165 | DELTAT->eos=0; 166 | } 167 | else 168 | { 169 | DELTAT->read_pointer=0; 170 | DELTAT->start=0; 171 | DELTAT->eos=1; 172 | } 173 | 174 | return v; 175 | } 176 | 177 | 178 | void YM_DELTAT_ADPCM_Reset(YM_DELTAT *DELTAT,int pan) 179 | { 180 | DELTAT->now_addr = 0; 181 | DELTAT->now_step = 0; 182 | DELTAT->step = 0; 183 | DELTAT->start = 0; 184 | DELTAT->end = 0; 185 | DELTAT->eos = 0; 186 | /* F2610->adpcm[i].delta = 21866; */ 187 | DELTAT->volume = 0; 188 | DELTAT->pan = &DELTAT->output_pointer[pan]; 189 | /* DELTAT->flagMask = 0; */ 190 | DELTAT->arrivedFlag = 0; 191 | DELTAT->flag = 0; 192 | DELTAT->adpcmx = 0; 193 | DELTAT->adpcmd = 127; 194 | DELTAT->adpcml = 0; 195 | /*DELTAT->adpcmm = 0;*/ 196 | DELTAT->volume_w_step = 0; 197 | DELTAT->next_leveling = 0; 198 | DELTAT->portstate = 0; 199 | DELTAT->memread = 0; 200 | /* DELTAT->portshift = 8; */ 201 | } 202 | 203 | 204 | void YM_DELTAT_ADPCM_CALC(YM_DELTAT *DELTAT) 205 | { 206 | UINT32 step; 207 | int data; 208 | INT32 old_m; 209 | INT32 now_leveling; 210 | INT32 delta_next; 211 | 212 | DELTAT->now_step += DELTAT->step; 213 | if ( DELTAT->now_step >= (1<now_step >> YM_DELTAT_SHIFT; 216 | DELTAT->now_step &= (1<now_addr > (DELTAT->end<<1) ) { 219 | if( DELTAT->portstate&0x10 ){ 220 | /**** repeat start ****/ 221 | DELTAT->now_addr = DELTAT->start<<1; 222 | DELTAT->adpcmx = 0; 223 | DELTAT->adpcmd = YM_DELTAT_DELTA_DEF; 224 | DELTAT->next_leveling = 0; 225 | DELTAT->flag = 1; 226 | DELTAT->eos = 0; 227 | 228 | }else{ 229 | DELTAT->arrivedFlag |= DELTAT->flagMask; 230 | DELTAT->flag = 0; 231 | DELTAT->eos = 1; 232 | DELTAT->adpcml = 0; 233 | now_leveling = 0; 234 | return; 235 | } 236 | } 237 | if( DELTAT->now_addr&1 ) data = DELTAT->now_data & 0x0f; 238 | else 239 | { 240 | DELTAT->now_data = *(ym_deltat_memory+(DELTAT->now_addr>>1)); 241 | data = DELTAT->now_data >> 4; 242 | } 243 | DELTAT->now_addr++; 244 | /* shift Measurement value */ 245 | old_m = DELTAT->adpcmx/*adpcmm*/; 246 | /* ch->adpcmm = YM_DELTAT_Limit( ch->adpcmx + (decode_tableB3[data] * ch->adpcmd / 8) ,YM_DELTAT_DECODE_MAX, YM_DELTAT_DECODE_MIN ); */ 247 | /* Forecast to next Forecast */ 248 | DELTAT->adpcmx += (ym_deltat_decode_tableB1[data] * DELTAT->adpcmd / 8); 249 | YM_DELTAT_Limit(DELTAT->adpcmx,YM_DELTAT_DECODE_MAX, YM_DELTAT_DECODE_MIN); 250 | /* delta to next delta */ 251 | DELTAT->adpcmd = (DELTAT->adpcmd * ym_deltat_decode_tableB2[data] ) / 64; 252 | YM_DELTAT_Limit(DELTAT->adpcmd,YM_DELTAT_DELTA_MAX, YM_DELTAT_DELTA_MIN ); 253 | /* shift leveling value */ 254 | delta_next = DELTAT->adpcmx/*adpcmm*/ - old_m; 255 | now_leveling = DELTAT->next_leveling; 256 | DELTAT->next_leveling = old_m + (delta_next / 2); 257 | }while(--step); 258 | /*#define YM_DELTAT_CUT_RE_SAMPLING */ 259 | #ifdef YM_DELTAT_CUT_RE_SAMPLING 260 | DELTAT->adpcml = DELTAT->next_leveling * DELTAT->volume; 261 | DELTAT->adpcml = DELTAT->adpcmx/*adpcmm*/ * DELTAT->volume; 262 | } 263 | #else 264 | /* delta step of re-sampling */ 265 | DELTAT->sample_step = (DELTAT->next_leveling - now_leveling) * DELTAT->volume_w_step; 266 | /* output of start point */ 267 | DELTAT->adpcml = now_leveling * DELTAT->volume; 268 | /* adjust to now */ 269 | DELTAT->adpcml += (int)((double)DELTAT->sample_step * ((double)DELTAT->now_step/(double)DELTAT->step)); 270 | } 271 | DELTAT->adpcml += DELTAT->sample_step; 272 | #endif 273 | /* output for work of output channels (outd[OPNxxxx])*/ 274 | *(DELTAT->pan) += DELTAT->adpcml; 275 | } 276 | 277 | -------------------------------------------------------------------------------- /source/fMSX/msxaudio/ymdeltat.h: -------------------------------------------------------------------------------- 1 | #ifndef __YMDELTAT_H_ 2 | #define __YMDELTAT_H_ 3 | 4 | #define YM_DELTAT_SHIFT (16) 5 | 6 | #ifndef OSD_CPU_H 7 | #define OSD_CPU_H 8 | typedef unsigned char UINT8; /* unsigned 8bit */ 9 | typedef unsigned short UINT16; /* unsigned 16bit */ 10 | typedef unsigned int UINT32; /* unsigned 32bit */ 11 | typedef signed char INT8; /* signed 8bit */ 12 | typedef signed short INT16; /* signed 16bit */ 13 | typedef signed int INT32; /* signed 32bit */ 14 | #endif 15 | 16 | /* adpcm type A and type B struct */ 17 | typedef struct deltat_adpcm_state { 18 | UINT8 *memory; 19 | UINT32 memory_size; 20 | double freqbase; 21 | INT32 *output_pointer; /* pointer of output pointers */ 22 | int output_range; 23 | 24 | UINT8 reg[16]; 25 | UINT8 portstate,portcontrol; 26 | int portshift; 27 | int memread; /* first two bytes of mem->cpu transfer are dummy */ 28 | 29 | UINT8 flag; /* port state */ 30 | UINT8 eos; /* end of sample flag */ 31 | UINT8 flagMask; /* arrived flag mask */ 32 | UINT8 now_data; 33 | UINT32 now_addr; 34 | UINT32 now_step; 35 | UINT32 step; 36 | UINT32 start; 37 | UINT32 end; 38 | UINT32 read_pointer; /* used for memory -> sample bank */ 39 | UINT32 write_pointer; /* used for memory -> sample bank */ 40 | UINT32 delta; 41 | INT32 volume; 42 | INT32 *pan; /* &output_pointer[pan] */ 43 | INT32 /*adpcmm,*/ adpcmx, adpcmd; 44 | INT32 adpcml; /* hiro-shi!! */ 45 | 46 | /* leveling and re-sampling state for DELTA-T */ 47 | INT32 volume_w_step; /* volume with step rate */ 48 | INT32 next_leveling; /* leveling value */ 49 | INT32 sample_step; /* step of re-sampling */ 50 | 51 | UINT8 arrivedFlag; /* flag of arrived end address */ 52 | }YM_DELTAT; 53 | 54 | /* static state */ 55 | extern UINT8 *ym_deltat_memory; /* memory pointer */ 56 | 57 | /* before YM_DELTAT_ADPCM_CALC(YM_DELTAT *DELTAT); */ 58 | #define YM_DELTAT_DECODE_PRESET(DELTAT) {ym_deltat_memory = DELTAT->memory;} 59 | 60 | UINT8 YM_DELTAT_ADPCM_Read(YM_DELTAT *DELTAT); 61 | void YM_DELTAT_ADPCM_Write(YM_DELTAT *DELTAT,int r,int v); 62 | void YM_DELTAT_ADPCM_Reset(YM_DELTAT *DELTAT,int pan); 63 | 64 | #endif 65 | 66 | void YM_DELTAT_ADPCM_CALC(YM_DELTAT *DELTAT); 67 | 68 | /* DELTA-T particle adjuster */ 69 | #define YM_DELTAT_DELTA_MAX (24576) 70 | #define YM_DELTAT_DELTA_MIN (127) 71 | #define YM_DELTAT_DELTA_DEF (127) 72 | 73 | #define YM_DELTAT_DECODE_RANGE 32768 74 | #define YM_DELTAT_DECODE_MIN (-(YM_DELTAT_DECODE_RANGE)) 75 | #define YM_DELTAT_DECODE_MAX ((YM_DELTAT_DECODE_RANGE)-1) 76 | 77 | extern const INT32 ym_deltat_decode_tableB1[]; 78 | extern const INT32 ym_deltat_decode_tableB2[]; 79 | 80 | #define YM_DELTAT_Limit(val,max,min) \ 81 | { \ 82 | if ( val > max ) val = max; \ 83 | else if ( val < min ) val = min; \ 84 | } 85 | -------------------------------------------------------------------------------- /source/fMSX/msxmusic/2413tone.h: -------------------------------------------------------------------------------- 1 | /* YM2413 VOICE */ 2 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 3 | 0x61,0x61,0x1e,0x17,0xf0,0x7f,0x07,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 4 | 0x13,0x41,0x0f,0x0d,0xce,0xf5,0x43,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 5 | 0x03,0x01,0x9a,0x04,0xf3,0xf4,0x13,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 6 | 0x21,0x61,0x1d,0x07,0xfa,0x64,0x30,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 7 | 0x22,0x21,0x1e,0x06,0xf0,0x76,0x18,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 8 | 0x31,0x02,0x16,0x05,0x90,0x71,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 9 | 0x21,0x61,0x1d,0x07,0x82,0x80,0x10,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 10 | 0x23,0x21,0x2d,0x16,0xc0,0x70,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 11 | 0x61,0x21,0x1b,0x06,0x64,0x65,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 12 | 0x61,0x61,0x0c,0x18,0x85,0xa0,0x79,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 13 | 0x23,0x21,0x87,0x11,0xf0,0xa4,0x00,0xf7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 14 | 0x97,0xe1,0x28,0x07,0xff,0xf3,0x02,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 15 | 0x61,0x10,0x0c,0x05,0xf2,0xc4,0x40,0xc8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 16 | 0x01,0x01,0x56,0x03,0xb4,0xb2,0x23,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 17 | 0x61,0x41,0x89,0x03,0xf1,0xf4,0xf0,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 18 | 0x04,0x21,0x16,0x00,0xdf,0xf8,0xff,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 19 | 0x23,0x32,0x00,0x00,0xd8,0xf7,0xf8,0xf7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 20 | 0x25,0x18,0x00,0x00,0xf8,0xda,0xf8,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -------------------------------------------------------------------------------- /source/fMSX/msxmusic/emu2149.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | 3 | emu2149.c -- YM2149/AY-3-8910 emulator by Mitsutaka Okazaki 2001 4 | 5 | 2001 04-28 : Version 1.00beta -- 1st Beta Release. 6 | 2001 08-14 : Version 1.10 7 | 2001 10-03 : Version 1.11 -- Added PSG_set_quality(). 8 | 9 | References: 10 | psg.vhd -- 2000 written by Kazuhiro Tsujikawa. 11 | s_fme7.c -- 1999,2000 written by Mamiya (NEZplug). 12 | ay8910.c -- 1998-2001 Author unknown (MAME). 13 | MSX-Datapack -- 1991 ASCII Corp. 14 | AY-3-8910 data sheet 15 | 16 | *****************************************************************************/ 17 | #include 18 | #include 19 | #include 20 | #include "emu2149.h" 21 | 22 | #if defined(_MSC_VER) 23 | #define INLINE __forceinline 24 | #elif defined(__GNUC__) 25 | #define INLINE __inline__ 26 | #else 27 | #define INLINE 28 | #endif 29 | 30 | #define EMU2149_VOL_DEFAULT 1 31 | #define EMU2149_VOL_YM2149 0 32 | #define EMU2149_VOL_AY_3_8910 1 33 | 34 | static e_uint32 voltbl[2][32]= 35 | { 36 | { 0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x05,0x06,0x07,0x09,0x0B,0x0D,0x0F,0x12, 37 | 0x16,0x1A,0x1F,0x25,0x2D,0x35,0x3F,0x4C,0x5A,0x6A,0x7F,0x97,0xB4,0xD6,0xFF,0xFF }, 38 | { 0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x05,0x05,0x07,0x07,0x0B,0x0B,0x0F,0x0F, 39 | 0x16,0x16,0x1F,0x1F,0x2D,0x2D,0x3F,0x3F,0x5A,0x5A,0x7F,0x7F,0xB4,0xB4,0xFF,0xFF } 40 | } ; 41 | 42 | #define GETA_BITS 24 43 | static e_uint32 clk, rate, base_incr, HQ ; 44 | 45 | EMU2149_API void PSG_init(e_uint32 c, e_uint32 r) 46 | { 47 | clk = c ; 48 | rate = r ; 49 | PSG_set_quality(0) ; 50 | } 51 | 52 | EMU2149_API void PSG_set_quality(e_uint32 q) 53 | { 54 | if(q) 55 | base_incr = 1<voltbl = voltbl[EMU2149_VOL_YM2149] ; 81 | break ; 82 | case 2: 83 | psg->voltbl = voltbl[EMU2149_VOL_AY_3_8910] ; 84 | break ; 85 | default: 86 | psg->voltbl = voltbl[EMU2149_VOL_DEFAULT] ; 87 | break ; 88 | } 89 | } 90 | 91 | EMU2149_API void PSG_reset(PSG *psg) 92 | { 93 | int i ; 94 | 95 | psg->base_count = 0 ; 96 | 97 | for(i=0;i<3;i++){ 98 | psg->count[i] = 0x1000 ; 99 | psg->freq[i] = 0 ; 100 | psg->edge[i] = 0 ; 101 | psg->volume[i] = 0 ; 102 | psg->mute[i] = 0 ; 103 | } 104 | 105 | for(i=0;i<16;i++) psg->reg[i] = 0 ; 106 | psg->adr = 0 ; 107 | 108 | psg->realstep = (e_uint32)((1<<31)/rate) ; 109 | psg->psgstep = (e_uint32)((1<<31)/(clk/16)) ; 110 | psg->psgtime = 0 ; 111 | 112 | psg->noise_seed = 0xffff ; 113 | psg->noise_count = 0x40 ; 114 | psg->noise_freq = 0 ; 115 | 116 | psg->env_volume = 0 ; 117 | psg->env_ptr = 0 ; 118 | psg->env_reverse = 0 ; 119 | psg->env_freq = 0 ; 120 | psg->env_count = 0 ; 121 | psg->env_enable = 0 ; 122 | 123 | psg->out = 0 ; 124 | } 125 | 126 | EMU2149_API void PSG_delete(PSG *psg) 127 | { 128 | free(psg) ; 129 | } 130 | 131 | EMU2149_API void PSG_close() 132 | { 133 | } 134 | 135 | EMU2149_API e_uint8 PSG_readIO(PSG *psg) 136 | { 137 | return (e_uint8)(psg->reg[psg->adr]) ; 138 | } 139 | 140 | EMU2149_API e_uint8 PSG_readReg(PSG *psg, e_uint32 reg) 141 | { 142 | 143 | return (e_uint8)(psg->reg[reg&0x1f]) ; 144 | 145 | } 146 | 147 | EMU2149_API void PSG_writeIO(PSG *psg, e_uint32 adr, e_uint32 val) 148 | { 149 | if(adr & 1) PSG_writeReg(psg, psg->adr, val) ; 150 | else psg->adr = val & 0x1f ; 151 | } 152 | 153 | EMU2149_API void PSG_writeReg(PSG *psg, e_uint32 reg, e_uint32 val) 154 | { 155 | 156 | int c ; 157 | 158 | if (reg>15) return ; 159 | 160 | psg->reg[reg] = (e_uint8)(val & 0xff) ; 161 | 162 | switch(reg) 163 | { 164 | case 0: case 2: case 4: 165 | case 1: case 3: case 5: 166 | c = reg >> 1 ; 167 | psg->freq[c] = ( (psg->reg[c*2+1]&15) << 8 ) + psg->reg[c*2] ; 168 | break ; 169 | 170 | case 6: 171 | psg->noise_freq = val==0 ? 1 : ((val & 31) << 1) ; 172 | break ; 173 | 174 | case 7: 175 | psg->tmask[0] = (val&1) ; 176 | psg->tmask[1] = (val&2) ; 177 | psg->tmask[2] = (val&4) ; 178 | psg->nmask[0] = (val&8) ; 179 | psg->nmask[1] = (val&16) ; 180 | psg->nmask[2] = (val&32) ; 181 | break ; 182 | 183 | case 8: 184 | case 9: 185 | case 10: 186 | psg->volume[reg-8] = val << 1 ; 187 | if(val&16) psg->env_enable = 1 ; 188 | break ; 189 | 190 | case 11: 191 | case 12: 192 | psg->env_freq = (psg->reg[12] << 8) + psg->reg[11] ; 193 | break ; 194 | 195 | case 13: 196 | val = val&15 ; 197 | if(val<4) val = 9 ; 198 | else if(val<8) val = 15 ; 199 | psg->env_count = 0x10000 - psg->env_freq ; 200 | psg->env_ptr = 0 ; 201 | psg->env_hold = (val&1)^1 ; 202 | psg->env_reverse = ((val>>2)&1)^1 ; 203 | psg->env_alt = ((val>>1)&1)^(val&1) ; 204 | break ; 205 | 206 | case 14: 207 | case 15: 208 | default: 209 | break; 210 | 211 | } 212 | 213 | return ; 214 | 215 | } 216 | 217 | INLINE static e_int16 calc(PSG *psg) 218 | { 219 | 220 | int i,noise ; 221 | e_uint32 incr ; 222 | e_int16 mix = 0 ; 223 | 224 | psg->base_count += base_incr ; 225 | incr = (psg->base_count >> GETA_BITS) ; 226 | psg->base_count &= (1 << GETA_BITS) - 1 ; 227 | 228 | /* Envelope */ 229 | if(psg->env_enable) 230 | { 231 | psg->env_count += incr ; 232 | if(psg->env_count&0x10000) 233 | { 234 | psg->env_ptr = (psg->env_ptr + 1)&31 ; 235 | if(psg->env_ptr == 0) 236 | { 237 | psg->env_enable = psg->env_hold ; 238 | psg->env_reverse = psg->env_reverse^psg->env_alt ; 239 | } 240 | psg->env_count -= psg->env_freq ; 241 | } 242 | } 243 | 244 | /* Noise */ 245 | psg->noise_count += incr ; 246 | if(psg->noise_count&0x40) 247 | { 248 | if(psg->noise_seed&1) psg->noise_seed^= 0x24000 ; 249 | psg->noise_seed >>= 1 ; 250 | psg->noise_count -= psg->noise_freq ; 251 | } 252 | 253 | noise = psg->noise_seed & 1 ; 254 | 255 | /* Tone */ 256 | for(i=0;i<3;i++) 257 | { 258 | psg->count[i] += incr ; 259 | if(psg->count[i]&0x1000) 260 | { 261 | if(psg->freq[i]>1) 262 | { 263 | psg->edge[i] = !psg->edge[i] ; 264 | psg->count[i] -= psg->freq[i] ; 265 | } 266 | else 267 | { 268 | psg->edge[i] = 1 ; 269 | } 270 | } 271 | 272 | if(psg->mute[i]) continue ; 273 | 274 | if((psg->tmask[i]||psg->edge[i])&&(psg->nmask[i]||noise)) 275 | { 276 | if((psg->volume[i]&32)==0) 277 | mix += psg->voltbl[psg->volume[i]&31] ; 278 | else if(psg->env_reverse) 279 | mix += psg->voltbl[31-psg->env_ptr] ; 280 | else 281 | mix += psg->voltbl[psg->env_ptr] ; 282 | } 283 | else if(psg->tmask[i]&&psg->nmask[i]) 284 | { 285 | mix += psg->voltbl[psg->volume[i]&31] ; 286 | } 287 | } 288 | 289 | return mix ; 290 | 291 | } 292 | 293 | EMU2149_API e_int16 PSG_calc(PSG *psg) 294 | { 295 | if(!HQ) return calc(psg) << 4 ; 296 | 297 | /* Simple rate converter */ 298 | while (psg->realstep > psg->psgtime) 299 | { 300 | psg->psgtime += psg->psgstep ; 301 | psg->out += calc(psg) ; 302 | psg->out >>= 1 ; 303 | } 304 | 305 | psg->psgtime = psg->psgtime - psg->realstep ; 306 | 307 | return (e_int16)( psg->out << 4 ) ; 308 | } 309 | 310 | 311 | -------------------------------------------------------------------------------- /source/fMSX/msxmusic/emu2149.h: -------------------------------------------------------------------------------- 1 | /* emu2149.h */ 2 | #ifndef _EMU2149_H_ 3 | #define _EMU2149_H_ 4 | #include "emutypes.h" 5 | 6 | #ifdef EMU2149_DLL_EXPORTS 7 | #define EMU2149_API __declspec(dllexport) 8 | #elif EMU2149_DLL_IMPORTS 9 | #define EMU2149_API __declspec(dllimport) 10 | #else 11 | #define EMU2149_API 12 | #endif 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | typedef struct { 19 | 20 | /* Volume Table */ 21 | e_uint32 *voltbl ; 22 | 23 | e_uint8 reg[0x20] ; 24 | e_int32 out ; 25 | 26 | e_uint32 count[3] ; 27 | e_uint32 volume[3] ; 28 | e_uint32 freq[3] ; 29 | e_uint32 edge[3] ; 30 | e_uint32 tmask[3] ; 31 | e_uint32 nmask[3] ; 32 | e_uint32 mute[3] ; 33 | 34 | e_uint32 base_count ; 35 | 36 | e_uint32 env_volume ; 37 | e_uint32 env_ptr ; 38 | e_uint32 env_enable ; 39 | e_uint32 env_reverse ; 40 | e_uint32 env_hold ; 41 | e_uint32 env_alt ; 42 | e_uint32 env_freq ; 43 | e_uint32 env_count ; 44 | 45 | e_uint32 noise_seed ; 46 | e_uint32 noise_count ; 47 | e_uint32 noise_freq ; 48 | 49 | /* rate converter */ 50 | e_uint32 realstep ; 51 | e_uint32 psgtime ; 52 | e_uint32 psgstep ; 53 | 54 | /* I/O Ctrl */ 55 | e_uint32 adr ; 56 | 57 | } PSG ; 58 | 59 | EMU2149_API void PSG_init(e_uint32 clk, e_uint32 rate) ; 60 | EMU2149_API void PSG_set_quality(e_uint32 q) ; 61 | EMU2149_API void PSG_close(void) ; 62 | EMU2149_API PSG *PSG_new(void) ; 63 | EMU2149_API void PSG_reset(PSG *) ; 64 | EMU2149_API void PSG_delete(PSG *) ; 65 | EMU2149_API void PSG_writeReg(PSG *, e_uint32 reg, e_uint32 val) ; 66 | EMU2149_API void PSG_writeIO(PSG *psg, e_uint32 adr, e_uint32 val) ; 67 | EMU2149_API e_uint8 PSG_readReg(PSG *psg, e_uint32 reg) ; 68 | EMU2149_API e_uint8 PSG_readIO(PSG *psg) ; 69 | EMU2149_API e_int16 PSG_calc(PSG *) ; 70 | EMU2149_API void PSG_setVolumeMode(PSG *psg, int type) ; 71 | 72 | #ifdef __cplusplus 73 | } 74 | #endif 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /source/fMSX/msxmusic/emu2212.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | 3 | emu2212.c -- S.C.C. emulator by Mitsutaka Okazaki 2001 4 | 5 | 2001 09-30 : Version 1.00 6 | 2001 10-03 : Version 1.01 -- Added SCC_set_quality(). 7 | 8 | *****************************************************************************/ 9 | #include 10 | #include 11 | #include 12 | #include "emu2212.h" 13 | 14 | #if defined(_MSC_VER) 15 | #define INLINE __forceinline 16 | #elif defined(__GNUC__) 17 | #define INLINE __inline__ 18 | #else 19 | #define INLINE 20 | #endif 21 | 22 | #define GETA_BITS 22 23 | 24 | static e_uint32 clk, rate ,base_incr, HQ ; 25 | 26 | EMUSCC_API void SCC_init(e_uint32 c, e_uint32 r) 27 | { 28 | clk = c ; 29 | rate = r ; 30 | SCC_set_quality(0) ; 31 | } 32 | 33 | EMUSCC_API void SCC_set_quality(e_uint32 q) 34 | { 35 | if(q) 36 | base_incr = 2<save_9000 = 0x3f ; 61 | scc->save_BFFE = 0 ; 62 | scc->save_mode = 0 ; 63 | 64 | for(i=0;i<5;i++) 65 | { 66 | for(j=0;j<5;j++) scc->wave[i][j] = 0 ; 67 | scc->count[i] = 0 ; 68 | scc->freq[i] = 0 ; 69 | scc->phase[i] = 0 ; 70 | scc->volume[i] = 0 ; 71 | scc->offset[i] = 0 ; 72 | scc->rotate[i] = 0 ; 73 | } 74 | 75 | scc->enable = 1 ; 76 | scc->ch_enable = 0xff ; 77 | 78 | scc->cycle_4bit = 0 ; 79 | scc->cycle_8bit = 0 ; 80 | scc->refresh = 0 ; 81 | 82 | scc->out = 0 ; 83 | 84 | scc->realstep = (e_uint32)((1<<31)/rate) ; 85 | scc->sccstep = (e_uint32)((1<<31)/(clk/2)) ; 86 | scc->scctime = 0 ; 87 | 88 | return ; 89 | 90 | } 91 | 92 | 93 | EMUSCC_API void SCC_delete(SCC *scc) 94 | { 95 | if(scc!=NULL) free(scc) ; 96 | } 97 | 98 | EMUSCC_API void SCC_close() 99 | { 100 | } 101 | 102 | INLINE static e_int16 calc(SCC *scc) 103 | { 104 | int i ; 105 | e_int32 mix = 0 ; 106 | 107 | for(i=0;i<5;i++){ 108 | 109 | if(!((scc->ch_enable>>i)&1)) continue ; 110 | 111 | scc->count[i] = (scc->count[i] + scc->incr[i]) ; 112 | 113 | if(scc->count[i]&(1<<(GETA_BITS+5))) 114 | { 115 | scc->count[i]&=((1<<(GETA_BITS+5))-1) ; 116 | scc->offset[i] = (scc->offset[i]+31)&scc->rotate[i] ; 117 | } 118 | 119 | scc->phase[i] = ((scc->count[i]>>(GETA_BITS))+scc->offset[i])&0x1f ; 120 | mix += ((((e_int8)(scc->wave[i][scc->phase[i]]) * (e_int8)scc->volume[i]))) >> 4 ; 121 | 122 | } 123 | 124 | return (e_int16)(mix<<4) ; 125 | } 126 | 127 | EMUSCC_API e_int16 SCC_calc(SCC *scc) 128 | { 129 | if(!HQ) return calc(scc) ; 130 | /* Simple rate converter */ 131 | while (scc->realstep > scc->scctime) 132 | { 133 | scc->scctime += scc->sccstep ; 134 | scc->out += calc(scc) ; 135 | scc->out >>= 1 ; 136 | } 137 | 138 | scc->scctime = scc->scctime - scc->realstep ; 139 | 140 | return scc->out ; 141 | } 142 | 143 | INLINE void check_enable(SCC *scc) 144 | { 145 | if((scc->save_BFFE==0x20)&&(scc->save_9000 == 0x80)) scc->enable = 2 ; 146 | else if((scc->save_BFFE==0x00)&&(scc->save_9000 == 0x3F)) scc->enable = 1 ; 147 | else scc->enable = 0 ; 148 | } 149 | 150 | EMUSCC_API e_uint32 SCC_read(SCC *scc, e_uint32 adr) 151 | { 152 | if((adr == 0xBFFE)||(adr == 0xBFFF)) return scc->save_BFFE ; 153 | if(adr == 0x9000) return scc->save_9000 ; 154 | 155 | if(scc->enable==0) return 0 ; 156 | 157 | if(((0x9800<=adr)&&(adr<0x9880))||((0xB800<=adr)&&(adr<0xB8A0))) 158 | { 159 | return scc->wave[(adr&0xe0)>>5][adr&0x1f] ; 160 | } 161 | else if (((0x9880<=adr)&&(adr<0x988A))||((0xB8A0<=adr)&&(adr<0xB8AA))) 162 | { 163 | if(adr&1) return scc->freq[(adr&0x0f)>>1]>>8 ; 164 | else return scc->freq[(adr&0x0f)>>1]&0xff ; 165 | } 166 | else if(((0x988A<=adr)&&(adr<0x988F))||((0xB8AA<=adr)&&(adr<0xB8AF))) 167 | { 168 | return scc->volume[(adr&0x0f)-0x0a] ; 169 | } 170 | else if((adr==0x988F)||(adr==0xB8AF)) 171 | { 172 | return scc->ch_enable ; 173 | } 174 | else if(((0x98C0<=adr)&&(adr<0x98FF))||((0xB8C0<=adr)&&(adr<0xB8DF))) 175 | { 176 | return scc->save_mode ; 177 | } 178 | 179 | return 0 ; 180 | } 181 | 182 | EMUSCC_API void SCC_write(SCC *scc, e_uint32 adr, e_uint32 val) 183 | { 184 | int ch ; 185 | e_uint32 freq ; 186 | 187 | val = val & 0xFF ; 188 | 189 | if((adr == 0xBFFE)||(adr == 0xBFFF)) 190 | { 191 | scc->save_BFFE = (e_uint8)val ; 192 | check_enable(scc) ; 193 | return ; 194 | } 195 | 196 | if(adr == 0x9000) 197 | { 198 | scc->save_9000 = (e_uint8)val ; 199 | check_enable(scc) ; 200 | return ; 201 | } 202 | 203 | if(scc->enable==0) return ; 204 | 205 | if(((0x9800<=adr)&&(adr<0x9880))||((0xB800<=adr)&&(adr<0xB8A0))) 206 | { 207 | 208 | ch = (adr&0xe0)>>5 ; 209 | if(!scc->rotate[ch]) 210 | { 211 | scc->wave[ch][adr&0x1f] = (e_int8)val ; 212 | if((scc->enable&1)&&(ch==3)) scc->wave[4][adr&0x1f] = (e_int8)val ; 213 | } 214 | 215 | } 216 | else if(((0x9880<=adr)&&(adr<0x988A))||((0xB8A0<=adr)&&(adr<0xB8AA))) 217 | { 218 | 219 | ch = (adr&0x0f)>>1 ; 220 | if(adr&1) scc->freq[ch] = ((val&0xf)<<8) | (scc->freq[ch]&0xff); 221 | else scc->freq[ch] = (scc->freq[ch]&0xf00) | (val&0xff) ; 222 | if(scc->refresh) scc->count[ch] = 0 ; 223 | freq = scc->freq[ch] ; 224 | if(scc->cycle_8bit) freq &= 0xff ; 225 | if(scc->cycle_4bit) freq >>= 8 ; 226 | if(freq <= 8) scc->incr[ch] = 0 ; else scc->incr[ch] = base_incr/(freq+1) ; 227 | 228 | } 229 | else if(((0x988A<=adr)&&(adr<0x988F))||((0xB8AA<=adr)&&(adr<0xB8AF))) 230 | { 231 | 232 | ch = ((adr&0x0f)-0x0a) ; 233 | scc->volume[ch] = (e_uint8)(val&0xf) ; 234 | 235 | } 236 | else if((adr==0x988F)||(adr==0xB8AF)) 237 | { 238 | 239 | scc->ch_enable = (e_uint8)val&31 ; 240 | 241 | } 242 | else if(((0x98C0<=adr)&&(adr<0x98FF))||((0xB8C0<=adr)&&(adr<0xB8DF))) 243 | { 244 | scc->save_mode = (e_uint8) val ; 245 | scc->cycle_4bit = val&1 ; 246 | scc->cycle_8bit = val&2 ; 247 | scc->refresh = val&32 ; 248 | if(val&64) for(ch=0;ch<5;ch++) scc->rotate[ch] = 0x1F ; 249 | else for(ch=0;ch<5;ch++) scc->rotate[ch] = 0 ; 250 | if(val&128) scc->rotate[3] = scc->rotate[4] = 0x1F ; 251 | } 252 | 253 | return ; 254 | } 255 | -------------------------------------------------------------------------------- /source/fMSX/msxmusic/emu2212.h: -------------------------------------------------------------------------------- 1 | #ifndef _EMUSCC_H_ 2 | #define _EMUSCC_H_ 3 | 4 | #ifdef EMUSCC_DLL_EXPORTS 5 | #define EMUSCC_API __declspec(dllexport) 6 | #elif EMUSCC_DLL_IMPORTS 7 | #define EMUSCC_API __declspec(dllimport) 8 | #else 9 | #define EMUSCC_API 10 | #endif 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | #include "emutypes.h" 17 | 18 | #define SCC_CACHE_SIZE 1024 // 2^N only. 19 | 20 | typedef struct { 21 | 22 | e_int32 out ; 23 | 24 | int masterVolume ; 25 | 26 | //e_int32 buf ; 27 | 28 | e_uint32 realstep ; 29 | e_uint32 scctime ; 30 | e_uint32 sccstep ; 31 | 32 | e_uint32 incr[5] ; 33 | 34 | e_uint8 save_9000 ; 35 | e_uint8 save_BFFE ; 36 | e_uint8 save_mode ; 37 | 38 | e_int8 wave[5][64] ; 39 | 40 | e_uint32 enable ; 41 | 42 | e_uint32 count[5] ; 43 | e_uint32 freq[5] ; 44 | e_uint32 phase[5] ; 45 | e_uint32 volume[5] ; 46 | e_uint32 offset[5] ; 47 | 48 | int ch_enable ; 49 | 50 | int cycle_4bit ; 51 | int cycle_8bit ; 52 | int refresh ; 53 | int rotate[5] ; 54 | 55 | } SCC ; 56 | 57 | EMUSCC_API void SCC_init(e_uint32 c, e_uint32 r); 58 | EMUSCC_API void SCC_set_quality(e_uint32 q) ; 59 | 60 | EMUSCC_API SCC *SCC_new(void) ; 61 | EMUSCC_API void SCC_reset(SCC *scc) ; 62 | EMUSCC_API void SCC_delete(SCC *scc) ; 63 | EMUSCC_API void SCC_close() ; 64 | EMUSCC_API e_int16 SCC_calc(SCC *scc) ; 65 | EMUSCC_API e_int16 SCC_calcHQ(SCC *scc) ; 66 | EMUSCC_API void SCC_write(SCC *scc, e_uint32 adr, e_uint32 val) ; 67 | EMUSCC_API e_uint32 SCC_read(SCC *scc, e_uint32 adr) ; 68 | 69 | #ifdef __cplusplus 70 | } 71 | #endif 72 | 73 | #endif -------------------------------------------------------------------------------- /source/fMSX/msxmusic/emu2413.h: -------------------------------------------------------------------------------- 1 | #ifndef _EMU2413_H_ 2 | #define _EMU2413_H_ 3 | 4 | #include "emutypes.h" 5 | 6 | #ifdef EMU2413_DLL_EXPORTS 7 | #define EMU2413_API __declspec(dllexport) 8 | #elif EMU2413_DLL_IMPORTS 9 | #define EMU2413_API __declspec(dllimport) 10 | #else 11 | #define EMU2413_API 12 | #endif 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #define PI 3.14159265358979 19 | 20 | enum {OPLL_2413_TONE=0, OPLL_VRC7_TONE=1} ; 21 | 22 | /* voice data */ 23 | typedef struct { 24 | e_uint32 TL,FB,EG,ML,AR,DR,SL,RR,KR,KL,AM,PM,WF ; 25 | } OPLL_PATCH ; 26 | 27 | /* slot */ 28 | typedef struct { 29 | 30 | OPLL_PATCH *patch; 31 | 32 | e_int32 type ; /* 0 : modulator 1 : carrier */ 33 | 34 | /* OUTPUT */ 35 | e_int32 feedback ; 36 | e_int32 output[5] ; /* Output value of slot */ 37 | 38 | /* for Phase Generator (PG) */ 39 | e_uint16 *sintbl ; /* Wavetable */ 40 | e_uint32 phase ; /* Phase */ 41 | e_uint32 dphase ; /* Phase increment amount */ 42 | e_uint32 pgout ; /* output */ 43 | 44 | /* for Envelope Generator (EG) */ 45 | e_int32 fnum ; /* F-Number */ 46 | e_int32 block ; /* Block */ 47 | e_int32 volume ; /* Current volume */ 48 | e_int32 sustine ; /* Sustine 1 = ON, 0 = OFF */ 49 | e_uint32 tll ; /* Total Level + Key scale level*/ 50 | e_uint32 rks ; /* Key scale offset (Rks) */ 51 | e_int32 eg_mode ; /* Current state */ 52 | e_uint32 eg_phase ; /* Phase */ 53 | e_uint32 eg_dphase ; /* Phase increment amount */ 54 | e_uint32 egout ; /* output */ 55 | 56 | 57 | /* refer to opll-> */ 58 | e_int32 *plfo_pm ; 59 | e_int32 *plfo_am ; 60 | 61 | 62 | } OPLL_SLOT ; 63 | 64 | /* Channel */ 65 | typedef struct { 66 | 67 | e_int32 patch_number ; 68 | e_int32 key_status ; 69 | OPLL_SLOT *mod, *car ; 70 | 71 | } OPLL_CH ; 72 | 73 | /* Mask */ 74 | #define OPLL_MASK_CH(x) (1<<(x)) 75 | #define OPLL_MASK_HH (1<<(9)) 76 | #define OPLL_MASK_CYM (1<<(10)) 77 | #define OPLL_MASK_TOM (1<<(11)) 78 | #define OPLL_MASK_SD (1<<(12)) 79 | #define OPLL_MASK_BD (1<<(13)) 80 | #define OPLL_MASK_RYTHM ( OPLL_MASK_HH | OPLL_MASK_CYM | OPLL_MASK_TOM | OPLL_MASK_SD | OPLL_MASK_BD ) 81 | 82 | /* opll */ 83 | typedef struct { 84 | 85 | e_uint32 adr ; 86 | 87 | e_int32 output[2] ; 88 | 89 | /* Register */ 90 | e_uint8 reg[0x40] ; 91 | e_int32 slot_on_flag[18] ; 92 | 93 | /* Rythm Mode : 0 = OFF, 1 = ON */ 94 | e_int32 rythm_mode ; 95 | 96 | /* Pitch Modulator */ 97 | e_uint32 pm_phase ; 98 | e_int32 lfo_pm ; 99 | 100 | /* Amp Modulator */ 101 | e_int32 am_phase ; 102 | e_int32 lfo_am ; 103 | 104 | 105 | /* Noise Generator */ 106 | e_uint32 noise_seed ; 107 | e_uint32 whitenoise ; 108 | e_uint32 noiseA ; 109 | e_uint32 noiseB ; 110 | e_uint32 noiseA_phase ; 111 | e_uint32 noiseB_phase ; 112 | e_uint32 noiseA_dphase ; 113 | e_uint32 noiseB_dphase ; 114 | 115 | /* Channel & Slot */ 116 | OPLL_CH *ch[9] ; 117 | OPLL_SLOT *slot[18] ; 118 | 119 | /* Voice Data */ 120 | OPLL_PATCH *patch[19*2] ; 121 | e_int32 patch_update[2] ; /* flag for check patch update */ 122 | 123 | e_uint32 mask ; 124 | 125 | } OPLL ; 126 | 127 | /* Initialize */ 128 | EMU2413_API void OPLL_init(e_uint32 clk, e_uint32 rate) ; 129 | EMU2413_API void OPLL_close(void) ; 130 | 131 | /* Create Object */ 132 | EMU2413_API OPLL *OPLL_new(void) ; 133 | EMU2413_API void OPLL_delete(OPLL *) ; 134 | 135 | /* Setup */ 136 | EMU2413_API void OPLL_reset(OPLL *) ; 137 | EMU2413_API void OPLL_reset_patch(OPLL *, e_int32) ; 138 | EMU2413_API void OPLL_setClock(e_uint32 c, e_uint32 r) ; 139 | 140 | /* Port/Register access */ 141 | EMU2413_API void OPLL_writeIO(OPLL *, e_uint32 reg, e_uint32 val) ; 142 | EMU2413_API void OPLL_writeReg(OPLL *, e_uint32 reg, e_uint32 val) ; 143 | 144 | /* Synthsize */ 145 | EMU2413_API e_int16 OPLL_calc(OPLL *) ; 146 | 147 | /* Misc */ 148 | EMU2413_API void OPLL_setPatch(OPLL *, const e_uint8 *dump) ; 149 | 150 | EMU2413_API void OPLL_copyPatch(OPLL *, e_int32, OPLL_PATCH *) ; 151 | EMU2413_API void OPLL_forceRefresh(OPLL *) ; 152 | 153 | /* Utility */ 154 | EMU2413_API void OPLL_dump2patch(const e_uint8 *dump, OPLL_PATCH *patch) ; 155 | EMU2413_API void OPLL_patch2dump(const OPLL_PATCH *patch, e_uint8 *dump) ; 156 | EMU2413_API void OPLL_getDefaultPatch(e_int32 type, e_int32 num, OPLL_PATCH *) ; 157 | 158 | /* Channel Mask */ 159 | EMU2413_API e_uint32 OPLL_setMask(OPLL *, e_uint32 mask) ; 160 | EMU2413_API e_uint32 OPLL_toggleMask(OPLL *, e_uint32 mask) ; 161 | 162 | #define dump2patch OPLL_dump2patch 163 | 164 | #ifdef __cplusplus 165 | } 166 | #endif 167 | 168 | #endif 169 | -------------------------------------------------------------------------------- /source/fMSX/msxmusic/emutypes.h: -------------------------------------------------------------------------------- 1 | #ifndef _EMUTYPES_H_ 2 | #define _EMUTYPES_H_ 3 | 4 | #if defined(_MSC_VER) 5 | #include 6 | #endif 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | typedef unsigned int e_uint; 12 | typedef signed int e_int; 13 | 14 | typedef unsigned char e_uint8 ; 15 | typedef signed char e_int8 ; 16 | 17 | typedef unsigned short e_uint16 ; 18 | typedef signed short e_int16 ; 19 | 20 | typedef unsigned int e_uint32 ; 21 | typedef signed int e_int32 ; 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | #endif 27 | -------------------------------------------------------------------------------- /source/fMSX/msxmusic/vrc7tone.h: -------------------------------------------------------------------------------- 1 | /* VRC7 VOICE */ 2 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3 | 0x33, 0x01, 0x09, 0x0e, 0x94, 0x90, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 4 | 0x13, 0x41, 0x0f, 0x0d, 0xce, 0xd3, 0x43, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 5 | 0x01, 0x12, 0x1b, 0x06, 0xff, 0xd2, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 6 | 0x61, 0x61, 0x1b, 0x07, 0xaf, 0x63, 0x20, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 7 | 0x22, 0x21, 0x1e, 0x06, 0xf0, 0x76, 0x08, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 8 | 0x66, 0x21, 0x15, 0x00, 0x93, 0x94, 0x20, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 9 | 0x21, 0x61, 0x1c, 0x07, 0x82, 0x81, 0x10, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 10 | 0x23, 0x21, 0x20, 0x1f, 0xc0, 0x71, 0x07, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 11 | 0x25, 0x31, 0x26, 0x05, 0x64, 0x41, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 12 | 0x17, 0x21, 0x28, 0x07, 0xff, 0x83, 0x02, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 13 | 0x97, 0x81, 0x25, 0x07, 0xcf, 0xc8, 0x02, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 14 | 0x21, 0x21, 0x54, 0x0f, 0x80, 0x7f, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 15 | 0x01, 0x01, 0x56, 0x03, 0xd3, 0xb2, 0x43, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 16 | 0x31, 0x21, 0x0c, 0x03, 0x82, 0xc0, 0x40, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 17 | 0x21, 0x01, 0x0c, 0x03, 0xd4, 0xd3, 0x40, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 18 | 0x04, 0x21, 0x28, 0x00, 0xdf, 0xf8, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 19 | 0x23, 0x22, 0x00, 0x00, 0xa8, 0xf8, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 20 | 0x25, 0x18, 0x00, 0x00, 0xf8, 0xa9, 0xf8, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 21 | -------------------------------------------------------------------------------- /source/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * fMSX orbis launcher for PlayStation 4 3 | * Copyright (C) 2015,2016,2017 Antonio Jose Ramos Marquez (aka bigboss) @psxdev on twitter 4 | * Repository https://github.com/psxdev/fmsx 5 | */ 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include "menu.h" 20 | #include "browser.h" 21 | 22 | typedef struct OrbisGlobalConf 23 | { 24 | Orbis2dConfig *conf; 25 | OrbisPadConfig *confPad; 26 | OrbisAudioConfig *confAudio; 27 | OrbisKeyboardConfig *confKeyboard; 28 | ps4LinkConfiguration *confLink; 29 | int orbisLinkFlag; 30 | }OrbisGlobalConf; 31 | 32 | OrbisGlobalConf *myConf; 33 | 34 | 35 | int x=1280/2; 36 | int y=720/2; 37 | int w=1280/64; 38 | int h=1280/64; 39 | int step=10; 40 | 41 | 42 | int64_t flipArg=0; 43 | int R,G,B; 44 | uint32_t color=0x80ff0000; 45 | int flag=0; 46 | //int closeMenu=0; 47 | Orbis2dConfig *conf; 48 | OrbisPadConfig *confPad; 49 | 50 | //extern char browserBackground[]; 51 | //extern char settingsBackground[]; 52 | //extern char creditsBackground[]; 53 | //extern char folder_icon[]; 54 | //extern char file_icon[]; 55 | Orbis2dTexture *browserTexture=NULL; 56 | Orbis2dTexture *folderTexture=NULL; 57 | Orbis2dTexture *fileTexture=NULL; 58 | 59 | Orbis2dTexture *settingsTexture=NULL; 60 | Orbis2dTexture *creditsTexture=NULL; 61 | 62 | int col=0; 63 | void finishApp() 64 | { 65 | orbis2dFinish(); 66 | orbisAudioFinish(); 67 | orbisKeyboardFinish(); 68 | orbisPadFinish(); 69 | ps4LinkFinish(); 70 | 71 | } 72 | void initTextures() 73 | { 74 | browserTexture=orbis2dLoadPngFromHost_v2(BROWSERBACKGROUND_FILE_PATH); 75 | //creditsTexture=orbis2dLoadPngFromHost_v2(CREDITS_FILE_PATH); 76 | settingsTexture=orbis2dLoadPngFromHost_v2(SETTINGS_FILE_PATH); 77 | folderTexture=orbis2dLoadPngFromHost_v2(FOLDER_ICON_PATH); 78 | fileTexture=orbis2dLoadPngFromHost_v2(FILE_ICON_PATH); 79 | creditsTexture=orbis2dLoadPngFromHost_v2(CREDITS_FILE_PATH); 80 | if(!creditsTexture) 81 | { 82 | debugNetPrintf(DEBUG,"credit chungo\n"); 83 | 84 | } 85 | else 86 | { 87 | debugNetPrintf(DEBUG,"credit bien\n"); 88 | 89 | } 90 | } 91 | 92 | 93 | 94 | void initApp() 95 | { 96 | int ret; 97 | 98 | debugNetPrintf(DEBUG,"[PS4LINK] Initialized and connected from pc/mac ready to receive commands\n"); 99 | 100 | orbisFileBrowserInit("host0:GAMES"); 101 | 102 | //hide playroom splash 103 | 104 | sceSystemServiceHideSplashScreen(); 105 | 106 | 107 | ret=orbisPadInitWithConf(myConf->confPad); 108 | 109 | if(ret==1) 110 | { 111 | 112 | 113 | confPad=orbisPadGetConf(); 114 | ret=orbis2dInitWithConf(myConf->conf); 115 | if(ret==1) 116 | { 117 | conf=orbis2dGetConf(); 118 | flag=1; 119 | ret=orbisAudioInitWithConf(myConf->confAudio); 120 | if(ret==1) 121 | { 122 | //orbisKeyboardInitWithConf(myConf->confKeyboard); 123 | ret=orbisKeyboardInit(); 124 | debugNetPrintf(DEBUG,"orbisKeyboardInit %d\n",ret); 125 | if(ret==1) 126 | { 127 | myConf->confKeyboard=OrbisKeyboardGetConf(); 128 | ret=orbisKeyboardOpen(); 129 | debugNetPrintf(DEBUG,"orbisKeyboardOpen %d\n",ret); 130 | } 131 | //ret=orbisAudioInitChannel(ORBISAUDIO_CHANNEL_MAIN,512,48000,ORBISAUDIO_FORMAT_S16_MONO); 132 | //ret=orbisAudioInitChannel(ORBISAUDIO_CHANNEL_MAIN,1024,48000,ORBISAUDIO_FORMAT_S16_STEREO); 133 | //debugNetPrintf(DEBUG,"orbisKeyboardInit %d\n",orbisKeyboardInit()); 134 | //sleep(1); 135 | //debugNetPrintf(DEBUG,"orbisKeyboardInit %d\n",orbisKeyboardOpen()); 136 | 137 | } 138 | } 139 | } 140 | 141 | } 142 | int main(int argc, char *argv[]) 143 | { 144 | int ret; 145 | 146 | uintptr_t intptr=0; 147 | sscanf(argv[1],"%p",&intptr); 148 | myConf=(OrbisGlobalConf *)intptr; 149 | ret=ps4LinkInitWithConf(myConf->confLink); 150 | if(!ret) 151 | { 152 | ps4LinkFinish(); 153 | return 0; 154 | } 155 | initApp(); 156 | 157 | 158 | /*Mod_Init(0); 159 | Mod_Load("host0:zweifeld.mod"); 160 | Mod_Play();*/ 161 | // orbisAudioResume(0); 162 | orbisAudioPause(0); 163 | 164 | initTextures(); 165 | debugNetPrintf(DEBUG,"after initTextures...\n"); 166 | 167 | 168 | while(flag) 169 | { 170 | fmsxInit(); 171 | } 172 | 173 | orbisAudioResume(0); 174 | //Mod_End(); 175 | //wait for current display buffer 176 | orbis2dStartDrawing(); 177 | 178 | // clear with background (default white) to the current display buffer 179 | orbis2dClearBuffer(0); 180 | 181 | //flush and flip 182 | orbis2dFinishDrawing(flipArg); 183 | 184 | //swap buffers 185 | orbis2dSwapBuffers(); 186 | 187 | finishApp(); 188 | 189 | exit(0); 190 | 191 | return 0; 192 | } 193 | -------------------------------------------------------------------------------- /system/browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psxdev/fmsx/60c32c0a29a6aa63066afe88a59e8d719d286b2a/system/browser.png -------------------------------------------------------------------------------- /system/credits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psxdev/fmsx/60c32c0a29a6aa63066afe88a59e8d719d286b2a/system/credits.png -------------------------------------------------------------------------------- /system/file_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psxdev/fmsx/60c32c0a29a6aa63066afe88a59e8d719d286b2a/system/file_icon.png -------------------------------------------------------------------------------- /system/folder_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psxdev/fmsx/60c32c0a29a6aa63066afe88a59e8d719d286b2a/system/folder_icon.png -------------------------------------------------------------------------------- /system/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/psxdev/fmsx/60c32c0a29a6aa63066afe88a59e8d719d286b2a/system/settings.png --------------------------------------------------------------------------------