This commit is contained in:
Rachael Alexanderson 2017-02-07 02:23:48 -05:00
commit d760b5070a
18 changed files with 595 additions and 530 deletions

View file

@ -2012,8 +2012,8 @@ PDynArray::PDynArray()
//
//==========================================================================
PDynArray::PDynArray(PType *etype)
: ElementType(etype)
PDynArray::PDynArray(PType *etype,PStruct *backing)
: ElementType(etype), BackingType(backing)
{
mDescriptiveName.Format("DynArray<%s>", etype->DescriptiveName());
Size = sizeof(FArray);
@ -2061,7 +2061,33 @@ PDynArray *NewDynArray(PType *type)
PType *atype = TypeTable.FindType(RUNTIME_CLASS(PDynArray), (intptr_t)type, 0, &bucket);
if (atype == NULL)
{
atype = new PDynArray(type);
FString backingname;
switch (type->GetRegType())
{
case REGT_INT:
backingname.Format("DynArray_I%d", type->Size * 8);
break;
case REGT_FLOAT:
backingname.Format("DynArray_F%d", type->Size * 8);
break;
case REGT_STRING:
backingname = "DynArray_String";
break;
case REGT_POINTER:
backingname = "DynArray_Ptr";
break;
default:
I_Error("Unsupported dynamic array requested");
break;
}
auto backing = NewNativeStruct(backingname, nullptr);
atype = new PDynArray(type, backing);
TypeTable.AddType(atype, RUNTIME_CLASS(PDynArray), (intptr_t)type, 0, bucket);
}
return (PDynArray *)atype;

View file

@ -6,6 +6,7 @@
#endif
typedef std::pair<const class PType *, unsigned> FTypeAndOffset;
class PStruct;
#include "vm.h"
@ -649,9 +650,10 @@ class PDynArray : public PCompoundType
DECLARE_CLASS(PDynArray, PCompoundType);
HAS_OBJECT_POINTERS;
public:
PDynArray(PType *etype);
PDynArray(PType *etype, PStruct *backing);
PType *ElementType;
PStruct *BackingType;
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;

View file

@ -821,6 +821,8 @@ xx(DamageFunction)
xx(Length)
xx(Unit)
xx(Size)
xx(Copy)
xx(Move)
xx(Voidptr)
xx(StateLabel)
xx(SpriteID)

View file

@ -1,28 +0,0 @@
/*
* Name: General Use Types Definitions -- Header Include file
* Version: 1.24
* Author: Vladimir Arnost (QA-Software)
* Last revision: Sep-4-1995
* Compiler: Borland C++ 3.1, Watcom C/C++ 10.0
*
*/
#ifndef __DEFTYPES_H_
#define __DEFTYPES_H_
/* Global type declarations */
#include "doomtype.h"
/* machine dependent types */
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef signed char schar;
typedef signed short sshort;
typedef signed int sint;
typedef signed long slong;
#endif // __DEFTYPES_H_

View file

@ -105,12 +105,6 @@ Revision History:
/* compiler dependence */
#ifndef OSD_CPU_H
#define OSD_CPU_H
typedef unsigned char UINT8; /* unsigned 8bit */
typedef unsigned short UINT16; /* unsigned 16bit */
typedef unsigned int UINT32; /* unsigned 32bit */
typedef signed char INT8; /* signed 8bit */
typedef signed short INT16; /* signed 16bit */
typedef signed int INT32; /* signed 32bit */
#endif
#ifndef PI
@ -119,12 +113,8 @@ typedef signed int INT32; /* signed 32bit */
#ifdef _MSC_VER
#pragma warning (disable: 4244)
#define INLINE __forceinline
#endif
#ifdef __GNUC__
#define INLINE __inline
#endif
#define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */
#define EG_SH 16 /* 16.16 fixed point (EG timing) */
@ -171,97 +161,100 @@ typedef signed int INT32; /* signed 32bit */
/* Saving is necessary for member of the 'R' mark for suspend/resume */
typedef struct{
UINT32 ar; /* attack rate: AR<<2 */
UINT32 dr; /* decay rate: DR<<2 */
UINT32 rr; /* release rate:RR<<2 */
UINT8 KSR; /* key scale rate */
UINT8 ksl; /* keyscale level */
UINT8 ksr; /* key scale rate: kcode>>KSR */
UINT8 mul; /* multiple: mul_tab[ML] */
struct OPL_SLOT
{
uint32_t ar; /* attack rate: AR<<2 */
uint32_t dr; /* decay rate: DR<<2 */
uint32_t rr; /* release rate:RR<<2 */
uint8_t KSR; /* key scale rate */
uint8_t ksl; /* keyscale level */
uint8_t ksr; /* key scale rate: kcode>>KSR */
uint8_t mul; /* multiple: mul_tab[ML] */
/* Phase Generator */
UINT32 Cnt; /* frequency counter */
UINT32 Incr; /* frequency counter step */
UINT8 FB; /* feedback shift value */
INT32 *connect1; /* slot1 output pointer */
INT32 op1_out[2]; /* slot1 output for feedback */
UINT8 CON; /* connection (algorithm) type */
uint32_t Cnt; /* frequency counter */
uint32_t Incr; /* frequency counter step */
uint8_t FB; /* feedback shift value */
int32_t *connect1; /* slot1 output pointer */
int32_t op1_out[2]; /* slot1 output for feedback */
uint8_t CON; /* connection (algorithm) type */
/* Envelope Generator */
UINT8 eg_type; /* percussive/non-percussive mode */
UINT8 state; /* phase type */
UINT32 TL; /* total level: TL << 2 */
INT32 TLL; /* adjusted now TL */
INT32 volume; /* envelope counter */
UINT32 sl; /* sustain level: sl_tab[SL] */
UINT8 eg_sh_ar; /* (attack state) */
UINT8 eg_sel_ar; /* (attack state) */
UINT8 eg_sh_dr; /* (decay state) */
UINT8 eg_sel_dr; /* (decay state) */
UINT8 eg_sh_rr; /* (release state) */
UINT8 eg_sel_rr; /* (release state) */
UINT32 key; /* 0 = KEY OFF, >0 = KEY ON */
uint8_t eg_type; /* percussive/non-percussive mode */
uint8_t state; /* phase type */
uint32_t TL; /* total level: TL << 2 */
int32_t TLL; /* adjusted now TL */
int32_t volume; /* envelope counter */
uint32_t sl; /* sustain level: sl_tab[SL] */
uint8_t eg_sh_ar; /* (attack state) */
uint8_t eg_sel_ar; /* (attack state) */
uint8_t eg_sh_dr; /* (decay state) */
uint8_t eg_sel_dr; /* (decay state) */
uint8_t eg_sh_rr; /* (release state) */
uint8_t eg_sel_rr; /* (release state) */
uint32_t key; /* 0 = KEY OFF, >0 = KEY ON */
/* LFO */
UINT32 AMmask; /* LFO Amplitude Modulation enable mask */
UINT8 vib; /* LFO Phase Modulation enable flag (active high)*/
uint32_t AMmask; /* LFO Amplitude Modulation enable mask */
uint8_t vib; /* LFO Phase Modulation enable flag (active high)*/
/* waveform select */
unsigned int wavetable;
} OPL_SLOT;
};
typedef struct{
struct OPL_CH
{
OPL_SLOT SLOT[2];
/* phase generator state */
UINT32 block_fnum; /* block+fnum */
UINT32 fc; /* Freq. Increment base */
UINT32 ksl_base; /* KeyScaleLevel Base step */
UINT8 kcode; /* key code (for key scaling) */
uint32_t block_fnum; /* block+fnum */
uint32_t fc; /* Freq. Increment base */
uint32_t ksl_base; /* KeyScaleLevel Base step */
uint8_t kcode; /* key code (for key scaling) */
float LeftVol; /* volumes for stereo panning */
float RightVol;
} OPL_CH;
};
/* OPL state */
typedef struct fm_opl_f {
struct FM_OPL
{
/* FM channel slots */
OPL_CH P_CH[9]; /* OPL/OPL2 chips have 9 channels*/
UINT32 eg_cnt; /* global envelope generator counter */
UINT32 eg_timer; /* global envelope generator counter works at frequency = chipclock/72 */
UINT32 eg_timer_add; /* step of eg_timer */
UINT32 eg_timer_overflow; /* envelope generator timer overflows every 1 sample (on real chip) */
uint32_t eg_cnt; /* global envelope generator counter */
uint32_t eg_timer; /* global envelope generator counter works at frequency = chipclock/72 */
uint32_t eg_timer_add; /* step of eg_timer */
uint32_t eg_timer_overflow; /* envelope generator timer overflows every 1 sample (on real chip) */
UINT8 rhythm; /* Rhythm mode */
uint8_t rhythm; /* Rhythm mode */
UINT32 fn_tab[1024]; /* fnumber->increment counter */
uint32_t fn_tab[1024]; /* fnumber->increment counter */
/* LFO */
UINT8 lfo_am_depth;
UINT8 lfo_pm_depth_range;
UINT32 lfo_am_cnt;
UINT32 lfo_am_inc;
UINT32 lfo_pm_cnt;
UINT32 lfo_pm_inc;
UINT32 noise_rng; /* 23 bit noise shift register */
UINT32 noise_p; /* current noise 'phase' */
UINT32 noise_f; /* current noise peroid */
uint8_t lfo_am_depth;
uint8_t lfo_pm_depth_range;
uint32_t lfo_am_cnt;
uint32_t lfo_am_inc;
uint32_t lfo_pm_cnt;
uint32_t lfo_pm_inc;
UINT8 wavesel; /* waveform select enable flag */
uint32_t noise_rng; /* 23 bit noise shift register */
uint32_t noise_p; /* current noise 'phase' */
uint32_t noise_f; /* current noise period */
uint8_t wavesel; /* waveform select enable flag */
int T[2]; /* timer counters */
UINT8 st[2]; /* timer enable */
uint8_t st[2]; /* timer enable */
UINT8 address; /* address register */
UINT8 status; /* status flag */
UINT8 statusmask; /* status mask */
UINT8 mode; /* Reg.08 : CSM,notesel,etc. */
uint8_t address; /* address register */
uint8_t status; /* status flag */
uint8_t statusmask; /* status mask */
uint8_t mode; /* Reg.08 : CSM,notesel,etc. */
bool IsStereo; /* Write stereo output */
} FM_OPL;
};
@ -278,59 +271,59 @@ static const int slot_array[32]=
/* table is 3dB/octave , DV converts this into 6dB/octave */
/* 0.1875 is bit 0 weight of the envelope counter (volume) expressed in the 'decibel' scale */
#define DV (0.1875/2.0)
static const UINT32 ksl_tab[8*16]=
static const uint32_t ksl_tab[8*16]=
{
/* OCT 0 */
UINT32(0.000/DV), UINT32(0.000/DV), UINT32(0.000/DV), UINT32(0.000/DV),
UINT32(0.000/DV), UINT32(0.000/DV), UINT32(0.000/DV), UINT32(0.000/DV),
UINT32(0.000/DV), UINT32(0.000/DV), UINT32(0.000/DV), UINT32(0.000/DV),
UINT32(0.000/DV), UINT32(0.000/DV), UINT32(0.000/DV), UINT32(0.000/DV),
uint32_t(0.000/DV), uint32_t(0.000/DV), uint32_t(0.000/DV), uint32_t(0.000/DV),
uint32_t(0.000/DV), uint32_t(0.000/DV), uint32_t(0.000/DV), uint32_t(0.000/DV),
uint32_t(0.000/DV), uint32_t(0.000/DV), uint32_t(0.000/DV), uint32_t(0.000/DV),
uint32_t(0.000/DV), uint32_t(0.000/DV), uint32_t(0.000/DV), uint32_t(0.000/DV),
/* OCT 1 */
UINT32(0.000/DV), UINT32(0.000/DV), UINT32(0.000/DV), UINT32(0.000/DV),
UINT32(0.000/DV), UINT32(0.000/DV), UINT32(0.000/DV), UINT32(0.000/DV),
UINT32(0.000/DV), UINT32(0.750/DV), UINT32(1.125/DV), UINT32(1.500/DV),
UINT32(1.875/DV), UINT32(2.250/DV), UINT32(2.625/DV), UINT32(3.000/DV),
uint32_t(0.000/DV), uint32_t(0.000/DV), uint32_t(0.000/DV), uint32_t(0.000/DV),
uint32_t(0.000/DV), uint32_t(0.000/DV), uint32_t(0.000/DV), uint32_t(0.000/DV),
uint32_t(0.000/DV), uint32_t(0.750/DV), uint32_t(1.125/DV), uint32_t(1.500/DV),
uint32_t(1.875/DV), uint32_t(2.250/DV), uint32_t(2.625/DV), uint32_t(3.000/DV),
/* OCT 2 */
UINT32(0.000/DV), UINT32(0.000/DV), UINT32(0.000/DV), UINT32(0.000/DV),
UINT32(0.000/DV), UINT32(1.125/DV), UINT32(1.875/DV), UINT32(2.625/DV),
UINT32(3.000/DV), UINT32(3.750/DV), UINT32(4.125/DV), UINT32(4.500/DV),
UINT32(4.875/DV), UINT32(5.250/DV), UINT32(5.625/DV), UINT32(6.000/DV),
uint32_t(0.000/DV), uint32_t(0.000/DV), uint32_t(0.000/DV), uint32_t(0.000/DV),
uint32_t(0.000/DV), uint32_t(1.125/DV), uint32_t(1.875/DV), uint32_t(2.625/DV),
uint32_t(3.000/DV), uint32_t(3.750/DV), uint32_t(4.125/DV), uint32_t(4.500/DV),
uint32_t(4.875/DV), uint32_t(5.250/DV), uint32_t(5.625/DV), uint32_t(6.000/DV),
/* OCT 3 */
UINT32(0.000/DV), UINT32(0.000/DV), UINT32(0.000/DV), UINT32(1.875/DV),
UINT32(3.000/DV), UINT32(4.125/DV), UINT32(4.875/DV), UINT32(5.625/DV),
UINT32(6.000/DV), UINT32(6.750/DV), UINT32(7.125/DV), UINT32(7.500/DV),
UINT32(7.875/DV), UINT32(8.250/DV), UINT32(8.625/DV), UINT32(9.000/DV),
uint32_t(0.000/DV), uint32_t(0.000/DV), uint32_t(0.000/DV), uint32_t(1.875/DV),
uint32_t(3.000/DV), uint32_t(4.125/DV), uint32_t(4.875/DV), uint32_t(5.625/DV),
uint32_t(6.000/DV), uint32_t(6.750/DV), uint32_t(7.125/DV), uint32_t(7.500/DV),
uint32_t(7.875/DV), uint32_t(8.250/DV), uint32_t(8.625/DV), uint32_t(9.000/DV),
/* OCT 4 */
UINT32(0.000/DV), UINT32(0.000/DV), UINT32(3.000/DV), UINT32(4.875/DV),
UINT32(6.000/DV), UINT32(7.125/DV), UINT32(7.875/DV), UINT32(8.625/DV),
UINT32(9.000/DV), UINT32(9.750/DV),UINT32(10.125/DV),UINT32(10.500/DV),
UINT32(10.875/DV),UINT32(11.250/DV),UINT32(11.625/DV),UINT32(12.000/DV),
uint32_t(0.000/DV), uint32_t(0.000/DV), uint32_t(3.000/DV), uint32_t(4.875/DV),
uint32_t(6.000/DV), uint32_t(7.125/DV), uint32_t(7.875/DV), uint32_t(8.625/DV),
uint32_t(9.000/DV), uint32_t(9.750/DV),uint32_t(10.125/DV),uint32_t(10.500/DV),
uint32_t(10.875/DV),uint32_t(11.250/DV),uint32_t(11.625/DV),uint32_t(12.000/DV),
/* OCT 5 */
UINT32(0.000/DV), UINT32(3.000/DV), UINT32(6.000/DV), UINT32(7.875/DV),
UINT32(9.000/DV),UINT32(10.125/DV),UINT32(10.875/DV),UINT32(11.625/DV),
UINT32(12.000/DV),UINT32(12.750/DV),UINT32(13.125/DV),UINT32(13.500/DV),
UINT32(13.875/DV),UINT32(14.250/DV),UINT32(14.625/DV),UINT32(15.000/DV),
uint32_t(0.000/DV), uint32_t(3.000/DV), uint32_t(6.000/DV), uint32_t(7.875/DV),
uint32_t(9.000/DV),uint32_t(10.125/DV),uint32_t(10.875/DV),uint32_t(11.625/DV),
uint32_t(12.000/DV),uint32_t(12.750/DV),uint32_t(13.125/DV),uint32_t(13.500/DV),
uint32_t(13.875/DV),uint32_t(14.250/DV),uint32_t(14.625/DV),uint32_t(15.000/DV),
/* OCT 6 */
UINT32(0.000/DV), UINT32(6.000/DV), UINT32(9.000/DV),UINT32(10.875/DV),
UINT32(12.000/DV),UINT32(13.125/DV),UINT32(13.875/DV),UINT32(14.625/DV),
UINT32(15.000/DV),UINT32(15.750/DV),UINT32(16.125/DV),UINT32(16.500/DV),
UINT32(16.875/DV),UINT32(17.250/DV),UINT32(17.625/DV),UINT32(18.000/DV),
uint32_t(0.000/DV), uint32_t(6.000/DV), uint32_t(9.000/DV),uint32_t(10.875/DV),
uint32_t(12.000/DV),uint32_t(13.125/DV),uint32_t(13.875/DV),uint32_t(14.625/DV),
uint32_t(15.000/DV),uint32_t(15.750/DV),uint32_t(16.125/DV),uint32_t(16.500/DV),
uint32_t(16.875/DV),uint32_t(17.250/DV),uint32_t(17.625/DV),uint32_t(18.000/DV),
/* OCT 7 */
UINT32(0.000/DV), UINT32(9.000/DV),UINT32(12.000/DV),UINT32(13.875/DV),
UINT32(15.000/DV),UINT32(16.125/DV),UINT32(16.875/DV),UINT32(17.625/DV),
UINT32(18.000/DV),UINT32(18.750/DV),UINT32(19.125/DV),UINT32(19.500/DV),
UINT32(19.875/DV),UINT32(20.250/DV),UINT32(20.625/DV),UINT32(21.000/DV)
uint32_t(0.000/DV), uint32_t(9.000/DV),uint32_t(12.000/DV),uint32_t(13.875/DV),
uint32_t(15.000/DV),uint32_t(16.125/DV),uint32_t(16.875/DV),uint32_t(17.625/DV),
uint32_t(18.000/DV),uint32_t(18.750/DV),uint32_t(19.125/DV),uint32_t(19.500/DV),
uint32_t(19.875/DV),uint32_t(20.250/DV),uint32_t(20.625/DV),uint32_t(21.000/DV)
};
#undef DV
/* 0 / 3.0 / 1.5 / 6.0 dB/OCT */
static const UINT32 ksl_shift[4] = { 31, 1, 2, 0 };
static const uint32_t ksl_shift[4] = { 31, 1, 2, 0 };
/* sustain level table (3dB per step) */
/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
#define SC(db) (UINT32) ( db * (2.0/ENV_STEP) )
static const UINT32 sl_tab[16]={
#define SC(db) (uint32_t) ( db * (2.0/ENV_STEP) )
static const uint32_t sl_tab[16]={
SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
};
@ -339,7 +332,6 @@ static const UINT32 sl_tab[16]={
#define RATE_STEPS (8)
static const unsigned char eg_inc[15*RATE_STEPS]={
/*cycle:0 1 2 3 4 5 6 7*/
/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..12 0 (increment by 0 or 1) */
@ -446,10 +438,10 @@ O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
/* multiple table */
#define ML 2
static const UINT8 mul_tab[16]= {
static const uint8_t mul_tab[16]= {
/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15 */
UINT8(0.50*ML), UINT8(1.00*ML), UINT8(2.00*ML), UINT8(3.00*ML), UINT8(4.00*ML), UINT8(5.00*ML), UINT8(6.00*ML), UINT8(7.00*ML),
UINT8(8.00*ML), UINT8(9.00*ML),UINT8(10.00*ML),UINT8(10.00*ML),UINT8(12.00*ML),UINT8(12.00*ML),UINT8(15.00*ML),UINT8(15.00*ML)
uint8_t(0.50*ML), uint8_t(1.00*ML), uint8_t(2.00*ML), uint8_t(3.00*ML), uint8_t(4.00*ML), uint8_t(5.00*ML), uint8_t(6.00*ML), uint8_t(7.00*ML),
uint8_t(8.00*ML), uint8_t(9.00*ML),uint8_t(10.00*ML),uint8_t(10.00*ML),uint8_t(12.00*ML),uint8_t(12.00*ML),uint8_t(15.00*ML),uint8_t(15.00*ML)
};
#undef ML
@ -478,12 +470,12 @@ static unsigned int sin_tab[SIN_LEN * 4];
The whole table takes: 64 * 210 = 13440 samples.
When AM = 1 data is used directly
When AM = 0 data is divided by 4 before being used (loosing precision is important)
When AM = 0 data is divided by 4 before being used (losing precision is important)
*/
#define LFO_AM_TAB_ELEMENTS 210
static const UINT8 lfo_am_table[LFO_AM_TAB_ELEMENTS] = {
static const uint8_t lfo_am_table[LFO_AM_TAB_ELEMENTS] = {
0,0,0,0,0,0,0,
1,1,1,1,
2,2,2,2,
@ -539,8 +531,7 @@ static const UINT8 lfo_am_table[LFO_AM_TAB_ELEMENTS] = {
};
/* LFO Phase Modulation table (verified on real YM3812) */
static const INT8 lfo_pm_table[8*8*2] = {
static const int8_t lfo_pm_table[8*8*2] = {
/* FNUM2/FNUM = 00 0xxxxxxx (0x0000) */
0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 0*/
0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 1*/
@ -582,8 +573,8 @@ static int num_lock = 0;
static signed int phase_modulation; /* phase modulation input (SLOT 2) */
static signed int output;
static UINT32 LFO_AM;
static INT32 LFO_PM;
static uint32_t LFO_AM;
static int32_t LFO_PM;
static bool CalcVoice (FM_OPL *OPL, int voice, float *buffer, int length);
static bool CalcRhythm (FM_OPL *OPL, float *buffer, int length);
@ -591,7 +582,7 @@ static bool CalcRhythm (FM_OPL *OPL, float *buffer, int length);
/* status set and IRQ handling */
INLINE void OPL_STATUS_SET(FM_OPL *OPL,int flag)
static inline void OPL_STATUS_SET(FM_OPL *OPL,int flag)
{
/* set status flag */
OPL->status |= flag;
@ -605,7 +596,7 @@ INLINE void OPL_STATUS_SET(FM_OPL *OPL,int flag)
}
/* status reset and IRQ handling */
INLINE void OPL_STATUS_RESET(FM_OPL *OPL,int flag)
static inline void OPL_STATUS_RESET(FM_OPL *OPL,int flag)
{
/* reset status flag */
OPL->status &=~flag;
@ -619,7 +610,7 @@ INLINE void OPL_STATUS_RESET(FM_OPL *OPL,int flag)
}
/* IRQ mask set */
INLINE void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag)
static inline void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag)
{
OPL->statusmask = flag;
/* IRQ handling check */
@ -629,13 +620,13 @@ INLINE void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag)
/* advance LFO to next sample */
INLINE void advance_lfo(FM_OPL *OPL)
static inline void advance_lfo(FM_OPL *OPL)
{
UINT8 tmp;
uint8_t tmp;
/* LFO */
OPL->lfo_am_cnt += OPL->lfo_am_inc;
if (OPL->lfo_am_cnt >= (UINT32)(LFO_AM_TAB_ELEMENTS<<LFO_SH) ) /* lfo_am_table is 210 elements long */
if (OPL->lfo_am_cnt >= (uint32_t)(LFO_AM_TAB_ELEMENTS<<LFO_SH) ) /* lfo_am_table is 210 elements long */
OPL->lfo_am_cnt -= (LFO_AM_TAB_ELEMENTS<<LFO_SH);
tmp = lfo_am_table[ OPL->lfo_am_cnt >> LFO_SH ];
@ -650,7 +641,7 @@ INLINE void advance_lfo(FM_OPL *OPL)
}
/* advance to next sample */
INLINE void advance(FM_OPL *OPL, int loch, int hich)
static inline void advance(FM_OPL *OPL, int loch, int hich)
{
OPL_CH *CH;
OPL_SLOT *op;
@ -695,7 +686,7 @@ INLINE void advance(FM_OPL *OPL, int loch, int hich)
{
op->volume += eg_inc[op->eg_sel_dr + ((OPL->eg_cnt>>op->eg_sh_dr)&7)];
if ( op->volume >= (INT32)op->sl )
if ( op->volume >= (int32_t)op->sl )
op->state = EG_SUS;
}
@ -746,7 +737,7 @@ INLINE void advance(FM_OPL *OPL, int loch, int hich)
/* Phase Generator */
if(op->vib)
{
UINT8 block;
uint8_t block;
unsigned int block_fnum = CH->block_fnum;
unsigned int fnum_lfo = (block_fnum&0x0380) >> 7;
@ -772,7 +763,7 @@ INLINE void advance(FM_OPL *OPL, int loch, int hich)
}
}
INLINE void advance_noise(FM_OPL *OPL)
static inline void advance_noise(FM_OPL *OPL)
{
int i;
@ -793,7 +784,7 @@ INLINE void advance_noise(FM_OPL *OPL)
while (i)
{
/*
UINT32 j;
uint32_t j;
j = ( (OPL->noise_rng) ^ (OPL->noise_rng>>14) ^ (OPL->noise_rng>>15) ^ (OPL->noise_rng>>22) ) & 1;
OPL->noise_rng = (j<<22) | (OPL->noise_rng>>1);
*/
@ -814,9 +805,9 @@ INLINE void advance_noise(FM_OPL *OPL)
}
INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab)
static inline signed int op_calc(uint32_t phase, unsigned int env, signed int pm, unsigned int wave_tab)
{
UINT32 p;
uint32_t p;
p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + (pm<<16))) >> FREQ_SH ) & SIN_MASK) ];
@ -825,9 +816,9 @@ INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm, unsigne
return tl_tab[p];
}
INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab)
static inline signed int op_calc1(uint32_t phase, unsigned int env, signed int pm, unsigned int wave_tab)
{
UINT32 p;
uint32_t p;
p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + pm )) >> FREQ_SH ) & SIN_MASK) ];
@ -837,10 +828,10 @@ INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsign
}
#define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (LFO_AM & (OP)->AMmask))
#define volume_calc(OP) ((OP)->TLL + ((uint32_t)(OP)->volume) + (LFO_AM & (OP)->AMmask))
/* calculate output */
INLINE float OPL_CALC_CH( OPL_CH *CH )
static inline float OPL_CALC_CH( OPL_CH *CH )
{
OPL_SLOT *SLOT;
unsigned int env;
@ -911,7 +902,7 @@ number number BLK/FNUM2 FNUM Drum Hat Drum Tom Cymbal
/* calculate rhythm */
INLINE void OPL_CALC_RH( OPL_CH *CH, unsigned int noise )
static inline void OPL_CALC_RH( OPL_CH *CH, unsigned int noise )
{
OPL_SLOT *SLOT;
signed int out;
@ -988,7 +979,7 @@ INLINE void OPL_CALC_RH( OPL_CH *CH, unsigned int noise )
/* when res1 = 0 phase = 0x000 | 0xd0; */
/* when res1 = 1 phase = 0x200 | (0xd0>>2); */
UINT32 phase = res1 ? (0x200|(0xd0>>2)) : 0xd0;
uint32_t phase = res1 ? (0x200|(0xd0>>2)) : 0xd0;
/* enable gate based on frequency of operator 2 in channel 8 */
unsigned char bit5e= ((CH[8].SLOT[SLOT2].Cnt>>FREQ_SH)>>5)&1;
@ -1029,7 +1020,7 @@ INLINE void OPL_CALC_RH( OPL_CH *CH, unsigned int noise )
/* when bit8 = 0 phase = 0x100; */
/* when bit8 = 1 phase = 0x200; */
UINT32 phase = bit8 ? 0x200 : 0x100;
uint32_t phase = bit8 ? 0x200 : 0x100;
/* Noise bit XOR'es phase by 0x100 */
/* when noisebit = 0 pass the phase from calculation above */
@ -1059,7 +1050,7 @@ INLINE void OPL_CALC_RH( OPL_CH *CH, unsigned int noise )
/* when res1 = 0 phase = 0x000 | 0x100; */
/* when res1 = 1 phase = 0x200 | 0x100; */
UINT32 phase = res1 ? 0x300 : 0x100;
uint32_t phase = res1 ? 0x300 : 0x100;
/* enable gate based on frequency of operator 2 in channel 8 */
unsigned char bit5e= ((CH[8].SLOT[SLOT2].Cnt>>FREQ_SH)>>5)&1;
@ -1073,7 +1064,6 @@ INLINE void OPL_CALC_RH( OPL_CH *CH, unsigned int noise )
output += op_calc(phase<<FREQ_SH, env, 0, CH[8].SLOT[SLOT2].wavetable) * 2;
}
}
@ -1176,18 +1166,18 @@ static void OPL_initalize(FM_OPL *OPL)
for( i=0 ; i < 1024 ; i++ )
{
/* opn phase increment counter = 20bit */
OPL->fn_tab[i] = (UINT32)( (double)i * 64 * OPL_FREQBASE * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */
OPL->fn_tab[i] = (uint32_t)( (double)i * 64 * OPL_FREQBASE * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */
}
/* Amplitude modulation: 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples */
/* One entry from LFO_AM_TABLE lasts for 64 samples */
OPL->lfo_am_inc = UINT32((1.0 / 64.0 ) * (1<<LFO_SH) * OPL_FREQBASE);
OPL->lfo_am_inc = uint32_t((1.0 / 64.0 ) * (1<<LFO_SH) * OPL_FREQBASE);
/* Vibrato: 8 output levels (triangle waveform); 1 level takes 1024 samples */
OPL->lfo_pm_inc = UINT32((1.0 / 1024.0) * (1<<LFO_SH) * OPL_FREQBASE);
OPL->lfo_pm_inc = uint32_t((1.0 / 1024.0) * (1<<LFO_SH) * OPL_FREQBASE);
OPL->eg_timer_add = UINT32((1<<EG_SH) * OPL_FREQBASE);
OPL->eg_timer_overflow = UINT32(( 1 ) * (1<<EG_SH));
OPL->eg_timer_add = uint32_t((1<<EG_SH) * OPL_FREQBASE);
OPL->eg_timer_overflow = uint32_t(( 1 ) * (1<<EG_SH));
// [RH] Support full MIDI panning. (But default to mono and center panning.)
OPL->IsStereo = false;
@ -1198,7 +1188,7 @@ static void OPL_initalize(FM_OPL *OPL)
}
}
INLINE void FM_KEYON(OPL_SLOT *SLOT, UINT32 key_set)
static inline void FM_KEYON(OPL_SLOT *SLOT, uint32_t key_set)
{
if( !SLOT->key )
{
@ -1210,7 +1200,7 @@ INLINE void FM_KEYON(OPL_SLOT *SLOT, UINT32 key_set)
SLOT->key |= key_set;
}
INLINE void FM_KEYOFF(OPL_SLOT *SLOT, UINT32 key_clr)
static inline void FM_KEYOFF(OPL_SLOT *SLOT, uint32_t key_clr)
{
if( SLOT->key )
{
@ -1226,7 +1216,7 @@ INLINE void FM_KEYOFF(OPL_SLOT *SLOT, UINT32 key_clr)
}
/* update phase increment counter of operator (also update the EG rates if necessary) */
void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)
static inline void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)
{
int ksr;
@ -1257,7 +1247,7 @@ void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)
}
/* set multi,am,vib,EG-TYP,KSR,mul */
void set_mul(FM_OPL *OPL,int slot,int v)
static inline void set_mul(FM_OPL *OPL,int slot,int v)
{
OPL_CH *CH = &OPL->P_CH[slot/2];
OPL_SLOT *SLOT = &CH->SLOT[slot&1];
@ -1271,7 +1261,7 @@ void set_mul(FM_OPL *OPL,int slot,int v)
}
/* set ksl & tl */
void set_ksl_tl(FM_OPL *OPL,int slot,int v)
static inline void set_ksl_tl(FM_OPL *OPL,int slot,int v)
{
OPL_CH *CH = &OPL->P_CH[slot/2];
OPL_SLOT *SLOT = &CH->SLOT[slot&1];
@ -1283,7 +1273,7 @@ void set_ksl_tl(FM_OPL *OPL,int slot,int v)
}
/* set attack rate & decay rate */
INLINE void set_ar_dr(FM_OPL *OPL,int slot,int v)
static inline void set_ar_dr(FM_OPL *OPL,int slot,int v)
{
OPL_CH *CH = &OPL->P_CH[slot/2];
OPL_SLOT *SLOT = &CH->SLOT[slot&1];
@ -1307,7 +1297,7 @@ INLINE void set_ar_dr(FM_OPL *OPL,int slot,int v)
}
/* set sustain level & release rate */
void set_sl_rr(FM_OPL *OPL,int slot,int v)
static inline void set_sl_rr(FM_OPL *OPL,int slot,int v)
{
OPL_CH *CH = &OPL->P_CH[slot/2];
OPL_SLOT *SLOT = &CH->SLOT[slot&1];
@ -1352,12 +1342,13 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
}
else
{ /* set IRQ mask ,timer enable*/
UINT8 st1 = v&1;
UINT8 st2 = (v>>1)&1;
uint8_t st1 = v&1;
uint8_t st2 = (v>>1)&1;
/* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */
OPL_STATUS_RESET(OPL, v & (0x78-0x08) );
OPL_STATUSMASK_SET(OPL, (~v) & 0x78 );
/* timer 2 */
if(OPL->st[1] != st2)
{
@ -1468,9 +1459,9 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
}
}
/* update */
if(CH->block_fnum != (UINT32)block_fnum)
if(CH->block_fnum != (uint32_t)block_fnum)
{
UINT8 block = block_fnum >> 10;
uint8_t block = block_fnum >> 10;
CH->block_fnum = block_fnum;
@ -1604,15 +1595,15 @@ public:
{
int i;
UINT8 rhythm = Chip.rhythm&0x20;
uint8_t rhythm = Chip.rhythm&0x20;
UINT32 lfo_am_cnt_bak = Chip.lfo_am_cnt;
UINT32 eg_timer_bak = Chip.eg_timer;
UINT32 eg_cnt_bak = Chip.eg_cnt;
uint32_t lfo_am_cnt_bak = Chip.lfo_am_cnt;
uint32_t eg_timer_bak = Chip.eg_timer;
uint32_t eg_cnt_bak = Chip.eg_cnt;
UINT32 lfo_am_cnt_out = lfo_am_cnt_bak;
UINT32 eg_timer_out = eg_timer_bak;
UINT32 eg_cnt_out = eg_cnt_bak;
uint32_t lfo_am_cnt_out = lfo_am_cnt_bak;
uint32_t eg_timer_out = eg_timer_bak;
uint32_t eg_cnt_out = eg_cnt_bak;
for (i = 0; i <= (rhythm ? 5 : 8); ++i)
{

View file

@ -69,12 +69,12 @@ musicBlock::~musicBlock ()
if (OPLinstruments != NULL) free(OPLinstruments);
}
void musicBlock::writeFrequency(uint slot, uint note, int pitch, uint keyOn)
void musicBlock::writeFrequency(uint32_t slot, uint32_t note, int pitch, uint32_t keyOn)
{
io->OPLwriteFreq (slot, note, pitch, keyOn);
}
void musicBlock::writeModulation(uint slot, struct OPL2instrument *instr, int state)
void musicBlock::writeModulation(uint32_t slot, struct OPL2instrument *instr, int state)
{
if (state)
state = 0x40; /* enable Frequency Vibrato */
@ -83,17 +83,17 @@ void musicBlock::writeModulation(uint slot, struct OPL2instrument *instr, int st
instr->trem_vibr_2 | state);
}
uint musicBlock::calcVolume(uint channelVolume, uint channelExpression, uint noteVolume)
uint32_t musicBlock::calcVolume(uint32_t channelVolume, uint32_t channelExpression, uint32_t noteVolume)
{
noteVolume = ((ulong)channelVolume * channelExpression * noteVolume) / (127*127);
noteVolume = ((uint64_t)channelVolume * channelExpression * noteVolume) / (127*127);
if (noteVolume > 127)
return 127;
else
return noteVolume;
}
int musicBlock::occupyChannel(uint slot, uint channel,
int note, int volume, struct OP2instrEntry *instrument, uchar secondary)
int musicBlock::occupyChannel(uint32_t slot, uint32_t channel,
int note, int volume, struct OP2instrEntry *instrument, uint8_t secondary)
{
struct OPL2instrument *instr;
struct channelEntry *ch = &channels[slot];
@ -142,7 +142,7 @@ int musicBlock::occupyChannel(uint slot, uint channel,
return slot;
}
int musicBlock::releaseChannel(uint slot, uint killed)
int musicBlock::releaseChannel(uint32_t slot, uint32_t killed)
{
struct channelEntry *ch = &channels[slot];
writeFrequency(slot, ch->realnote, ch->pitch, 0);
@ -157,10 +157,10 @@ int musicBlock::releaseChannel(uint slot, uint killed)
return slot;
}
int musicBlock::releaseSustain(uint channel)
int musicBlock::releaseSustain(uint32_t channel)
{
uint i;
uint id = channel;
uint32_t i;
uint32_t id = channel;
for(i = 0; i < io->OPLchannels; i++)
{
@ -170,16 +170,16 @@ int musicBlock::releaseSustain(uint channel)
return 0;
}
int musicBlock::findFreeChannel(uint flag, uint channel, uchar note)
int musicBlock::findFreeChannel(uint32_t flag, uint32_t channel, uint8_t note)
{
uint i;
uint32_t i;
ulong bestfit = 0;
uint bestvoice = 0;
uint32_t bestfit = 0;
uint32_t bestvoice = 0;
for (i = 0; i < io->OPLchannels; ++i)
{
ulong magic;
uint32_t magic;
magic = ((channels[i].flags & CH_FREE) << 24) |
((channels[i].note == note &&
@ -200,9 +200,9 @@ int musicBlock::findFreeChannel(uint flag, uint channel, uchar note)
return bestvoice;
}
struct OP2instrEntry *musicBlock::getInstrument(uint channel, uchar note)
struct OP2instrEntry *musicBlock::getInstrument(uint32_t channel, uint8_t note)
{
uint instrnumber;
uint32_t instrnumber;
if (channel == PERCUSSION)
{
@ -225,7 +225,7 @@ struct OP2instrEntry *musicBlock::getInstrument(uint channel, uchar note)
// code 1: play note
CVAR (Bool, opl_singlevoice, 0, 0)
void musicBlock::OPLplayNote(uint channel, uchar note, int volume)
void musicBlock::OPLplayNote(uint32_t channel, uint8_t note, int volume)
{
int i;
struct OP2instrEntry *instr;
@ -251,11 +251,11 @@ void musicBlock::OPLplayNote(uint channel, uchar note, int volume)
}
// code 0: release note
void musicBlock::OPLreleaseNote(uint channel, uchar note)
void musicBlock::OPLreleaseNote(uint32_t channel, uint8_t note)
{
uint i;
uint id = channel;
uint sustain = driverdata.channelSustain[channel];
uint32_t i;
uint32_t id = channel;
uint32_t sustain = driverdata.channelSustain[channel];
for(i = 0; i < io->OPLchannels; i++)
{
@ -270,10 +270,10 @@ void musicBlock::OPLreleaseNote(uint channel, uchar note)
}
// code 2: change pitch wheel (bender)
void musicBlock::OPLpitchWheel(uint channel, int pitch)
void musicBlock::OPLpitchWheel(uint32_t channel, int pitch)
{
uint i;
uint id = channel;
uint32_t i;
uint32_t id = channel;
// Convert pitch from 14-bit to 7-bit, then scale it, since the player
// code only understands sensitivities of 2 semitones.
@ -292,10 +292,10 @@ void musicBlock::OPLpitchWheel(uint channel, int pitch)
}
// code 4: change control
void musicBlock::OPLchangeControl(uint channel, uchar controller, int value)
void musicBlock::OPLchangeControl(uint32_t channel, uint8_t controller, int value)
{
uint i;
uint id = channel;
uint32_t i;
uint32_t id = channel;
switch (controller)
{
@ -310,7 +310,7 @@ void musicBlock::OPLchangeControl(uint channel, uchar controller, int value)
struct channelEntry *ch = &channels[i];
if (ch->channel == id)
{
uchar flags = ch->flags;
uint8_t flags = ch->flags;
ch->time = MLtime;
if (value >= MOD_MIN)
{
@ -418,7 +418,7 @@ void musicBlock::OPLchangeControl(uint channel, uchar controller, int value)
}
}
void musicBlock::OPLresetControllers(uint chan, int vol)
void musicBlock::OPLresetControllers(uint32_t chan, int vol)
{
driverdata.channelVolume[chan] = vol;
driverdata.channelExpression[chan] = 127;
@ -429,14 +429,14 @@ void musicBlock::OPLresetControllers(uint chan, int vol)
driverdata.channelPitchSens[chan] = 200;
}
void musicBlock::OPLprogramChange(uint channel, int value)
void musicBlock::OPLprogramChange(uint32_t channel, int value)
{
driverdata.channelInstr[channel] = value;
}
void musicBlock::OPLplayMusic(int vol)
{
uint i;
uint32_t i;
for (i = 0; i < CHANNELS; i++)
{
@ -446,7 +446,7 @@ void musicBlock::OPLplayMusic(int vol)
void musicBlock::OPLstopMusic()
{
uint i;
uint32_t i;
for(i = 0; i < io->OPLchannels; i++)
if (!(channels[i].flags & CH_FREE))
releaseChannel(i, 1);
@ -454,10 +454,10 @@ void musicBlock::OPLstopMusic()
int musicBlock::OPLloadBank (FileReader &data)
{
static const uchar masterhdr[8] = { '#','O','P','L','_','I','I','#' };
static const uint8_t masterhdr[8] = { '#','O','P','L','_','I','I','#' };
struct OP2instrEntry *instruments;
uchar filehdr[8];
uint8_t filehdr[8];
data.Read (filehdr, 8);
if (memcmp(filehdr, masterhdr, 8))

View file

@ -22,7 +22,7 @@
* Oct-30-1994 V1.40 V.Arnost
* Added BLASTER variable parsing
* Apr-14-1995 V1.50 V.Arnost
* Some declarations moved from adlib.h to deftypes.h
* Some declarations moved from adlib.h to doomtype.h
* Jul-22-1995 V1.60 V.Arnost
* Ported to Watcom C
* Simplified WriteChannel() and WriteValue()
@ -63,7 +63,7 @@ void OPLio::WriteDelay(int ticks)
{
}
void OPLio::OPLwriteReg(int which, uint reg, uchar data)
void OPLio::OPLwriteReg(int which, uint32_t reg, uint8_t data)
{
if (IsOPL3)
{
@ -80,13 +80,13 @@ void OPLio::OPLwriteReg(int which, uint reg, uchar data)
* Write to an operator pair. To be used for register bases of 0x20, 0x40,
* 0x60, 0x80 and 0xE0.
*/
void OPLio::OPLwriteChannel(uint regbase, uint channel, uchar data1, uchar data2)
void OPLio::OPLwriteChannel(uint32_t regbase, uint32_t channel, uint8_t data1, uint8_t data2)
{
static const uint op_num[OPL2CHANNELS] = {
static const uint32_t op_num[OPL2CHANNELS] = {
0x00, 0x01, 0x02, 0x08, 0x09, 0x0A, 0x10, 0x11, 0x12};
uint which = channel / OPL2CHANNELS;
uint reg = regbase + op_num[channel % OPL2CHANNELS];
uint32_t which = channel / OPL2CHANNELS;
uint32_t reg = regbase + op_num[channel % OPL2CHANNELS];
OPLwriteReg (which, reg, data1);
OPLwriteReg (which, reg+3, data2);
}
@ -95,10 +95,10 @@ void OPLio::OPLwriteChannel(uint regbase, uint channel, uchar data1, uchar data2
* Write to channel a single value. To be used for register bases of
* 0xA0, 0xB0 and 0xC0.
*/
void OPLio::OPLwriteValue(uint regbase, uint channel, uchar value)
void OPLio::OPLwriteValue(uint32_t regbase, uint32_t channel, uint8_t value)
{
uint which = channel / OPL2CHANNELS;
uint reg = regbase + (channel % OPL2CHANNELS);
uint32_t which = channel / OPL2CHANNELS;
uint32_t reg = regbase + (channel % OPL2CHANNELS);
OPLwriteReg (which, reg, value);
}
@ -174,7 +174,7 @@ static WORD frequencies[] =
* That last byte in the table doesn't look right, either, but that's what
* it really is.
*/
void OPLio::OPLwriteFreq(uint channel, uint note, uint pitch, uint keyon)
void OPLio::OPLwriteFreq(uint32_t channel, uint32_t note, uint32_t pitch, uint32_t keyon)
{
int octave = 0;
int j = (note << 5) + pitch;
@ -202,9 +202,9 @@ void OPLio::OPLwriteFreq(uint channel, uint note, uint pitch, uint keyon)
/*
* Adjust volume value (register 0x40)
*/
inline uint OPLio::OPLconvertVolume(uint data, uint volume)
inline uint32_t OPLio::OPLconvertVolume(uint32_t data, uint32_t volume)
{
static uchar volumetable[128] = {
static uint8_t volumetable[128] = {
0, 1, 3, 5, 6, 8, 10, 11,
13, 14, 16, 17, 19, 20, 22, 23,
25, 26, 27, 29, 30, 32, 33, 34,
@ -223,11 +223,11 @@ inline uint OPLio::OPLconvertVolume(uint data, uint volume)
124, 124, 125, 125, 126, 126, 127, 127};
return 0x3F - (((0x3F - data) *
(uint)volumetable[volume <= 127 ? volume : 127]) >> 7);
(uint32_t)volumetable[volume <= 127 ? volume : 127]) >> 7);
}
uint OPLio::OPLpanVolume(uint volume, int pan)
uint32_t OPLio::OPLpanVolume(uint32_t volume, int pan)
{
if (pan >= 0)
return volume;
@ -238,7 +238,7 @@ uint OPLio::OPLpanVolume(uint volume, int pan)
/*
* Write volume data to a channel
*/
void OPLio::OPLwriteVolume(uint channel, struct OPL2instrument *instr, uint volume)
void OPLio::OPLwriteVolume(uint32_t channel, struct OPL2instrument *instr, uint32_t volume)
{
if (instr != 0)
{
@ -251,11 +251,11 @@ void OPLio::OPLwriteVolume(uint channel, struct OPL2instrument *instr, uint volu
/*
* Write pan (balance) data to a channel
*/
void OPLio::OPLwritePan(uint channel, struct OPL2instrument *instr, int pan)
void OPLio::OPLwritePan(uint32_t channel, struct OPL2instrument *instr, int pan)
{
if (instr != 0)
{
uchar bits;
uint8_t bits;
if (pan < -36) bits = 0x10; // left
else if (pan > 36) bits = 0x20; // right
else bits = 0x30; // both
@ -292,7 +292,7 @@ void OPLio::OPLwritePan(uint channel, struct OPL2instrument *instr, int pan)
* data[5] data[12] reg. 0x40 - output level (bottom 6 bits only)
* data[6] reg. 0xC0 - feedback/AM-FM (both operators)
*/
void OPLio::OPLwriteInstrument(uint channel, struct OPL2instrument *instr)
void OPLio::OPLwriteInstrument(uint32_t channel, struct OPL2instrument *instr)
{
OPLwriteChannel(0x40, channel, 0x3F, 0x3F); // no volume
OPLwriteChannel(0x20, channel, instr->trem_vibr_1, instr->trem_vibr_2);
@ -307,7 +307,7 @@ void OPLio::OPLwriteInstrument(uint channel, struct OPL2instrument *instr)
*/
void OPLio::OPLshutup(void)
{
uint i;
uint32_t i;
for(i = 0; i < OPLchannels; i++)
{
@ -321,10 +321,10 @@ void OPLio::OPLshutup(void)
/*
* Initialize hardware upon startup
*/
int OPLio::OPLinit(uint numchips, bool stereo, bool initopl3)
int OPLio::OPLinit(uint32_t numchips, bool stereo, bool initopl3)
{
assert(numchips >= 1 && numchips <= countof(chips));
uint i;
uint32_t i;
IsOPL3 = (current_opl_core == 1 || current_opl_core == 2 || current_opl_core == 3);
memset(chips, 0, sizeof(chips));
@ -349,7 +349,7 @@ int OPLio::OPLinit(uint numchips, bool stereo, bool initopl3)
void OPLio::OPLwriteInitState(bool initopl3)
{
for (uint i = 0; i < NumChips; ++i)
for (uint32_t i = 0; i < NumChips; ++i)
{
int chip = i << (int)IsOPL3;
if (IsOPL3 && initopl3)

View file

@ -289,7 +289,7 @@ FString OPLMIDIDevice::GetStats()
{
FString out;
char star[3] = { TEXTCOLOR_ESCAPE, 'A', '*' };
for (uint i = 0; i < io->OPLchannels; ++i)
for (uint32_t i = 0; i < io->OPLchannels; ++i)
{
if (channels[i].flags & CH_FREE)
{

View file

@ -336,7 +336,7 @@ DiskWriterIO::~DiskWriterIO()
//
//==========================================================================
int DiskWriterIO::OPLinit(uint numchips, bool, bool initopl3)
int DiskWriterIO::OPLinit(uint32_t numchips, bool, bool initopl3)
{
FILE *file = fopen(Filename, "wb");
if (file == NULL)

View file

@ -76,7 +76,7 @@ Voice-mail (Czech language only, not recommended; weekends only):
#define __MUSLIB_H_
#ifndef __DEFTYPES_H_
#include "deftypes.h"
#include "doomtype.h"
#endif
class FileReader;
@ -119,7 +119,7 @@ struct OPL2instrument {
/*0B*/ BYTE scale_2; /* OP 2: key scale level */
/*0C*/ BYTE level_2; /* OP 2: output level */
/*0D*/ BYTE unused;
/*0E*/ sshort basenote; /* base note offset */
/*0E*/ int16_t basenote; /* base note offset */
};
/* OP2 instrument file entry */
@ -152,41 +152,41 @@ struct OP2instrEntry {
#define CH_FREE 0x80
struct OPLdata {
uint channelInstr[CHANNELS]; // instrument #
uchar channelVolume[CHANNELS]; // volume
uchar channelLastVolume[CHANNELS]; // last volume
schar channelPan[CHANNELS]; // pan, 0=normal
schar channelPitch[CHANNELS]; // pitch wheel, 64=normal
uchar channelSustain[CHANNELS]; // sustain pedal value
uchar channelModulation[CHANNELS]; // modulation pot value
ushort channelPitchSens[CHANNELS]; // pitch sensitivity, 2=default
ushort channelRPN[CHANNELS]; // RPN number for data entry
uchar channelExpression[CHANNELS]; // expression
uint32_t channelInstr[CHANNELS]; // instrument #
uint8_t channelVolume[CHANNELS]; // volume
uint8_t channelLastVolume[CHANNELS]; // last volume
int8_t channelPan[CHANNELS]; // pan, 0=normal
int8_t channelPitch[CHANNELS]; // pitch wheel, 64=normal
uint8_t channelSustain[CHANNELS]; // sustain pedal value
uint8_t channelModulation[CHANNELS]; // modulation pot value
uint16_t channelPitchSens[CHANNELS]; // pitch sensitivity, 2=default
uint16_t channelRPN[CHANNELS]; // RPN number for data entry
uint8_t channelExpression[CHANNELS]; // expression
};
struct OPLio {
virtual ~OPLio();
void OPLwriteChannel(uint regbase, uint channel, uchar data1, uchar data2);
void OPLwriteValue(uint regbase, uint channel, uchar value);
void OPLwriteFreq(uint channel, uint freq, uint octave, uint keyon);
uint OPLconvertVolume(uint data, uint volume);
uint OPLpanVolume(uint volume, int pan);
void OPLwriteVolume(uint channel, struct OPL2instrument *instr, uint volume);
void OPLwritePan(uint channel, struct OPL2instrument *instr, int pan);
void OPLwriteInstrument(uint channel, struct OPL2instrument *instr);
void OPLwriteChannel(uint32_t regbase, uint32_t channel, uint8_t data1, uint8_t data2);
void OPLwriteValue(uint32_t regbase, uint32_t channel, uint8_t value);
void OPLwriteFreq(uint32_t channel, uint32_t freq, uint32_t octave, uint32_t keyon);
uint32_t OPLconvertVolume(uint32_t data, uint32_t volume);
uint32_t OPLpanVolume(uint32_t volume, int pan);
void OPLwriteVolume(uint32_t channel, struct OPL2instrument *instr, uint32_t volume);
void OPLwritePan(uint32_t channel, struct OPL2instrument *instr, int pan);
void OPLwriteInstrument(uint32_t channel, struct OPL2instrument *instr);
void OPLshutup(void);
void OPLwriteInitState(bool initopl3);
virtual int OPLinit(uint numchips, bool stereo=false, bool initopl3=false);
virtual int OPLinit(uint32_t numchips, bool stereo=false, bool initopl3=false);
virtual void OPLdeinit(void);
virtual void OPLwriteReg(int which, uint reg, uchar data);
virtual void OPLwriteReg(int which, uint32_t reg, uint8_t data);
virtual void SetClockRate(double samples_per_tick);
virtual void WriteDelay(int ticks);
class OPLEmul *chips[MAXOPL2CHIPS];
uint OPLchannels;
uint NumChips;
uint32_t OPLchannels;
uint32_t NumChips;
bool IsOPL3;
};
@ -195,7 +195,7 @@ struct DiskWriterIO : public OPLio
DiskWriterIO(const char *filename);
~DiskWriterIO();
int OPLinit(uint numchips, bool notused, bool initopl3);
int OPLinit(uint32_t numchips, bool notused, bool initopl3);
void SetClockRate(double samples_per_tick);
void WriteDelay(int ticks);
@ -214,14 +214,14 @@ struct musicBlock {
struct OP2instrEntry *OPLinstruments;
ulong MLtime;
uint32_t MLtime;
void OPLplayNote(uint channel, uchar note, int volume);
void OPLreleaseNote(uint channel, uchar note);
void OPLpitchWheel(uint channel, int pitch);
void OPLchangeControl(uint channel, uchar controller, int value);
void OPLprogramChange(uint channel, int value);
void OPLresetControllers(uint channel, int vol);
void OPLplayNote(uint32_t channel, uint8_t note, int volume);
void OPLreleaseNote(uint32_t channel, uint8_t note);
void OPLpitchWheel(uint32_t channel, int pitch);
void OPLchangeControl(uint32_t channel, uint8_t controller, int value);
void OPLprogramChange(uint32_t channel, int value);
void OPLresetControllers(uint32_t channel, int vol);
void OPLplayMusic(int vol);
void OPLstopMusic();
@ -230,27 +230,27 @@ struct musicBlock {
protected:
/* OPL channel (voice) data */
struct channelEntry {
uchar channel; /* MUS channel number */
uchar note; /* note number */
uchar flags; /* see CH_xxx below */
uchar realnote; /* adjusted note number */
schar finetune; /* frequency fine-tune */
sint pitch; /* pitch-wheel value */
uint volume; /* note volume */
uint realvolume; /* adjusted note volume */
uint8_t channel; /* MUS channel number */
uint8_t note; /* note number */
uint8_t flags; /* see CH_xxx below */
uint8_t realnote; /* adjusted note number */
int8_t finetune; /* frequency fine-tune */
int pitch; /* pitch-wheel value */
uint32_t volume; /* note volume */
uint32_t realvolume; /* adjusted note volume */
struct OPL2instrument *instr; /* current instrument */
ulong time; /* note start time */
uint32_t time; /* note start time */
} channels[MAXCHANNELS];
void writeFrequency(uint slot, uint note, int pitch, uint keyOn);
void writeModulation(uint slot, struct OPL2instrument *instr, int state);
uint calcVolume(uint channelVolume, uint channelExpression, uint noteVolume);
int occupyChannel(uint slot, uint channel,
int note, int volume, struct OP2instrEntry *instrument, uchar secondary);
int releaseChannel(uint slot, uint killed);
int releaseSustain(uint channel);
int findFreeChannel(uint flag, uint channel, uchar note);
struct OP2instrEntry *getInstrument(uint channel, uchar note);
void writeFrequency(uint32_t slot, uint32_t note, int pitch, uint32_t keyOn);
void writeModulation(uint32_t slot, struct OPL2instrument *instr, int state);
uint32_t calcVolume(uint32_t channelVolume, uint32_t channelExpression, uint32_t noteVolume);
int occupyChannel(uint32_t slot, uint32_t channel,
int note, int volume, struct OP2instrEntry *instrument, uint8_t secondary);
int releaseChannel(uint32_t slot, uint32_t killed);
int releaseSustain(uint32_t channel);
int findFreeChannel(uint32_t flag, uint32_t channel, uint8_t note);
struct OP2instrEntry *getInstrument(uint32_t channel, uint8_t note);
friend class Stat_opl;

View file

@ -856,6 +856,7 @@ void P_Spawn3DFloors (void)
{
case ExtraFloor_LightOnly:
if (line.args[1] < 0 || line.args[1] > 2) line.args[1] = 0;
if (line.args[0] != 0)
P_Set3DFloor(&line, 3, flagvals[line.args[1]], 0);
break;
@ -875,6 +876,7 @@ void P_Spawn3DFloors (void)
line.args[4]=0;
}
}
if (line.args[0] != 0)
P_Set3DFloor(&line, line.args[1]&~8, line.args[2], line.args[3]);
break;

View file

@ -1097,7 +1097,7 @@ public:
{
ld->alpha = 0.75;
}
if (strifetrans2 && ld->alpha == OPAQUE)
if (strifetrans2 && ld->alpha == 1.)
{
ld->alpha = 0.25;
}

View file

@ -6368,11 +6368,8 @@ ExpEmit FxClassDefaults::Emit(VMFunctionBuilder *build)
//==========================================================================
FxGlobalVariable::FxGlobalVariable(PField* mem, const FScriptPosition &pos)
: FxExpression(EFX_GlobalVariable, pos)
: FxMemberBase(EFX_GlobalVariable, mem, pos)
{
membervar = mem;
AddressRequested = false;
AddressWritable = true; // must be true unless classx tells us otherwise if requested.
}
//==========================================================================
@ -6548,11 +6545,8 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build)
//==========================================================================
FxStackVariable::FxStackVariable(PType *type, int offset, const FScriptPosition &pos)
: FxExpression(EFX_StackVariable, pos)
: FxMemberBase(EFX_StackVariable, new PField(NAME_None, type, 0, offset), pos)
{
membervar = new PField(NAME_None, type, 0, offset);
AddressRequested = false;
AddressWritable = true; // must be true unless classx tells us otherwise if requested.
}
//==========================================================================
@ -6651,14 +6645,16 @@ ExpEmit FxStackVariable::Emit(VMFunctionBuilder *build)
//
//
//==========================================================================
FxMemberBase::FxMemberBase(EFxType type, PField *f, const FScriptPosition &p)
:FxExpression(type, p), membervar(f)
{
}
FxStructMember::FxStructMember(FxExpression *x, PField* mem, const FScriptPosition &pos)
: FxExpression(EFX_StructMember, pos)
: FxMemberBase(EFX_StructMember, mem, pos)
{
classx = x;
membervar = mem;
AddressRequested = false;
AddressWritable = true; // must be true unless classx tells us otherwise if requested.
}
//==========================================================================
@ -6730,35 +6726,13 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx)
else if (classx->ValueType->IsKindOf(RUNTIME_CLASS(PStruct)))
{
// if this is a struct within a class or another struct we can simplify the expression by creating a new PField with a cumulative offset.
if (classx->ExprType == EFX_ClassMember || classx->ExprType == EFX_StructMember)
if (classx->ExprType == EFX_ClassMember || classx->ExprType == EFX_StructMember || classx->ExprType == EFX_GlobalVariable || classx->ExprType == EFX_StackVariable)
{
auto parentfield = static_cast<FxStructMember *>(classx)->membervar;
auto parentfield = static_cast<FxMemberBase *>(classx)->membervar;
// PFields are garbage collected so this will be automatically taken care of later.
auto newfield = new PField(membervar->SymbolName, membervar->Type, membervar->Flags | parentfield->Flags, membervar->Offset + parentfield->Offset);
newfield->BitValue = membervar->BitValue;
static_cast<FxStructMember *>(classx)->membervar = newfield;
classx->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away.
auto x = classx->Resolve(ctx);
classx = nullptr;
return x;
}
else if (classx->ExprType == EFX_GlobalVariable)
{
auto parentfield = static_cast<FxGlobalVariable *>(classx)->membervar;
auto newfield = new PField(membervar->SymbolName, membervar->Type, membervar->Flags | parentfield->Flags, membervar->Offset + parentfield->Offset);
newfield->BitValue = membervar->BitValue;
static_cast<FxGlobalVariable *>(classx)->membervar = newfield;
classx->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away.
auto x = classx->Resolve(ctx);
classx = nullptr;
return x;
}
else if (classx->ExprType == EFX_StackVariable)
{
auto parentfield = static_cast<FxStackVariable *>(classx)->membervar;
auto newfield = new PField(membervar->SymbolName, membervar->Type, membervar->Flags | parentfield->Flags, membervar->Offset + parentfield->Offset);
newfield->BitValue = membervar->BitValue;
static_cast<FxStackVariable *>(classx)->ReplaceField(newfield);
static_cast<FxMemberBase *>(classx)->membervar = newfield;
classx->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away.
auto x = classx->Resolve(ctx);
classx = nullptr;
@ -6946,7 +6920,18 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
return nullptr;
}
PArray *arraytype = dyn_cast<PArray>(Array->ValueType);
PArray *arraytype = nullptr;
PType *elementtype = nullptr;
if (Array->IsDynamicArray())
{
PDynArray *darraytype = static_cast<PDynArray*>(Array->ValueType);
elementtype = darraytype->ElementType;
Array->ValueType = NewPointer(NewResizableArray(elementtype)); // change type so that this can use the code for resizable arrays unchanged.
arrayispointer = true;
}
else
{
arraytype = dyn_cast<PArray>(Array->ValueType);
if (arraytype == nullptr)
{
// Check if we got a pointer to an array. Some native data structures (like the line list in sectors) use this.
@ -6960,19 +6945,16 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
arraytype = static_cast<PArray*>(ptype->PointedType);
arrayispointer = true;
}
elementtype = arraytype->ElementType;
}
if (Array->IsResizableArray())
{
// if this is an array within a class or another struct we can simplify the expression by creating a new PField with a cumulative offset.
if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember)
if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember || Array->ExprType == EFX_GlobalVariable || Array->ExprType == EFX_StackVariable)
{
auto parentfield = static_cast<FxStructMember *>(Array)->membervar;
SizeAddr = parentfield->Offset + parentfield->Type->Align;
}
else if (Array->ExprType == EFX_GlobalVariable)
{
auto parentfield = static_cast<FxGlobalVariable *>(Array)->membervar;
SizeAddr = parentfield->Offset + parentfield->Type->Align;
auto parentfield = static_cast<FxMemberBase *>(Array)->membervar;
SizeAddr = parentfield->Offset + sizeof(void*);
}
else
{
@ -6981,54 +6963,32 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
return nullptr;
}
}
else if (index->isConstant())
// constant indices can only be resolved at compile time for statically sized arrays.
else if (index->isConstant() && arraytype != nullptr && !arrayispointer)
{
unsigned indexval = static_cast<FxConstant *>(index)->GetValue().GetInt();
if (indexval >= arraytype->ElementCount && !Array->IsResizableArray())
if (indexval >= arraytype->ElementCount)
{
ScriptPosition.Message(MSG_ERROR, "Array index out of bounds");
delete this;
return nullptr;
}
if (!arrayispointer)
{
// if this is an array within a class or another struct we can simplify the expression by creating a new PField with a cumulative offset.
if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember)
if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember || Array->ExprType == EFX_GlobalVariable || Array->ExprType == EFX_StackVariable)
{
auto parentfield = static_cast<FxStructMember *>(Array)->membervar;
auto parentfield = static_cast<FxMemberBase *>(Array)->membervar;
// PFields are garbage collected so this will be automatically taken care of later.
auto newfield = new PField(NAME_None, arraytype->ElementType, parentfield->Flags, indexval * arraytype->ElementSize + parentfield->Offset);
static_cast<FxStructMember *>(Array)->membervar = newfield;
auto newfield = new PField(NAME_None, elementtype, parentfield->Flags, indexval * arraytype->ElementSize + parentfield->Offset);
static_cast<FxMemberBase *>(Array)->membervar = newfield;
Array->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away.
auto x = Array->Resolve(ctx);
Array = nullptr;
return x;
}
else if (Array->ExprType == EFX_GlobalVariable)
{
auto parentfield = static_cast<FxGlobalVariable *>(Array)->membervar;
auto newfield = new PField(NAME_None, arraytype->ElementType, parentfield->Flags, indexval * arraytype->ElementSize + parentfield->Offset);
static_cast<FxGlobalVariable *>(Array)->membervar = newfield;
Array->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away.
auto x = Array->Resolve(ctx);
Array = nullptr;
return x;
}
else if (Array->ExprType == EFX_StackVariable)
{
auto parentfield = static_cast<FxStackVariable *>(Array)->membervar;
auto newfield = new PField(NAME_None, arraytype->ElementType, parentfield->Flags, indexval * arraytype->ElementSize + parentfield->Offset);
static_cast<FxStackVariable *>(Array)->ReplaceField(newfield);
Array->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away.
auto x = Array->Resolve(ctx);
Array = nullptr;
return x;
}
}
}
ValueType = arraytype->ElementType;
ValueType = elementtype;
if (!Array->RequestAddress(ctx, &AddressWritable))
{
ScriptPosition.Message(MSG_ERROR, "Unable to dereference array.");
@ -7067,17 +7027,8 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
build->Emit(OP_LP, start.RegNum, arrayvar.RegNum, build->GetConstantInt(0));
auto f = new PField(NAME_None, TypeUInt32, 0, SizeAddr);
if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember)
{
static_cast<FxStructMember *>(Array)->membervar = f;
static_cast<FxStructMember *>(Array)->AddressRequested = false;
}
else if (Array->ExprType == EFX_GlobalVariable)
{
static_cast<FxGlobalVariable *>(Array)->membervar = f;
static_cast<FxGlobalVariable *>(Array)->AddressRequested = false;
}
static_cast<FxMemberBase *>(Array)->membervar = f;
static_cast<FxMemberBase *>(Array)->AddressRequested = false;
Array->ValueType = TypeUInt32;
bound = Array->Emit(build);
}
@ -7804,6 +7755,70 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
// same for String methods. It also uses a hidden struct type to define them.
Self->ValueType = TypeStringStruct;
}
else if (Self->IsDynamicArray())
{
if (MethodName == NAME_Size)
{
FxExpression *x = new FxMemberIdentifier(Self, NAME_Size, ScriptPosition); // todo: obfuscate the name to prevent direct access.
Self = nullptr;
delete this;
return x->Resolve(ctx);
}
else
{
auto elementType = static_cast<PDynArray*>(Self->ValueType)->ElementType;
Self->ValueType = static_cast<PDynArray*>(Self->ValueType)->BackingType;
// this requires some added type checks for the passed types.
for (auto &a : ArgList)
{
a = a->Resolve(ctx);
if (a == nullptr)
{
delete this;
return nullptr;
}
if (a->IsDynamicArray())
{
// Copy and Move must turn their parameter into a pointer to the backing struct type.
auto backingtype = static_cast<PDynArray*>(a->ValueType)->BackingType;
if (elementType != static_cast<PDynArray*>(a->ValueType)->ElementType)
{
ScriptPosition.Message(MSG_ERROR, "Type mismatch in function argument");
delete this;
return nullptr;
}
bool writable;
if (!a->RequestAddress(ctx, &writable))
{
ScriptPosition.Message(MSG_ERROR, "Unable to dereference array variable");
delete this;
return nullptr;
}
a->ValueType = NewPointer(backingtype);
// Also change the field's type so the code generator can work with this (actually this requires swapping out the entire field.)
if (Self->ExprType == EFX_StructMember || Self->ExprType == EFX_ClassMember || Self->ExprType == EFX_StackVariable)
{
auto member = static_cast<FxMemberBase*>(Self);
auto newfield = new PField(NAME_None, backingtype, 0, member->membervar->Offset);
member->membervar = newfield;
}
}
else if (a->IsPointer() && Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
{
// the only case which must be checked up front is for pointer arrays receiving a new element.
// Since there is only one native backing class it uses a neutral void pointer as its argument,
// meaning that FxMemberFunctionCall is unable to do a proper check. So we have to do it here.
if (a->ValueType != elementType)
{
ScriptPosition.Message(MSG_ERROR, "Type mismatch in function argument. Got %s, expected %s", a->ValueType->DescriptiveName(), elementType->DescriptiveName());
delete this;
return nullptr;
}
}
}
}
}
else if (Self->IsArray())
{
if (MethodName == NAME_Size)
@ -7826,19 +7841,9 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
else
{
// Resizable arrays can only be defined in C code and they can only exist in pointer form to reduce their impact on the code generator.
if (Self->ExprType == EFX_StructMember || Self->ExprType == EFX_ClassMember)
if (Self->ExprType == EFX_StructMember || Self->ExprType == EFX_ClassMember || Self->ExprType == EFX_GlobalVariable)
{
auto member = static_cast<FxStructMember*>(Self);
auto newfield = new PField(NAME_None, TypeUInt32, VARF_ReadOnly, member->membervar->Offset + member->membervar->Type->Align); // the size is stored right behind the pointer.
member->membervar = newfield;
Self = nullptr;
delete this;
member->ValueType = TypeUInt32;
return member;
}
else if (Self->ExprType == EFX_GlobalVariable)
{
auto member = static_cast<FxGlobalVariable*>(Self);
auto member = static_cast<FxMemberBase*>(Self);
auto newfield = new PField(NAME_None, TypeUInt32, VARF_ReadOnly, member->membervar->Offset + member->membervar->Type->Align); // the size is stored right behind the pointer.
member->membervar = newfield;
Self = nullptr;

View file

@ -333,6 +333,7 @@ public:
bool IsObject() const { return ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && !ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) && ValueType != TypeNullPtr && static_cast<PPointer*>(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PClass)); }
bool IsArray() const { return ValueType->IsKindOf(RUNTIME_CLASS(PArray)) || (ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PArray))); }
bool IsResizableArray() const { return (ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PResizableArray))); } // can only exist in pointer form.
bool IsDynamicArray() const { return (ValueType->IsKindOf(RUNTIME_CLASS(PDynArray))); }
virtual ExpEmit Emit(VMFunctionBuilder *build);
void EmitStatement(VMFunctionBuilder *build);
@ -1313,19 +1314,30 @@ public:
};
//==========================================================================
//
// FxMemberBase
//
//==========================================================================
class FxMemberBase : public FxExpression
{
public:
PField *membervar;
bool AddressRequested = false;
bool AddressWritable = true;
FxMemberBase(EFxType type, PField *f, const FScriptPosition &p);
};
//==========================================================================
//
// FxGlobalVariaböe
//
//==========================================================================
class FxGlobalVariable : public FxExpression
class FxGlobalVariable : public FxMemberBase
{
public:
PField *membervar;
bool AddressRequested;
bool AddressWritable;
FxGlobalVariable(PField*, const FScriptPosition&);
FxExpression *Resolve(FCompileContext&);
bool RequestAddress(FCompileContext &ctx, bool *writable);
@ -1342,19 +1354,17 @@ public:
ExpEmit Emit(VMFunctionBuilder *build);
};
//==========================================================================
//
// FxClassMember
//
//==========================================================================
class FxStructMember : public FxExpression
class FxStructMember : public FxMemberBase
{
public:
FxExpression *classx;
PField *membervar;
bool AddressRequested;
bool AddressWritable;
FxStructMember(FxExpression*, PField*, const FScriptPosition&);
~FxStructMember();
@ -1402,13 +1412,9 @@ public:
//
//==========================================================================
class FxStackVariable : public FxExpression
class FxStackVariable : public FxMemberBase
{
public:
PField *membervar;
bool AddressRequested;
bool AddressWritable;
FxStackVariable(PType *type, int offset, const FScriptPosition&);
~FxStackVariable();
void ReplaceField(PField *newfield);

View file

@ -1137,3 +1137,50 @@ DEFINE_ACTION_FUNCTION(FStringStruct, AppendFormat)
(*self) += s;
return 0;
}
DEFINE_ACTION_FUNCTION(FStringStruct, Mid)
{
PARAM_SELF_STRUCT_PROLOGUE(FString);
PARAM_INT(ipos);
PARAM_INT(ilen);
// validate. we don't want to crash if someone passes negative values.
// with size_t it's handled naturally I think, as it's unsigned, but not in ZScript.
if (ipos < 0) ipos = 0;
if (ilen < 0) ilen = 0;
// convert to size_t to prevent overflows here
size_t slen = self->Len();
size_t pos = (size_t)ipos;
size_t len = (size_t)ilen;
if (pos > slen) pos = slen - 1;
if (pos + len > slen)
len = slen - pos;
FString s = self->Mid(pos, len);
ACTION_RETURN_STRING(s);
}
DEFINE_ACTION_FUNCTION(FStringStruct, Len)
{
PARAM_SELF_STRUCT_PROLOGUE(FString);
ACTION_RETURN_INT(self->Len());
}
// CharAt and CharCodeAt is how JS does it, and JS is similar here in that it doesn't have char type as int.
DEFINE_ACTION_FUNCTION(FStringStruct, CharAt)
{
PARAM_SELF_STRUCT_PROLOGUE(FString);
PARAM_INT(pos);
int slen = self->Len();
if (pos < 0 || pos >= slen)
ACTION_RETURN_STRING("");
ACTION_RETURN_STRING(FString((*self)[pos]));
}
DEFINE_ACTION_FUNCTION(FStringStruct, CharCodeAt)
{
PARAM_SELF_STRUCT_PROLOGUE(FString);
PARAM_INT(pos);
int slen = self->Len();
if (pos < 0 || pos >= slen)
ACTION_RETURN_INT(0);
ACTION_RETURN_INT((*self)[pos]);
}

View file

@ -1358,9 +1358,16 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
case AST_DynArrayType:
if (allowarraytypes)
{
Error(field, "%s: Dynamic array types not implemented yet", name.GetChars());
auto atype = static_cast<ZCC_DynArrayType *>(ztype);
retval = NewDynArray(DetermineType(outertype, field, name, atype->ElementType, false, false));
auto ftype = DetermineType(outertype, field, name, atype->ElementType, false, true);
if (ftype->GetRegType() == REGT_NIL || ftype->GetRegCount() > 1)
{
Error(field, "%s: Base type for dynamic array types nust be integral, but got %s", name.GetChars(), ftype->DescriptiveName());
}
else
{
retval = NewDynArray(ftype);
}
break;
}
break;

View file

@ -417,9 +417,14 @@ enum EPickStart
// Although String is a builtin type, this is a convenient way to attach methods to it.
struct StringStruct native
{
native void Replace(String pattern, String replacement);
native static vararg String Format(String fmt, ...);
native vararg void AppendFormat(String fmt, ...);
native void Replace(String pattern, String replacement);
native String Mid(int pos = 0, int len = 2147483647);
native int Len();
native String CharAt(int pos);
native int CharCodeAt(int pos);
}
class Floor : Thinker native

View file

@ -156,7 +156,7 @@ class FastProjectile : Actor
ExplodeMissile (NULL, NULL);
return;
}
if (frac != (0, 0, 0) && ripcount <= 0)
if (!(frac.xy ~== (0, 0)) && ripcount <= 0)
{
ripcount = count >> 3;