Commit 0bae7b1b authored by Cayce's avatar Cayce
Browse files

migrate 4.9 to 5.1. Changelog from fMSX site, filtering non-ported changes:

New in fMSX 5.1
    -

New in fMSX 5.0
    Switched to microseconds in the AY8910 PSG emulation.
    Now updating, rendering, and playing sound every 8 scanlines.

Does not build yet due to MCF (MSX Cheat File) addition; next commit will fix that.
parent 50e0d7f8
......@@ -202,7 +202,7 @@ void Write8910(AY8910 *D,byte R,byte V)
D->R[R]=V;
/* Compute envelope period (why not <<4?) */
J=((int)D->R[12]<<8)+D->R[11];
D->EPeriod=1000*(J? J:0x10000)/D->Clock;
D->EPeriod=(int)(1000000L*(J? J:0x10000)/D->Clock);
/* No channels changed */
return;
......@@ -240,18 +240,18 @@ void Write8910(AY8910 *D,byte R,byte V)
/** Loop8910() ***********************************************/
/** Call this function periodically to update volume **/
/** envelopes. Use mS to pass the time since the last call **/
/** of Loop8910() in milliseconds. **/
/** envelopes. Use uSec to pass the time since the last **/
/** call of Loop8910() in microseconds. **/
/*************************************************************/
void Loop8910(AY8910 *D,int mS)
void Loop8910(AY8910 *D,int uSec)
{
int J,I;
/* Exit if no envelope running */
if(!D->EPeriod) return;
/* Count milliseconds */
D->ECount += mS;
/* Count microseconds */
D->ECount += uSec;
if(D->ECount<D->EPeriod) return;
/* Count steps */
......
......@@ -42,7 +42,7 @@ typedef struct
byte Changed; /* Bitmap of changed channels */
byte Sync; /* AY8910_SYNC/AY8910_ASYNC */
byte Latch; /* Latch for the register num */
int EPeriod; /* Envelope step in msecs */
int EPeriod; /* Envelope step in microsecs */
int ECount; /* Envelope step counter */
int EPhase; /* Envelope phase */
} AY8910;
......@@ -86,10 +86,10 @@ void Sync8910(AY8910 *D,byte Sync);
/** Loop8910() ***********************************************/
/** Call this function periodically to update volume **/
/** envelopes. Use mS to pass the time since the last call **/
/** of Loop8910() in milliseconds. **/
/** envelopes. Use uSec to pass the time since the last **/
/** call of Loop8910() in microseconds. **/
/*************************************************************/
void Loop8910(AY8910 *D,int mS);
void Loop8910(AY8910 *D,int uSec);
#ifdef __cplusplus
}
......
......@@ -72,7 +72,7 @@
#define EFF_EAGLE (EFF_SOFTEN|EFF_SOFTEN2)
#define EFF_SCALE2X (EFF_SOFTEN3)
#define EFF_HQ4X (EFF_SOFTEN|EFF_SOFTEN3)
#define EFF_NEAREST (EFF_SOFTEN2|EFF_SOFTEN3)
#define EFF_NEAREST (EFF_SOFTEN2|EFF_SOFTEN3) /* Disable hw interpolation */
#define EFF_RASTER_ALL (EFF_TVLINES|EFF_LCDLINES)
#define EFF_RASTER (EFF_TVLINES|EFF_LCDLINES)
......
/** EMULib Emulation Library *********************************/
/** **/
/** MCF.c **/
/** **/
/** This file contains support for the .MCF cheat file **/
/** format. See MCF.h for declarations. **/
/** **/
/** Copyright (C) Marat Fayzullin 2017 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#include "MCF.h"
#include <stdio.h>
#include <string.h>
/** LoadFileMCF() ********************************************/
/** Load cheats from .MCF file. Returns number of loaded **/
/** cheat entries or 0 on failure. **/
/*************************************************************/
int LoadFileMCF(const char *Name,MCFEntry *Cheats,int MaxCheats)
{
char Buf[256],Note[256];
unsigned int Arg0,Addr,Data,Arg3;
int J;
RFILE *F;
/* Open .MCF text file with cheats */
F = rfopen(Name,"rb");
if(!F) return(0);
/* Load cheats from file */
for(J=0;!rfeof(F)&&(J<MaxCheats);)
if(rfgets(Buf,sizeof(Buf),F) && (sscanf(Buf,"%u,%u,%u,%u,%255s",&Arg0,&Addr,&Data,&Arg3,Note)==5))
{
Cheats[J].Addr = Addr;
Cheats[J].Data = Data;
Cheats[J].Size = Data>0xFFFF? 4:Data>0xFF? 2:1;
strncpy(Cheats[J].Note,Note,sizeof(Cheats[J].Note));
Cheats[J].Note[sizeof(Cheats[J].Note)-1] = '\0';
++J;
}
/* Done with the file */
rfclose(F);
/* Done */
return(J);
}
/** EMULib Emulation Library *********************************/
/** **/
/** MCF.h **/
/** **/
/** This file contains declarations for the .MCF cheat file **/
/** support. See MCF.c for implementation. **/
/** **/
/** Copyright (C) Marat Fayzullin 2017 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#ifndef MCF_H
#define MCF_H
/** MCFEntry *************************************************/
/** Definition of a single MCF entry representing a cheat. **/
/*************************************************************/
typedef struct
{
unsigned int Addr; // Address to apply cheat to
unsigned int Data; // Data to write to Addr
unsigned char Size; // Size of Data in bytes (1/2/4)
char Note[116]; // Description of the cheat
} MCFEntry;
/** LoadFileMCF() ********************************************/
/** Load cheats from .MCF file. Returns number of loaded **/
/** cheat entries or 0 on failure. **/
/*************************************************************/
int LoadFileMCF(const char *Name,MCFEntry *Cheats,int MaxCheats);
#endif /* MCF_H */
......@@ -122,7 +122,7 @@ void Reset2413(YM2413 *D,int First)
D->Sync = YM2413_ASYNC;
D->Changed = (1<<YM2413_CHANNELS)-1;
D->PChanged = (1<<YM2413_CHANNELS)-1;
D->DChanged = (1<<YM2413_CHANNELS)-1;
D->DChanged = 0x1F;
D->Latch = 0;
}
......
......@@ -21,6 +21,7 @@ Specify these in your RetroArch core options:
fmsx_mapper_type_mode=Guess Mapper Type A*|Guess Mapper Type B|Generic 8kB|Generic 16kB|Konami5 8kB|Konami4 8kB|ASCII 8kB|ASCII 16kB|GameMaster2|FMPAC
fmsx_ram_pages=Auto*|64KB|128KB|256KB|512KB
fmsx_vram_pages=Auto*|32KB|64KB|128KB|192KB
fmsx_simbdos=No*|Yes
A star (*) indicates this is the default setting.
......@@ -44,6 +45,10 @@ Optional; loaded when found:
## Technical details
Video: 16bpp RGB565 272x228 (544x228 in 512px MSX2 screen modes).
Video: 16bpp RGB565 272x228 (544x228 in 512px MSX2 screen modes). This includes an 8px (16px) border; MSX native screen resolutions are:
- horizontal: 256 or 512 (textmode: 40 or 80 columns)
- vertical: 192 or 212
Audio: rendered in 48kHz 16b mono.
Framerate: NTSC (US/JP) implies 60Hz - thus 60FPS, PAL (EU) implies 50Hz (=50FPS). Gameplay and audio actually becomes 17% slower when switching from NTSC to PAL - just like on a real MSX.
......@@ -17,6 +17,7 @@
#include "Sound.h"
#include "Floppy.h"
#include "SHA1.h"
#include "MCF.h"
#include <string.h>
#include <stdlib.h>
......@@ -176,9 +177,14 @@ byte PLatch; /* Palette buffer */
byte ALatch; /* Address buffer */
int Palette[16]; /* Current palette */
/** Cheat entries ********************************************/
int MCFCount = 0; /* Size of MCFEntries[] */
MCFEntry MCFEntries[MAXCHEATS]; /* Entries from .MCF file */
/** Places in DiskROM to be patched with ED FE C9 ************/
static const word DiskPatches[] =
{ 0x4010,0x4013,0x4016,0x401C,0x401F,0 };
CheatCode CheatCodes[MAXCHEATS];
/** Places in BIOS to be patched with ED FE C9 ***************/
static const word BIOSPatches[] =
......@@ -432,6 +438,7 @@ int StartMSX(int NewMode,int NewRAMPages,int NewVRAMPages)
FMPACKey = 0x0000;
ExitNow = 0;
NChunks = 0;
MCFCount = 0;
/* Zero cartridge related data */
for(J=0;J<MAXSLOTS;++J)
......@@ -2034,6 +2041,24 @@ word LoopZ80(Z80 *R)
else RefreshLine12(ScanLine);
}
/* Every few scanlines, update sound */
if(!(ScanLine&0x07))
{
/* Compute number of microseconds */
J = (int)(1000000L*(CPU_HPERIOD<<3)/CPU_CLOCK);
/* Update AY8910 state */
Loop8910(&PSG,J);
/* Flush changes to the sound channels */
Sync8910(&PSG,AY8910_FLUSH|(OPTION(MSX_DRUMS)? AY8910_DRUMS:0));
SyncSCC(&SCChip,SCC_FLUSH);
Sync2413(&OPLL,YM2413_FLUSH);
/* Render and play all sound now */
PlayAllSound(J);
}
/* Keyboard, sound, and other stuff always runs at line 192 */
/* This way, it can't be shut off by overscan tricks (Maarten) */
if(ScanLine==192)
......@@ -2044,14 +2069,6 @@ word LoopZ80(Z80 *R)
/* Check sprites and set Collision bit */
if(!(VDPStatus[0]&0x20)&&CheckSprites()) VDPStatus[0]|=0x20;
/* Update AY8910 state */
J=1000*VPeriod/CPU_CLOCK;
Loop8910(&PSG,J);
/* Flush changes to the sound channels */
Sync8910(&PSG,AY8910_FLUSH|(OPTION(MSX_DRUMS)? AY8910_DRUMS:0));
SyncSCC(&SCChip,SCC_FLUSH);
Sync2413(&OPLL,YM2413_FLUSH);
/* Check joystick */
JoyState=Joystick();
......@@ -2337,11 +2354,50 @@ int LoadFile(const char *FileName)
if(hasext(FileName,".FNT")) return(!!LoadFNT(FileName));
/* Try loading as palette */
if(hasext(FileName,".PAL")) return(!!LoadPAL(FileName));
if(hasext(FileName,".MCF")) return(!!LoadMCF(FileName));
/* Unknown file type */
return(0);
}
/** ApplyMCFCheat() ******************************************/
/** Apply given MCF cheat entry. Returns 0 on failure or 1 **/
/** on success. **/
/*************************************************************/
int ApplyMCFCheat(int N)
{
int Status;
/* Must be a valid MSX-specific entry */
if((N<0)||(N>=MCFCount)||(MCFEntries[N].Addr>0xFFFF)||(MCFEntries[N].Size>2))
return(0);
/* Switch cheats off for now and remove all present cheats */
Status = Cheats(CHTS_QUERY);
Cheats(CHTS_OFF);
ResetCheats();
/* Insert cheat codes from the MCF entry */
CheatCodes[0].Addr = MCFEntries[N].Addr;
CheatCodes[0].Data = MCFEntries[N].Data;
CheatCodes[0].Size = MCFEntries[N].Size;
sprintf(
(char *)CheatCodes[0].Text,
CheatCodes[0].Size>1? "%04X-%04X":"%04X-%02X",
CheatCodes[0].Addr,
CheatCodes[0].Data
);
/* Have one cheat code now */
CheatCount = 1;
/* Turn cheats back on, if they were on */
Cheats(Status);
/* Done */
return(CheatCount);
}
/** GuessROM() ***********************************************/
/** Guess MegaROM mapper of a ROM. **/
/*************************************************************/
......@@ -2854,6 +2910,16 @@ int LoadPAL(const char *Name)
return(J);
}
/** LoadMCF() ************************************************/
/** Load cheats from .MCF file. Returns number of loaded **/
/** cheat entries or 0 on failure. **/
/*************************************************************/
int LoadMCF(const char *Name)
{
MCFCount = LoadFileMCF(Name,MCFEntries,sizeof(MCFEntries)/sizeof(MCFEntries[0]));
return(MCFCount);
}
#define SaveSTRUCT(Name) \
if(Size+sizeof(Name)>MaxSize) return(0); \
else { memcpy(Buf+Size,&(Name),sizeof(Name));Size+=sizeof(Name); }
......
......@@ -263,6 +263,14 @@ extern const char *FNTName; /* Font file for text */
extern FDIDisk FDD[4]; /* Floppy disk images */
extern FILE *CasStream; /* Cassette I/O stream */
typedef struct
{
unsigned int Addr;
word Data,Orig;
byte Size;
byte Text[14];
} CheatCode;
/** StartMSX() ***********************************************/
/** Allocate memory, load ROM image, initialize hardware, **/
/** CPU and start the emulation. This function returns 0 in **/
......@@ -343,6 +351,12 @@ byte LoadFNT(const char *FileName);
/*************************************************************/
int SetScreenDepth(int Depth);
/** ApplyMCFCheat() ******************************************/
/** Apply given MCF cheat entry. Returns 0 on failure or 1 **/
/** on success. **/
/*************************************************************/
int ApplyMCFCheat(int N);
/** SaveState() **********************************************/
/** Save emulation state to a memory buffer. Returns size **/
/** on success, 0 on failure. **/
......@@ -355,6 +369,12 @@ unsigned int SaveState(unsigned char *Buf,unsigned int MaxSize);
/*************************************************************/
unsigned int LoadState(unsigned char *Buf,unsigned int MaxSize);
/** LoadMCF() ************************************************/
/** Load cheats from .MCF file. Returns number of loaded **/
/** cheat entries or 0 on failure. **/
/*************************************************************/
int LoadMCF(const char *Name);
/** InitMachine() ********************************************/
/** Allocate resources needed by the machine-dependent code.**/
/************************************ TO BE WRITTEN BY USER **/
......@@ -391,6 +411,11 @@ byte DiskPresent(byte ID);
byte DiskRead(byte ID,byte *Buf,int N);
byte DiskWrite(byte ID,const byte *Buf,int N);
/** PlayAllSound() *******************************************/
/** Render and play given number of microseconds of sound. **/
/************************************ TO BE WRITTEN BY USER **/
void PlayAllSound(int uSec);
/** SetColor() ***********************************************/
/** Set color N (0..15) to (R,G,B). **/
/************************************ TO BE WRITTEN BY USER **/
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment