mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-04 23:07:46 -04:00
bug fixes in drc, audio, display
This commit is contained in:
parent
8ac9ab7fcb
commit
b9bc876c9c
14 changed files with 130 additions and 93 deletions
|
@ -176,10 +176,10 @@ m16_32_s2_no_unal2:
|
|||
@ filter out DC offset
|
||||
@ in=int_sample (max 20 bit), y=filter memory, r3=tmp
|
||||
.macro DCfilt in y
|
||||
rsb r3, \y, \in, asl #12 @ fixpoint 20.12
|
||||
rsb r3, \y, \in, lsl #12 @ fixpoint 20.12
|
||||
add \y, \y, r3, asr #13
|
||||
sub \in, \in, \y, asr #12
|
||||
sub \in, \in, \in, asr #2 @ reduce audio lvl some
|
||||
sub r3, r3, r3, asr #2 @ reduce audio lvl some
|
||||
asr \in, r3, #12
|
||||
.endm
|
||||
|
||||
@ mix 32bit audio (with 16bits really used, upper bits indicate overflow) with normal 16 bit audio with left channel only
|
||||
|
|
|
@ -38,7 +38,7 @@ static void dac_recalculate(void)
|
|||
|
||||
for(i = 0; i <= lines; i++)
|
||||
{
|
||||
dac_info[i] = ((pos+(1<<15)) >> 16); // round to nearest
|
||||
dac_info[i] = ((pos+0x8000) >> 16); // round to nearest
|
||||
pos += Pico.snd.fm_mult;
|
||||
}
|
||||
for (i = lines+1; i < sizeof(dac_info) / sizeof(dac_info[0]); i++)
|
||||
|
@ -85,10 +85,10 @@ void PsndRerate(int preserve_state)
|
|||
// calculate Pico.snd.len
|
||||
Pico.snd.len = PicoIn.sndRate / target_fps;
|
||||
Pico.snd.len_e_add = ((PicoIn.sndRate - Pico.snd.len * target_fps) << 16) / target_fps;
|
||||
Pico.snd.len_e_cnt = 0;
|
||||
Pico.snd.len_e_cnt = 0; // Q16
|
||||
|
||||
// samples per line
|
||||
Pico.snd.fm_mult = 65536.0 * PicoIn.sndRate / (target_fps*target_lines);
|
||||
// samples per line (Q16)
|
||||
Pico.snd.fm_mult = 65536LL * PicoIn.sndRate / (target_fps*target_lines);
|
||||
|
||||
// recalculate dac info
|
||||
dac_recalculate();
|
||||
|
@ -176,7 +176,7 @@ PICO_INTERNAL void PsndDoFM(int line_to)
|
|||
int pos, len;
|
||||
int stereo = 0;
|
||||
|
||||
// Q16, number of samples to fill in buffer
|
||||
// Q16, number of samples since last call
|
||||
len = ((line_to-1) * Pico.snd.fm_mult) - Pico.snd.fm_pos;
|
||||
|
||||
// don't do this too often (no more than 256 per sec)
|
||||
|
@ -184,9 +184,9 @@ PICO_INTERNAL void PsndDoFM(int line_to)
|
|||
return;
|
||||
|
||||
// update position and calculate buffer offset and length
|
||||
pos = Pico.snd.fm_pos >> 16;
|
||||
pos = (Pico.snd.fm_pos+0x8000) >> 16;
|
||||
Pico.snd.fm_pos += len;
|
||||
len = (Pico.snd.fm_pos >> 16) - pos;
|
||||
len = ((Pico.snd.fm_pos+0x8000) >> 16) - pos;
|
||||
|
||||
// fill buffer
|
||||
if (PicoIn.opt & POPT_EN_STEREO) {
|
||||
|
@ -195,8 +195,6 @@ PICO_INTERNAL void PsndDoFM(int line_to)
|
|||
}
|
||||
if (PicoIn.opt & POPT_EN_FM)
|
||||
YM2612UpdateOne(PsndBuffer + pos, len, stereo, 1);
|
||||
else
|
||||
memset32(PsndBuffer + pos, 0, len<<stereo);
|
||||
}
|
||||
|
||||
// cdda
|
||||
|
@ -258,6 +256,8 @@ PICO_INTERNAL void PsndClear(void)
|
|||
memset32((int *) out, 0, len/2);
|
||||
if (len & 1) out[len-1] = 0;
|
||||
}
|
||||
if (!(PicoIn.opt & POPT_EN_FM))
|
||||
memset32(PsndBuffer, 0, PicoIn.opt & POPT_EN_STEREO ? len*2 : len);
|
||||
}
|
||||
|
||||
|
||||
|
@ -265,7 +265,7 @@ static int PsndRender(int offset, int length)
|
|||
{
|
||||
int *buf32;
|
||||
int stereo = (PicoIn.opt & 8) >> 3;
|
||||
int fmlen = (Pico.snd.fm_pos >> 16) - offset;
|
||||
int fmlen = ((Pico.snd.fm_pos+0x8000) >> 16) - offset;
|
||||
|
||||
offset <<= stereo;
|
||||
buf32 = PsndBuffer+offset;
|
||||
|
@ -282,15 +282,11 @@ static int PsndRender(int offset, int length)
|
|||
int *fmbuf = buf32 + (fmlen << stereo);
|
||||
if (PicoIn.opt & POPT_EN_FM)
|
||||
YM2612UpdateOne(fmbuf, length-fmlen, stereo, 1);
|
||||
else
|
||||
memset32(fmbuf, 0, (length-fmlen)<<stereo);
|
||||
Pico.snd.fm_pos += (length-fmlen)<<16;
|
||||
}
|
||||
|
||||
// CD: PCM sound
|
||||
if (PicoIn.AHW & PAHW_MCD) {
|
||||
pcd_pcm_update(buf32, length, stereo);
|
||||
//buf32_updated = 1;
|
||||
}
|
||||
|
||||
// CD: CDDA audio
|
||||
|
|
|
@ -564,7 +564,7 @@ INLINE void FM_KEYON(int c , int s )
|
|||
SLOT->ssg ^= SLOT->ssgn;
|
||||
SLOT->ssgn = 0;
|
||||
SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC;
|
||||
if (SLOT->ar + SLOT->ksr < 32+62) {
|
||||
if (SLOT->ar_ksr < 32+62) {
|
||||
if (SLOT->volume > MIN_ATT_INDEX) SLOT->state = EG_ATT;
|
||||
} else {
|
||||
SLOT->volume = MIN_ATT_INDEX;
|
||||
|
@ -619,6 +619,7 @@ INLINE void set_ar_ksr(FM_CH *CH, FM_SLOT *SLOT, int v)
|
|||
int eg_sh_ar, eg_sel_ar;
|
||||
|
||||
SLOT->ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
|
||||
SLOT->ar_ksr = SLOT->ar + SLOT->ksr;
|
||||
|
||||
SLOT->KSR = 3-(v>>6);
|
||||
if (SLOT->KSR != old_KSR)
|
||||
|
@ -627,10 +628,10 @@ INLINE void set_ar_ksr(FM_CH *CH, FM_SLOT *SLOT, int v)
|
|||
}
|
||||
|
||||
/* refresh Attack rate */
|
||||
if ((SLOT->ar + SLOT->ksr) < 32+62)
|
||||
if ((SLOT->ar_ksr) < 32+62)
|
||||
{
|
||||
eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
|
||||
eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
|
||||
eg_sh_ar = eg_rate_shift [SLOT->ar_ksr];
|
||||
eg_sel_ar = eg_rate_select[SLOT->ar_ksr];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -872,7 +873,7 @@ INLINE void update_ssg_eg_phase(FM_SLOT *SLOT)
|
|||
|
||||
if (SLOT->state != EG_ATT) {
|
||||
SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC;
|
||||
if (SLOT->ar + SLOT->ksr < 32+62) {
|
||||
if (SLOT->ar_ksr < 32+62) {
|
||||
if (SLOT->volume > MIN_ATT_INDEX) SLOT->state = EG_ATT;
|
||||
} else {
|
||||
SLOT->volume = MIN_ATT_INDEX;
|
||||
|
@ -972,7 +973,7 @@ static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
|
|||
ct->vol_out3 = (SLOT->vol_ipol*ifrac1 + SLOT->vol_out*ifrac0) >> EG_SH;
|
||||
SLOT = &ct->CH->SLOT[SLOT4];
|
||||
ct->vol_out4 = (SLOT->vol_ipol*ifrac1 + SLOT->vol_out*ifrac0) >> EG_SH;
|
||||
#else
|
||||
#elif 1
|
||||
switch (ct->eg_timer >> EG_SH)
|
||||
{
|
||||
case 0:
|
||||
|
@ -997,6 +998,23 @@ static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
|
|||
ct->vol_out4 = (ct->CH->SLOT[SLOT4].vol_ipol +
|
||||
ct->CH->SLOT[SLOT4].vol_out) >> 1;
|
||||
}
|
||||
#elif 0
|
||||
if (ct->eg_timer >> (EG_SH-1) < EG_TIMER_OVERFLOW >> EG_SH) {
|
||||
ct->vol_out1 = ct->CH->SLOT[SLOT1].vol_ipol;
|
||||
ct->vol_out2 = ct->CH->SLOT[SLOT2].vol_ipol;
|
||||
ct->vol_out3 = ct->CH->SLOT[SLOT3].vol_ipol;
|
||||
ct->vol_out4 = ct->CH->SLOT[SLOT4].vol_ipol;
|
||||
} else {
|
||||
ct->vol_out1 = ct->CH->SLOT[SLOT1].vol_out;
|
||||
ct->vol_out2 = ct->CH->SLOT[SLOT2].vol_out;
|
||||
ct->vol_out3 = ct->CH->SLOT[SLOT3].vol_out;
|
||||
ct->vol_out4 = ct->CH->SLOT[SLOT4].vol_out;
|
||||
}
|
||||
#else
|
||||
ct->vol_out1 = ct->CH->SLOT[SLOT1].vol_out;
|
||||
ct->vol_out2 = ct->CH->SLOT[SLOT2].vol_out;
|
||||
ct->vol_out3 = ct->CH->SLOT[SLOT3].vol_out;
|
||||
ct->vol_out4 = ct->CH->SLOT[SLOT4].vol_out;
|
||||
#endif
|
||||
|
||||
if (ct->pack & 4) continue; /* output disabled */
|
||||
|
@ -1335,12 +1353,13 @@ INLINE void refresh_fc_eg_slot(FM_SLOT *SLOT, int fc, int kc)
|
|||
{
|
||||
int eg_sh, eg_sel;
|
||||
SLOT->ksr = ksr;
|
||||
SLOT->ar_ksr = SLOT->ar + ksr;
|
||||
|
||||
/* calculate envelope generator rates */
|
||||
if ((SLOT->ar + ksr) < 32+62)
|
||||
if ((SLOT->ar_ksr) < 32+62)
|
||||
{
|
||||
eg_sh = eg_rate_shift [SLOT->ar + ksr ];
|
||||
eg_sel = eg_rate_select[SLOT->ar + ksr ];
|
||||
eg_sh = eg_rate_shift [SLOT->ar_ksr];
|
||||
eg_sel = eg_rate_select[SLOT->ar_ksr];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -56,8 +56,9 @@ typedef struct
|
|||
|
||||
UINT8 ssg; /* 0x30 SSG-EG waveform */
|
||||
UINT8 ssgn;
|
||||
UINT16 vol_out; /* 0x32 current output from EG (without LFO) */
|
||||
UINT16 vol_ipol; /* 0x34 interpolator memory */
|
||||
UINT16 ar_ksr; /* 0x32 ar+ksr */
|
||||
UINT16 vol_out; /* 0x34 current output from EG (without LFO) */
|
||||
UINT16 vol_ipol; /* 0x36 interpolator memory */
|
||||
} FM_SLOT;
|
||||
|
||||
|
||||
|
|
|
@ -42,10 +42,10 @@
|
|||
@ r5=slot, r1=eg_cnt, trashes: r0,r2,r3
|
||||
@ writes output to routp, but only if vol_out changes
|
||||
.macro update_eg_phase_slot slot
|
||||
ldrh r0, [r5,#0x32] @ vol_out
|
||||
ldrh r0, [r5,#0x34] @ vol_out
|
||||
ldrb r2, [r5,#0x17] @ state
|
||||
add r3, r5, #0x1c
|
||||
strh r0, [r5,#0x34] @ vol_ipol
|
||||
strh r0, [r5,#0x36] @ vol_ipol
|
||||
tst r2, r2
|
||||
beq 0f @ EG_OFF
|
||||
|
||||
|
@ -182,7 +182,7 @@
|
|||
11:
|
||||
ldrh r3, [r5,#0x18] @ tl
|
||||
add r0, r0, r3 @ volume += tl
|
||||
strh r0, [r5,#0x32] @ vol_out
|
||||
strh r0, [r5,#0x34] @ vol_out
|
||||
.if \slot == SLOT1
|
||||
mov r6, r6, lsr #16
|
||||
orr r6, r0, r6, lsl #16
|
||||
|
@ -207,11 +207,9 @@
|
|||
ldrh r0, [r5,#0x30] @ ssg+ssgn
|
||||
ldrb r2, [r5,#0x17] @ state
|
||||
ldrh r3, [r5,#0x1a] @ volume
|
||||
tst r0, #0x08 @ ssg enabled?
|
||||
beq 9f
|
||||
cmp r2, #EG_REL @ state > EG_REL?
|
||||
ble 9f
|
||||
cmp r3, #0x200 @ volume >= 0x200?
|
||||
cmp r0, #0x08 @ ssg enabled &&
|
||||
cmpge r2, #EG_REL+1 @ state > EG_REL &&
|
||||
cmpge r3, #0x200 @ volume >= 0x200?
|
||||
blt 9f
|
||||
|
||||
tst r0, #0x01
|
||||
|
@ -226,35 +224,33 @@
|
|||
eor r0, r0, #0x4 @ if ( !(ssg&0x04 )
|
||||
tst r0, #0x4
|
||||
cmpne r2, #EG_ATT @ if ( state != EG_ATT )
|
||||
movne r0, #0x400
|
||||
subne r0, r0, #1
|
||||
strneh r0, [r5,#0x1a] @ volume = MAX_ATT
|
||||
movne r3, #0x400
|
||||
subne r3, r3, #1
|
||||
strneh r3, [r5,#0x1a] @ volume = MAX_ATT
|
||||
b 9f
|
||||
|
||||
1: tst r0, #0x02
|
||||
eorne r0, r0, #0x4 @ ssg ^= 4
|
||||
eorne r0, r0, #0x400 @ ssgn ^= 4
|
||||
strneh r0, [r5,#0x30]
|
||||
moveq r3, #0
|
||||
streq r3, [r5,#0x0c] @ phase = 0
|
||||
moveq r0, #0
|
||||
streq r0, [r5,#0x0c] @ phase = 0
|
||||
|
||||
cmp r2, #EG_ATT @ if ( state != EG_ATT )
|
||||
beq 9f
|
||||
|
||||
ldr r3, [r5,#0x1c] @ sl
|
||||
ldr r0, [r5,#0x1c] @ sl
|
||||
mov r2, #EG_SUS @ state = sl==MIN_ATT ? EG_SUS:EG_DEC
|
||||
cmp r3, #0
|
||||
|
||||
ldr r0, [r5,#0x04] @ ar
|
||||
ldr r3, [r5,#0x14] @ ksr
|
||||
movne r2, #EG_DEC
|
||||
add r0, r0, r3
|
||||
cmp r0, #32+62 @ if ( ar+ksr >= 32+62 )
|
||||
ldrlt r0, [r5,#0x1a]
|
||||
movge r0, #0
|
||||
strgeh r0, [r5,#0x1a] @ volume = MIN_ATT
|
||||
|
||||
cmp r0, #0
|
||||
|
||||
ldrh r0, [r5,#0x32] @ ar+ksr
|
||||
movne r2, #EG_DEC
|
||||
cmp r0, #32+62 @ if ( ar+ksr >= 32+62 )
|
||||
movge r3, #0
|
||||
strgeh r3, [r5,#0x1a] @ volume = MIN_ATT
|
||||
bge 9f
|
||||
|
||||
cmp r3, #0
|
||||
movgt r2, #EG_ATT
|
||||
strb r2, [r5,#0x17] @ state
|
||||
9:
|
||||
|
@ -673,10 +669,10 @@ chan_render_loop:
|
|||
ldr r10, [lr, #0x54] @ op1_out
|
||||
@ ldmia lr, {r6,r7} @ load volumes
|
||||
ldr r5, [lr, #0x40] @ CH
|
||||
ldrh r6, [r5, #0x32] @ vol_out values for all slots
|
||||
ldrh r2, [r5, #0x32+SLOT_STRUCT_SIZE*2]
|
||||
ldrh r7, [r5, #0x32+SLOT_STRUCT_SIZE]
|
||||
ldrh r3, [r5, #0x32+SLOT_STRUCT_SIZE*3]
|
||||
ldrh r6, [r5, #0x34] @ vol_out values for all slots
|
||||
ldrh r2, [r5, #0x34+SLOT_STRUCT_SIZE*2]
|
||||
ldrh r7, [r5, #0x34+SLOT_STRUCT_SIZE]
|
||||
ldrh r3, [r5, #0x34+SLOT_STRUCT_SIZE*3]
|
||||
orr r6, r6, r2, lsl #16
|
||||
orr r7, r7, r3, lsl #16
|
||||
|
||||
|
@ -756,28 +752,28 @@ eg_done:
|
|||
cmp r3, #(EG_TIMER_OVERFLOW>>EG_SH)/2
|
||||
bgt 0f @ mix is vol_out
|
||||
|
||||
ldrh r0, [r5,#0x34] @ SLOT1 vol_ipol
|
||||
ldrh r0, [r5,#0x36] @ SLOT1 vol_ipol
|
||||
lsleq r2, r6, #16
|
||||
addeq r0, r0, r2, lsr #16
|
||||
lsreq r0, r0, #1
|
||||
mov r6, r6, lsr #16
|
||||
orr r6, r0, r6, lsl #16
|
||||
|
||||
ldrh r0, [r5,#0x34+SLOT_STRUCT_SIZE*2] @ SLOT2 vol_ipol
|
||||
ldrh r0, [r5,#0x36+SLOT_STRUCT_SIZE*2] @ SLOT2 vol_ipol
|
||||
addeq r0, r0, r6, lsr #16
|
||||
lsreq r0, r0, #1
|
||||
mov r6, r6, lsl #16
|
||||
orr r6, r6, r0
|
||||
ror r6, r6, #16
|
||||
|
||||
ldrh r0, [r5,#0x34+SLOT_STRUCT_SIZE] @ SLOT3 vol_ipol
|
||||
ldrh r0, [r5,#0x36+SLOT_STRUCT_SIZE] @ SLOT3 vol_ipol
|
||||
lsleq r2, r7, #16
|
||||
addeq r0, r0, r2, lsr #16
|
||||
lsreq r0, r0, #1
|
||||
mov r7, r7, lsr #16
|
||||
orr r7, r0, r7, lsl #16
|
||||
|
||||
ldrh r0, [r5,#0x34+SLOT_STRUCT_SIZE*3] @ SLOT4 vol_ipol
|
||||
ldrh r0, [r5,#0x36+SLOT_STRUCT_SIZE*3] @ SLOT4 vol_ipol
|
||||
addeq r0, r0, r7, lsr #16
|
||||
lsreq r0, r0, #1
|
||||
mov r7, r7, lsl #16
|
||||
|
@ -787,22 +783,22 @@ eg_done:
|
|||
@ super-basic... just take value closest to sample point
|
||||
mov r3, r8, lsr #EG_SH-1 @ eg_timer, [0..3<<EG_SH) after loop
|
||||
cmp r3, #(EG_TIMER_OVERFLOW>>EG_SH)
|
||||
bgt 0f @ mix is vol_out
|
||||
bge 0f @ mix is vol_out
|
||||
|
||||
ldrh r0, [r5,#0x34] @ SLOT1 vol_ipol
|
||||
ldrh r0, [r5,#0x36] @ SLOT1 vol_ipol
|
||||
mov r6, r6, lsr #16
|
||||
orr r6, r0, r6, lsl #16
|
||||
|
||||
ldrh r0, [r5,#0x34+SLOT_STRUCT_SIZE*2] @ SLOT2 vol_ipol
|
||||
ldrh r0, [r5,#0x36+SLOT_STRUCT_SIZE*2] @ SLOT2 vol_ipol
|
||||
mov r6, r6, lsl #16
|
||||
orr r6, r6, r0
|
||||
ror r6, r6, #16
|
||||
|
||||
ldrh r0, [r5,#0x34+SLOT_STRUCT_SIZE] @ SLOT3 vol_ipol
|
||||
ldrh r0, [r5,#0x36+SLOT_STRUCT_SIZE] @ SLOT3 vol_ipol
|
||||
mov r7, r7, lsr #16
|
||||
orr r7, r0, r7, lsl #16
|
||||
|
||||
ldrh r0, [r5,#0x34+SLOT_STRUCT_SIZE*3] @ SLOT4 vol_ipol
|
||||
ldrh r0, [r5,#0x36+SLOT_STRUCT_SIZE*3] @ SLOT4 vol_ipol
|
||||
mov r7, r7, lsl #16
|
||||
orr r7, r7, r0
|
||||
ror r7, r7, #16
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue