Merge pull request #8 from DrUm78/FunKey

Last irixxxx's optimizations for 32X and Sega-CD + volume fix
This commit is contained in:
Vincent-FK 2021-06-21 10:43:32 +02:00 committed by GitHub
commit 99a45bbe18
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 2624 additions and 2411 deletions

7
.gitmodules vendored
View File

@ -3,13 +3,16 @@
url = https://github.com/FunKey-Project/picofe-irixxxx.git
[submodule "cpu/cyclone"]
path = cpu/cyclone
url = https://github.com/notaz/cyclone68000.git
url = https://github.com/irixxxx/cyclone68000.git
[submodule "pico/sound/emu2413"]
path = pico/sound/emu2413
url = https://github.com/digital-sound-antiques/emu2413.git
[submodule "pico/cd/libchdr"]
path = pico/cd/libchdr
url = https://github.com/irixxxx/libchdr-picodrive.git
url = https://github.com/rtissera/libchdr.git
[submodule "platform/common/minimp3"]
path = platform/common/minimp3
url = https://github.com/lieff/minimp3
[submodule "platform/common/dr_libs"]
path = platform/common/dr_libs
url = https://github.com/mackron/dr_libs

View File

@ -245,7 +245,8 @@ OBJS += platform/common/mp3_helix.o
else ifeq "$(HAVE_LIBAVCODEC)" "1"
OBJS += platform/common/mp3_libavcodec.o
else
OBJS += platform/common/mp3_minimp3.o
#OBJS += platform/common/mp3_minimp3.o
OBJS += platform/common/mp3_drmp3.o
endif
endif

View File

@ -160,6 +160,9 @@ else ifeq ($(platform), ps3)
CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ -DFAMEC_NO_GOTOS
STATIC_LINKING = 1
NO_MMAP = 1
# PS3 has memory mapped in a way not suitable for DRC
use_sh2drc = 0
use_svpdrc = 0
# sncps3
else ifeq ($(platform), sncps3)
@ -170,6 +173,9 @@ else ifeq ($(platform), sncps3)
CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ -DFAMEC_NO_GOTOS
STATIC_LINKING = 1
NO_MMAP = 1
# PS3 has memory mapped in a way not suitable for DRC
use_sh2drc = 0
use_svpdrc = 0
# Lightweight PS3 Homebrew SDK
else ifeq ($(platform), psl1ght)
@ -179,6 +185,9 @@ else ifeq ($(platform), psl1ght)
CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ -DFAMEC_NO_GOTOS
STATIC_LINKING = 1
NO_MMAP = 1
# PS3 has memory mapped in a way not suitable for DRC
use_sh2drc = 0
use_svpdrc = 0
# PSP
else ifeq ($(platform), psp1)
@ -253,14 +262,18 @@ else ifeq ($(platform), ngc)
TARGET := $(TARGET_NAME)_libretro_$(platform).a
CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT)
AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT)
CFLAGS += -DGEKKO -DHW_DOL -mrvl -mcpu=750 -meabi -mhard-float -DBLARGG_BIG_ENDIAN=1 -D__ppc__
CFLAGS += -DGEKKO -DHW_DOL -mrvl -mcpu=750 -meabi -mhard-float -D__ppc__ -DMSB_FIRST
STATIC_LINKING = 1
NO_MMAP = 1
# Nintendo Wii
else ifeq ($(platform), wii)
TARGET := $(TARGET_NAME)_libretro_$(platform).a
CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT)
AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT)
CFLAGS += -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -DBLARGG_BIG_ENDIAN=1 -D__ppc__
CFLAGS += -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -D__ppc__ -DMSB_FIRST
STATIC_LINKING = 1
NO_MMAP = 1
# Nintendo Wii U
else ifeq ($(platform), wiiu)
@ -268,8 +281,12 @@ else ifeq ($(platform), wiiu)
CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT)
CXX = $(DEVKITPPC)/bin/powerpc-eabi-g++$(EXE_EXT)
AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT)
COMMONFLAGS += -DGEKKO -DWIIU -DHW_RVL -mwup -mcpu=750 -meabi -mhard-float -D__POWERPC__ -D__ppc__ -DMSB_FIRST -DWORDS_BIGENDIAN=1 -I./deps/include/
COMMONFLAGS += -U__INT32_TYPE__ -U __UINT32_TYPE__ -D__INT32_TYPE__=int
CFLAGS += -DGEKKO -DWIIU -DHW_RVL -mwup -mcpu=750 -meabi -mhard-float -D__ppc__ -DMSB_FIRST
STATIC_LINKING = 1
NO_MMAP = 1
# Wii U has memory mapped in a way not suitable for DRC
use_sh2drc = 0
use_svpdrc = 0
# Nintendo Switch (libtransistor)
else ifeq ($(platform), switch)

@ -1 +1 @@
Subproject commit 94a9d9a888e72cbfa4db12113cd113cf5e154f7f
Subproject commit 1f03ed6a49252bfb900c4d3932094308e1c5b375

View File

@ -1187,7 +1187,7 @@ static void emith_ldst_offs(int sz, int rd, int rn, int o9, int ld, int mode)
#define host_instructions_updated(base, end, force) \
do { if (force) __builtin___clear_cache(base, end); } while (0)
#define emith_update_cache() /**/
#define emith_rw_offs_max() 0xff
#define emith_rw_offs_max() 0x1ff
#define emith_uext_ptr(r) /**/

View File

@ -362,6 +362,11 @@ enum { OPS_STD, OPS_STDU /*,OPS_STQ*/ };
#define PPC_STB_IMM(rt, ra, offs16) \
PPC_OP_IMM(OP_STB,rt,ra,(u16)(offs16))
#define PPC_STXU_IMM(rt, ra, offs16) \
PPC_OP_IMM(OP__ST,rt,ra,((u16)(offs16)&~3)|OPS_STDU)
#define PPC_STWU_IMM(rt, ra, offs16) \
PPC_OP_IMM(OP_STWU,rt,ra,(u16)(offs16))
// load/store, indexed
#define PPC_LDX_REG(rt, ra, rb) \
@ -407,6 +412,7 @@ enum { OPS_STD, OPS_STDU /*,OPS_STQ*/ };
#define PPC_LDP_REG PPC_LDX_REG
#define PPC_STP_IMM PPC_STX_IMM
#define PPC_STP_REG PPC_STX_REG
#define PPC_STPU_IMM PPC_STXU_IMM
#define PPC_BFXP_IMM PPC_BFX_IMM
#define emith_uext_ptr(r) EMIT(PPC_EXTUW_REG(r, r))
@ -440,6 +446,7 @@ enum { OPS_STD, OPS_STDU /*,OPS_STQ*/ };
#define PPC_LDP_REG PPC_LDW_REG
#define PPC_STP_IMM PPC_STW_IMM
#define PPC_STP_REG PPC_STW_REG
#define PPC_STPU_IMM PPC_STWU_IMM
#define PPC_BFXP_IMM PPC_BFXW_IMM
#define emith_uext_ptr(r) /**/
@ -1552,10 +1559,11 @@ static int emith_cond_check(int cond)
static NOINLINE void host_instructions_updated(void *base, void *end, int force)
{
int step = 32, lgstep = 5;
char *_base = base, *_end = end;
int count = (_end - _base + step-1) >> lgstep;
char *_base = (char *)((uptr)base & ~(step-1));
int count = (((char *)end - _base) >> lgstep) + 1;
if (count <= 0) count = 1; // make sure count is positive
base = _base;
asm volatile(
" mtctr %1;"
@ -1587,25 +1595,24 @@ static NOINLINE void host_instructions_updated(void *base, void *end, int force)
#define emith_sh2_drc_entry() do { \
int _c, _z = PTR_SIZE; u32 _m = 0xffffc000; /* r14-r31 */ \
if (__builtin_parity(_m) == 1) _m |= 0x1; /* ABI align for SP is 16 */ \
int _s = count_bits(_m) * _z, _o = 0; \
for (_c = HOST_REGS-1; _m && _c >= 0; _m &= ~(1 << _c), _c--) \
int _s = count_bits(_m) * _z, _o = STACK_EXTRA; \
EMIT(PPC_STPU_IMM(SP, SP, -_s-STACK_EXTRA)); \
EMIT(PPC_MFSP_REG(AT, LR)); \
for (_c = 0; _m && _c < HOST_REGS; _m &= ~(1 << _c), _c++) \
if (_m & (1 << _c)) \
{ _o -= _z; if (_c) emith_write_r_r_offs_ptr(_c, SP, _o); } \
EMIT(PPC_MFSP_REG(10, LR)); \
emith_write_r_r_offs_ptr(10, SP, 2*PTR_SIZE); \
emith_write_r_r_offs_ptr(SP, SP, -_s-STACK_EXTRA); /* XXX stdu */ \
emith_add_r_r_ptr_imm(SP, SP, -_s-STACK_EXTRA); \
{ if (_c) emith_write_r_r_offs_ptr(_c, SP, _o); _o += _z; } \
emith_write_r_r_offs_ptr(AT, SP, _o + _z); \
} while (0)
#define emith_sh2_drc_exit() do { \
int _c, _z = PTR_SIZE; u32 _m = 0xffffc000; \
if (__builtin_parity(_m) == 1) _m |= 0x1; \
int _s = count_bits(_m) * _z, _o = STACK_EXTRA; \
emith_read_r_r_offs_ptr(AT, SP, _o+_s + _z); \
EMIT(PPC_MTSP_REG(AT, LR)); \
for (_c = 0; _m && _c < HOST_REGS; _m &= ~(1 << _c), _c++) \
if (_m & (1 << _c)) \
{ if (_c) emith_read_r_r_offs_ptr(_c, SP, _o); _o += _z; } \
emith_add_r_r_ptr_imm(SP, SP, _s+STACK_EXTRA); \
emith_read_r_r_offs_ptr(10, SP, 2*PTR_SIZE); \
EMIT(PPC_MTSP_REG(10, LR)); \
emith_ret(); \
} while (0)

View File

@ -383,12 +383,9 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI, // x86-64,i386 common
// _r_imm
#define emith_move_r_imm(r, imm) do { \
if (imm) { \
EMIT_REX_IF(0, 0, r); \
EMIT_OP(0xb8 + ((r)&7)); \
EMIT(imm, u32); \
} else \
emith_eor_r_r(r, r); \
EMIT_REX_IF(0, 0, r); \
EMIT_OP(0xb8 + ((r)&7)); \
EMIT(imm, u32); \
} while (0)
#define emith_move_r_ptr_imm(r, imm) do { \

View File

@ -4614,7 +4614,7 @@ OPCODE(0x013C)
src = 1 << (src & 7);
FETCH_BYTE(res);
flag_NotZ = res & src;
RET(8)
RET(10)
}
// BTST
@ -19318,6 +19318,7 @@ OPCODE(0x4E73)
AREG(7) = ASP;
ASP = res;
}
CHECK_BRANCH_EXCEPTION(res)
POST_IO
ctx->execinfo &= ~(FM68K_EMULATE_GROUP_0|FM68K_EMULATE_TRACE|FM68K_DO_TRACE);
CHECK_INT_TO_JUMP(20)
@ -24027,11 +24028,7 @@ OPCODE(0x5048)
dst = AREGu32((Opcode >> 0) & 7);
res = dst + src;
AREG((Opcode >> 0) & 7) = res;
#ifdef USE_CYCLONE_TIMING
RET(4)
#else
RET(8)
#endif
}
// ADDQ

View File

@ -389,7 +389,7 @@ addi 32 . . 0000011010...... A+-DXWL... U U U U 20 20 4 4
addq 8 . d 0101...000000... .......... U U U U 4 4 2 2
addq 8 . . 0101...000...... A+-DXWL... U U U U 8 8 4 4
addq 16 . d 0101...001000... .......... U U U U 4 4 2 2
addq 16 . a 0101...001001... .......... U U U U 4 4 2 2
addq 16 . a 0101...001001... .......... U U U U 8 8 2 2
addq 16 . . 0101...001...... A+-DXWL... U U U U 8 8 4 4
addq 32 . d 0101...010000... .......... U U U U 8 8 2 2
addq 32 . a 0101...010001... .......... U U U U 8 8 2 2

View File

@ -43,7 +43,7 @@ extern void m68040_fpu_op1(void);
/* ================================= DATA ================================= */
/* ======================================================================== */
int m68ki_initial_cycles;
//int m68ki_initial_cycles;
//int m68ki_remaining_cycles = 0; /* Number of clocks remaining */
uint m68ki_tracing = 0;
uint m68ki_address_space;
@ -828,6 +828,10 @@ int m68k_execute(int num_cycles)
m68ki_instruction_jump_table[REG_IR]();
USE_CYCLES(CYC_INSTRUCTION[REG_IR]); // moving this up may cause a deadlock
/* ASG: update cycles */
USE_CYCLES(CPU_INT_CYCLES);
CPU_INT_CYCLES = 0;
/* Trace m68k_exception, if necessary */
m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
@ -839,10 +843,6 @@ int m68k_execute(int num_cycles)
/* set previous PC to current PC for the next entry into the loop */
REG_PPC = REG_PC;
/* ASG: update cycles */
USE_CYCLES(CPU_INT_CYCLES);
CPU_INT_CYCLES = 0;
/* return how many clocks we used */
return m68ki_initial_cycles - GET_CYCLES();
}

View File

@ -27,14 +27,11 @@
#define M68KCPU__HEADER
// notaz: something's missing this
#ifndef UINT64
#define UINT64 unsigned long long
#endif
#ifndef UINT16
#define UINT32 unsigned int
#define UINT16 unsigned short
#define UINT8 unsigned char
#endif
#include <stdint.h>
typedef uint64_t UINT64;
typedef uint32_t UINT32;
typedef uint16_t UINT16;
typedef uint8_t UINT8;
#include "m68k.h"
#include <limits.h>
@ -919,6 +916,7 @@ typedef struct
void (*instr_hook_callback)(void); /* Called every instruction cycle prior to execution */
// notaz
sint cyc_initial_cycles;
sint cyc_remaining_cycles;
sint not_polling;
} m68ki_cpu_core;
@ -926,6 +924,7 @@ typedef struct
// notaz
extern m68ki_cpu_core *m68ki_cpu_p;
#define m68ki_cpu (*m68ki_cpu_p)
#define m68ki_initial_cycles m68ki_cpu_p->cyc_initial_cycles
#define m68ki_remaining_cycles m68ki_cpu_p->cyc_remaining_cycles

View File

@ -641,6 +641,9 @@ int get_oper_cycles(opcode_struct* op, int ea_mode, int cpu_type)
strcmp(op->name, "suba") == 0))
return op->cycles[cpu_type] + g_ea_cycle_table[ea_mode][cpu_type][size] + 2;
if(cpu_type == CPU_TYPE_000 && ea_mode == EA_MODE_I && op->size == 8 && strcmp(op->name, "btst") == 0)
return op->cycles[cpu_type] + g_ea_cycle_table[ea_mode][cpu_type][size] + 2;
if(strcmp(op->name, "jmp") == 0)
return op->cycles[cpu_type] + g_jmp_cycle_table[ea_mode];
if(strcmp(op->name, "jsr") == 0)

View File

@ -203,19 +203,35 @@ static char sh2dasm_buff[64];
(ulong)(sh2)->poll_addr, (sh2)->poll_cycles, (sh2)->poll_cnt); \
}
#if (DRC_DEBUG & (8|256|512|1024)) || defined(PDB)
#if (DRC_DEBUG & (256|512|1024))
static SH2 csh2[2][8];
static FILE *trace[2];
static int topen[2];
#endif
#if (DRC_DEBUG & 8)
static u32 lastpc, lastcnt;
static void *lastblock;
#endif
#if (DRC_DEBUG & (8|256|512|1024)) || defined(PDB)
static void REGPARM(3) *sh2_drc_log_entry(void *block, SH2 *sh2, u32 sr)
{
if (block != NULL) {
dbg(8, "= %csh2 enter %08x %p, c=%d", sh2->is_slave ? 's' : 'm',
sh2->pc, block, (signed int)sr >> 12);
#if defined PDB
dbg(8, "= %csh2 enter %08x %p, c=%d", sh2->is_slave?'s':'m',
sh2->pc, block, (signed int)sr >> 12);
pdb_step(sh2, sh2->pc);
#elif (DRC_DEBUG & 8)
if (lastpc != sh2->pc) {
if (lastcnt)
dbg(8, "= %csh2 enter %08x %p (%d times), c=%d", sh2->is_slave?'s':'m',
lastpc, lastblock, lastcnt, (signed int)sr >> 12);
dbg(8, "= %csh2 enter %08x %p, c=%d", sh2->is_slave?'s':'m',
sh2->pc, block, (signed int)sr >> 12);
lastpc = sh2->pc;
lastblock = block;
lastcnt = 0;
} else
lastcnt++;
#elif (DRC_DEBUG & 256)
{
static SH2 fsh2;
@ -468,7 +484,7 @@ static void rcache_free_tmp(int hr);
#include "../drc/emit_mips.c"
#elif defined(__riscv__) || defined(__riscv)
#include "../drc/emit_riscv.c"
#elif defined(__powerpc__) || defined(_M_PPC)
#elif defined(__powerpc__) || defined(__ppc__) || defined(_M_PPC)
#include "../drc/emit_ppc.c"
#elif defined(__i386__) || defined(_M_X86)
#include "../drc/emit_x86.c"
@ -747,6 +763,7 @@ static void rm_from_hashlist(struct block_entry *be, int tcache_id)
}
#if LINK_BRANCHES
static void add_to_hashlist_unresolved(struct block_link *bl, int tcache_id)
{
u32 tcmask = HASH_TABLE_SIZE(tcache_id) - 1;
@ -789,7 +806,6 @@ static void rm_from_hashlist_unresolved(struct block_link *bl, int tcache_id)
bl->next->prev = bl->prev;
}
#if LINK_BRANCHES
static void dr_block_link(struct block_entry *be, struct block_link *bl, int emit_jump)
{
dbg(2, "- %slink from %p to pc %08x entry %p", emit_jump ? "":"early ",
@ -1017,23 +1033,23 @@ static void dr_rm_block_entry(struct block_desc *bd, int tcache_id, u32 nolit, i
return;
}
#if LINK_BRANCHES
// remove from hash table, make incoming links unresolved
if (bd->active) {
for (i = 0; i < bd->entry_count; i++) {
rm_from_hashlist(&bd->entryp[i], tcache_id);
#if LINK_BRANCHES
while ((bl = bd->entryp[i].links) != NULL) {
dr_block_unlink(bl, 1);
add_to_hashlist_unresolved(bl, tcache_id);
}
#endif
}
dr_mark_memory(-1, bd, tcache_id, nolit);
add_to_block_list(&inactive_blocks[tcache_id], bd);
}
bd->active = 0;
#endif
if (free) {
#if LINK_BRANCHES
@ -1053,7 +1069,6 @@ static void dr_rm_block_entry(struct block_desc *bd, int tcache_id, u32 nolit, i
rm_from_block_lists(bd);
bd->addr = bd->size = bd->addr_lit = bd->size_lit = 0;
bd->entry_count = 0;
bd->entryp = NULL;
}
emith_update_cache();
}
@ -1339,6 +1354,7 @@ static void rcache_add_vreg_alias(int x, sh2_reg_e r);
static void rcache_remove_vreg_alias(int x, sh2_reg_e r);
static void rcache_evict_vreg(int x);
static void rcache_remap_vreg(int x);
static int rcache_get_reg(sh2_reg_e r, rc_gr_mode mode, int *hr);
static void rcache_set_x16(int hr, int s16_, int u16_)
{
@ -1444,7 +1460,6 @@ static int rcache_is_u16(int hr)
} */ \
}
#if PROPAGATE_CONSTANTS
static inline int gconst_alloc(sh2_reg_e r)
{
int i, n = -1;
@ -1481,7 +1496,6 @@ static void gconst_new(sh2_reg_e r, u32 val)
if (guest_regs[r].vreg >= 0)
rcache_remove_vreg_alias(guest_regs[r].vreg, r);
}
#endif
static int gconst_get(sh2_reg_e r, u32 *val)
{
@ -2598,8 +2612,8 @@ static uptr split_address(uptr la, uptr mask, s32 *offs)
uptr sign = (mask>>1) + 1; // sign bit in offset
*offs = (la & mask) | (la & sign ? ~mask : 0); // offset part, sign extended
la = (la & ~mask) + ((la & sign) << 1); // base part, corrected for offs sign
if (~mask && la == ~mask && !(*offs & sign)) { // special case la=-1 & offs>0
*offs = -*offs;
if (~mask && la == ~mask && *offs > 0) { // special case la=-1&~mask && offs>0
*offs -= mask+1;
la = 0;
}
return la;
@ -2661,6 +2675,11 @@ static int emit_get_rbase_and_offs(SH2 *sh2, sh2_reg_e r, int rmode, s32 *offs)
} else {
// known fixed host address
la = split_address(la + ((a + *offs) & mask), omask, offs);
if (la == 0) {
// offset only. optimize for hosts having short indexed addressing
la = *offs & ~0x7f; // keep the lower bits for endianess handling
*offs &= 0x7f;
}
hr = rcache_get_tmp();
emith_move_r_ptr_imm(hr, la);
}
@ -3014,12 +3033,22 @@ static void emit_do_static_regs(int is_write, int tmpr)
// divide operation replacement functions, called by compiled code. Only the
// 32:16 cases and the 64:32 cases described in the SH2 prog man are replaced.
static uint32_t REGPARM(2) sh2_drc_divu32(uint32_t dv, uint32_t ds)
// This is surprisingly difficult since the SH2 division operation is generating
// the result in the dividend during the operation, leaving some remainder-like
// stuff in the bits unused for the result, and leaving the T and Q status bits
// in a state depending on the operands and the result. Q always reflects the
// last result bit generated (i.e. bit 0 of the result). For T:
// 32:16 T = top bit of the 16 bit remainder-like
// 64:32 T = resulting T of the DIV0U/S operation
// The remainder-like depends on outcome of the last generated result bit.
static uint32_t REGPARM(3) sh2_drc_divu32(uint32_t dv, uint32_t *dt, uint32_t ds)
{
if (ds && ds >= dv) {
// good case: no divide by 0, and no result overflow
if (ds > dv && (uint16_t)ds == 0) {
// good case: no overflow, divisor not 0, lower 16 bits 0
uint32_t quot = dv / (ds>>16), rem = dv - (quot * (ds>>16));
if (~quot&1) rem -= ds>>16;
*dt = (rem>>15) & 1;
return (uint16_t)quot | ((2*rem + (quot>>31)) << 16);
} else {
// bad case: use the sh2 algo to get the right result
@ -3029,20 +3058,21 @@ static uint32_t REGPARM(2) sh2_drc_divu32(uint32_t dv, uint32_t ds)
dv = (dv<<1) | t;
t = v;
v = dv;
if (q) dv += ds, q = dv < v;
else dv -= ds, q = !(dv < v);
if (q) dv += ds, q = dv < v;
else dv -= ds, q = dv > v;
q ^= t, t = !q;
}
*dt = dv>>31;
return (dv<<1) | t;
}
}
static uint32_t REGPARM(3) sh2_drc_divu64(uint32_t dh, uint32_t *dl, uint32_t ds)
{
if (ds > 1 && ds >= dh) {
// good case: no divide by 0, and no result overflow
if (ds > dh) {
// good case: no overflow, divisor not 0
uint64_t dv = *dl | ((uint64_t)dh << 32);
uint32_t quot = dv / ds, rem = dv - (quot * ds);
uint32_t quot = dv / ds, rem = dv - ((uint64_t)quot * ds);
if (~quot&1) rem -= ds;
*dl = quot;
return rem;
@ -3055,8 +3085,8 @@ static uint32_t REGPARM(3) sh2_drc_divu64(uint32_t dh, uint32_t *dl, uint32_t ds
dv = (dv<<1) | t;
t = v;
v = dv;
if (q) dv += ((uint64_t)ds << 32), q = dv < v;
else dv -= ((uint64_t)ds << 32), q = !(dv < v);
if (q) dv += ((uint64_t)ds << 32), q = dv < v;
else dv -= ((uint64_t)ds << 32), q = dv > v;
q ^= t, t = !q;
}
*dl = (dv<<1) | t;
@ -3064,16 +3094,17 @@ static uint32_t REGPARM(3) sh2_drc_divu64(uint32_t dh, uint32_t *dl, uint32_t ds
}
}
static uint32_t REGPARM(2) sh2_drc_divs32(int32_t dv, int32_t ds)
static uint32_t REGPARM(3) sh2_drc_divs32(int32_t dv, uint32_t *dt, int32_t ds)
{
uint32_t adv = abs(dv), ads = abs(ds)>>16;
if (ads > 1 && ads > adv>>16 && (int32_t)ads > 0 && !(uint16_t)ds) {
// good case: no divide by 0, and no result overflow
if (ads > adv>>16 && ds != 0x80000000 && (int16_t)ds == 0) {
// good case: no overflow, divisor not 0 and not MIN_INT, lower 16 bits 0
uint32_t quot = adv / ads, rem = adv - (quot * ads);
int m1 = (rem ? dv^ds : ds) < 0;
if (rem && dv < 0) rem = (quot&1 ? -rem : +ads-rem);
else rem = (quot&1 ? +rem : -ads+rem);
quot = ((dv^ds)<0 ? -quot : +quot) - m1;
*dt = (rem>>15) & 1;
return (uint16_t)quot | ((2*rem + (quot>>31)) << 16);
} else {
// bad case: use the sh2 algo to get the right result
@ -3083,10 +3114,11 @@ static uint32_t REGPARM(2) sh2_drc_divs32(int32_t dv, int32_t ds)
dv = (dv<<1) | t;
t = v;
v = dv;
if (m^q) dv += ds, q = (uint32_t)dv < v;
else dv -= ds, q = !((uint32_t)dv < v);
if (m^q) dv += ds, q = (uint32_t)dv < v;
else dv -= ds, q = (uint32_t)dv > v;
q ^= m^t, t = !(m^q);
}
*dt = (uint32_t)dv>>31;
return (dv<<1) | t;
}
}
@ -3096,8 +3128,8 @@ static uint32_t REGPARM(3) sh2_drc_divs64(int32_t dh, uint32_t *dl, int32_t ds)
int64_t _dv = *dl | ((int64_t)dh << 32);
uint64_t adv = (_dv < 0 ? -_dv : _dv); // llabs isn't in older toolchains
uint32_t ads = abs(ds);
if (ads > 1 && ads > adv>>32 && (int64_t)adv > 0) {
// good case: no divide by 0, and no result overflow
if (ads > adv>>32 && ds != 0x80000000) {
// good case: no overflow, divisor not 0 and not MIN_INT
uint32_t quot = adv / ads, rem = adv - ((uint64_t)quot * ads);
int m1 = (rem ? dh^ds : ds) < 0;
if (rem && dh < 0) rem = (quot&1 ? -rem : +ads-rem);
@ -3110,12 +3142,12 @@ static uint32_t REGPARM(3) sh2_drc_divs64(int32_t dh, uint32_t *dl, int32_t ds)
uint64_t dv = *dl | ((uint64_t)dh << 32);
int m = (uint32_t)ds>>31, q = (uint64_t)dv>>63, t = m^q, s = 32;
while (s--) {
int64_t v = (uint64_t)dv>>63;
uint64_t v = (uint64_t)dv>>63;
dv = (dv<<1) | t;
t = v;
v = dv;
if (m^q) dv += ((uint64_t)ds << 32), q = dv < v;
else dv -= ((uint64_t)ds << 32), q = !(dv < v);
if (m^q) dv += ((uint64_t)ds << 32), q = dv < v;
else dv -= ((uint64_t)ds << 32), q = dv > v;
q ^= m^t, t = !(m^q);
}
*dl = (dv<<1) | t;
@ -3508,7 +3540,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
// if exiting a pinned loop pinned regs must be written back to ctx
// since they are reloaded in the loop entry code
emith_cmp_r_imm(sr, 0);
EMITH_JMP_START(DCOND_GT);
EMITH_JMP_START(DCOND_GE);
rcache_save_pinned();
if (blx_target_count < ARRAY_SIZE(blx_targets)) {
@ -3532,13 +3564,13 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
emith_cmp_r_imm(sr, 0);
blx_targets[blx_target_count++] =
(struct linkage) { .pc = pc, .ptr = tcache_ptr, .mask = 0x1 };
emith_jump_cond_patchable(DCOND_LE, tcache_ptr);
emith_jump_cond_patchable(DCOND_LT, tcache_ptr);
} else {
// blx table full, must inline exit code
tmp = rcache_get_tmp_arg(0);
emith_cmp_r_imm(sr, 0);
EMITH_SJMP_START(DCOND_GT);
emith_move_r_imm_c(DCOND_LE, tmp, pc);
emith_move_r_imm_c(DCOND_LT, tmp, pc);
emith_jump_cond(DCOND_LE, sh2_drc_exit);
EMITH_SJMP_END(DCOND_GT);
rcache_free_tmp(tmp);
@ -3921,8 +3953,10 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
#if DIV_OPTIMIZER
if (div(opd).div1 == 16 && div(opd).ro == div(opd).rn) {
// divide 32/16
tmp = rcache_get_tmp_arg(1);
emith_add_r_r_ptr_imm(tmp, CONTEXT_REG, offsetof(SH2, drc_tmp));
rcache_get_reg_arg(0, div(opd).rn, NULL);
rcache_get_reg_arg(1, div(opd).rm, NULL);
rcache_get_reg_arg(2, div(opd).rm, NULL);
rcache_invalidate_tmp();
emith_abicall(sh2_drc_divu32);
tmp = rcache_get_tmp_ret();
@ -3934,8 +3968,9 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
emith_and_r_r_imm(tmp3, tmp2, 1); // Q = !Rn[0]
emith_eor_r_r_imm(tmp3, tmp3, 1);
emith_or_r_r_lsl(sr, tmp3, Q_SHIFT);
emith_ctx_read(tmp3, offsetof(SH2, drc_tmp));
emith_or_r_r_r(sr, sr, tmp3); // T
rcache_free_tmp(tmp3);
emith_or_r_r_r_lsr(sr, sr, tmp2, 31); // T = Rn[31]
skip_op = div(opd).div1 + div(opd).rotcl;
}
else if (div(opd).div1 == 32 && div(opd).ro != div(opd).rn) {
@ -3960,7 +3995,6 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
emith_eor_r_r_imm(tmp3, tmp3, 1);
emith_or_r_r_lsl(sr, tmp3, Q_SHIFT);
rcache_free_tmp(tmp3);
emith_or_r_r_r_lsr(sr, sr, tmp4, 31); // T = Ro[31]
skip_op = div(opd).div1 + div(opd).rotcl;
}
#endif
@ -4035,8 +4069,10 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
#if DIV_OPTIMIZER
if (div(opd).div1 == 16 && div(opd).ro == div(opd).rn) {
// divide 32/16
tmp = rcache_get_tmp_arg(1);
emith_add_r_r_ptr_imm(tmp, CONTEXT_REG, offsetof(SH2, drc_tmp));
rcache_get_reg_arg(0, div(opd).rn, NULL);
tmp2 = rcache_get_reg_arg(1, div(opd).rm, NULL);
tmp2 = rcache_get_reg_arg(2, div(opd).rm, NULL);
tmp3 = rcache_get_tmp();
emith_lsr(tmp3, tmp2, 31);
emith_or_r_r_lsl(sr, tmp3, M_SHIFT); // M = Rm[31]
@ -4052,19 +4088,22 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
emith_and_r_r_imm(tmp3, tmp3, 1);
emith_eor_r_r_imm(tmp3, tmp3, 1);
emith_or_r_r_lsl(sr, tmp3, Q_SHIFT); // Q = !Rn[0]^M
emith_ctx_read(tmp3, offsetof(SH2, drc_tmp));
emith_or_r_r_r(sr, sr, tmp3); // T
rcache_free_tmp(tmp3);
emith_or_r_r_r_lsr(sr, sr, tmp2, 31); // T = Rn[31]
skip_op = div(opd).div1 + div(opd).rotcl;
}
else if (div(opd).div1 == 32 && div(opd).ro != div(opd).rn) {
// divide 64/32
tmp4 = rcache_get_reg(div(opd).ro, RC_GR_READ, NULL);
emith_ctx_write(tmp4, offsetof(SH2, drc_tmp));
rcache_get_reg_arg(0, div(opd).rn, NULL);
tmp = rcache_get_reg_arg(0, div(opd).rn, NULL);
tmp2 = rcache_get_reg_arg(2, div(opd).rm, NULL);
tmp3 = rcache_get_tmp_arg(1);
emith_lsr(tmp3, tmp2, 31);
emith_or_r_r_lsl(sr, tmp3, M_SHIFT); // M = Rm[31]
emith_or_r_r_lsl(sr, tmp3, M_SHIFT); // M = Rm[31]
emith_eor_r_r_lsr(tmp3, tmp, 31);
emith_or_r_r(sr, tmp3); // T = Rn[31]^M
emith_add_r_r_ptr_imm(tmp3, CONTEXT_REG, offsetof(SH2, drc_tmp));
rcache_invalidate_tmp();
emith_abicall(sh2_drc_divs64);
@ -4081,7 +4120,6 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
emith_eor_r_r_imm(tmp3, tmp3, 1);
emith_or_r_r_lsl(sr, tmp3, Q_SHIFT); // Q = !Ro[0]^M
rcache_free_tmp(tmp3);
emith_or_r_r_r_lsr(sr, sr, tmp4, 31); // T = Ro[31]
skip_op = div(opd).div1 + div(opd).rotcl;
} else
#endif
@ -5638,7 +5676,10 @@ int sh2_execute_drc(SH2 *sh2c, int cycles)
// bit11 contains T saved for delay slot
// others are usual SH2 flags
sh2c->sr &= 0x3f3;
sh2c->sr |= cycles << 12;
sh2c->sr |= (cycles-1) << 12;
#if (DRC_DEBUG & 8)
lastpc = lastcnt = 0;
#endif
sh2c->state |= SH2_IN_DRC;
sh2_drc_entry(sh2c);
@ -5646,11 +5687,16 @@ int sh2_execute_drc(SH2 *sh2c, int cycles)
// TODO: irq cycles
ret_cycles = (int32_t)sh2c->sr >> 12;
if (ret_cycles > 0)
if (ret_cycles >= 0)
dbg(1, "warning: drc returned with cycles: %d, pc %08x", ret_cycles, sh2c->pc);
#if (DRC_DEBUG & 8)
if (lastcnt)
dbg(8, "= %csh2 enter %08x %p (%d times), c=%d", sh2c->is_slave?'s':'m',
lastpc, lastblock, lastcnt, (signed int)sh2c->sr >> 12);
#endif
sh2c->sr &= 0x3f3;
return ret_cycles;
return ret_cycles+1;
}
static void block_stats(void)
@ -6177,6 +6223,7 @@ u16 scan_block(u32 base_pc, int is_slave, u8 *op_flags, u32 *end_pc_out,
break;
case 1: // SLEEP 0000000000011011
opd->op = OP_SLEEP;
opd->cycles = 3;
end_block = 1;
break;
case 2: // RTE 0000000000101011

View File

@ -47,7 +47,7 @@ u16 scan_block(u32 base_pc, int is_slave, u8 *op_flags, u32 *end_pc,
#elif defined(__riscv__) || defined(__riscv)
#define DRC_SR_REG "s11"
#define DRC_REG_LL 0 // no ABI for (__ILP32__ && __riscv_xlen != 32)
#elif defined(__powerpc__)
#elif defined(__powerpc__) || defined(__ppc__)
#define DRC_SR_REG "r28"
#define DRC_REG_LL 0 // no ABI for __ILP32__
#elif defined(__i386__)
@ -70,12 +70,13 @@ extern void REGPARM(1) (*sh2_drc_restore_sr)(SH2 *sh2);
#else
#define DRC_DECLARE_SR register long _sh2_sr asm(DRC_SR_REG)
#endif
// NB: save/load SR register only when DRC is executing and not in DMA access
#define DRC_SAVE_SR(sh2) \
if (likely(sh2->state & SH2_IN_DRC)) \
if (likely((sh2->state & (SH2_IN_DRC|SH2_STATE_SLEEP)) == SH2_IN_DRC)) \
sh2->sr = (s32)_sh2_sr
// sh2_drc_save_sr(sh2)
#define DRC_RESTORE_SR(sh2) \
if (likely(sh2->state & SH2_IN_DRC)) \
if (likely((sh2->state & (SH2_IN_DRC|SH2_STATE_SLEEP)) == SH2_IN_DRC)) \
_sh2_sr = (s32)sh2->sr
// sh2_drc_restore_sr(sh2)
#else

View File

@ -167,14 +167,16 @@ int sh2_execute_interpreter(SH2 *sh2, int cycles)
sh2->icount--;
if (sh2->test_irq && !sh2->delay && sh2->pending_level > ((sh2->sr >> 4) & 0x0f))
if (sh2->test_irq && !sh2->delay)
{
int level = sh2->pending_level;
int vector = sh2->irq_callback(sh2, level);
sh2_do_irq(sh2, level, vector);
if (level > ((sh2->sr >> 4) & 0x0f))
{
int vector = sh2->irq_callback(sh2, level);
sh2_do_irq(sh2, level, vector);
}
sh2->test_irq = 0;
}
}
while (sh2->icount > 0 || sh2->delay); /* can't interrupt before delay */
@ -221,7 +223,7 @@ int sh2_execute_interpreter(SH2 *sh2, int cycles)
|| pc_expect != sh2->pc) // branched
{
pc_expect = sh2->pc;
if (sh2->icount < 0)
if (sh2->icount <= 0)
break;
}

View File

@ -50,8 +50,8 @@ typedef struct SH2_
#define SH2_STATE_CPOLL (1 << 2) // polling comm regs
#define SH2_STATE_VPOLL (1 << 3) // polling VDP
#define SH2_STATE_RPOLL (1 << 4) // polling address in SDRAM
#define SH2_TIMER_RUN (1 << 7) // SOC WDT timer is running
#define SH2_IN_DRC (1 << 8) // DRC in use
#define SH2_TIMER_RUN (1 << 6) // SOC WDT timer is running
#define SH2_IN_DRC (1 << 7) // DRC in use
unsigned int state;
uint32_t poll_addr;
int poll_cycles;

View File

@ -56,14 +56,14 @@ void p32x_update_irls(SH2 *active_sh2, unsigned int m68k_cycles)
if (mrun) {
p32x_sh2_poll_event(&msh2, SH2_IDLE_STATES, m68k_cycles);
if (msh2.state & SH2_STATE_RUN)
sh2_end_run(&msh2, 1);
sh2_end_run(&msh2, 0);
}
srun = sh2_irl_irq(&ssh2, slvl, ssh2.state & SH2_STATE_RUN);
if (srun) {
p32x_sh2_poll_event(&ssh2, SH2_IDLE_STATES, m68k_cycles);
if (ssh2.state & SH2_STATE_RUN)
sh2_end_run(&ssh2, 1);
sh2_end_run(&ssh2, 0);
}
elprintf(EL_32X, "update_irls: m %d/%d, s %d/%d", mlvl, mrun, slvl, srun);
@ -142,9 +142,9 @@ void p32x_reset_sh2s(void)
unsigned int vbr;
// initial data
idl_src = CPU_BE2(*(unsigned int *)(Pico.rom + 0x3d4)) & ~0xf0000000;
idl_dst = CPU_BE2(*(unsigned int *)(Pico.rom + 0x3d8)) & ~0xf0000000;
idl_size= CPU_BE2(*(unsigned int *)(Pico.rom + 0x3dc));
idl_src = CPU_BE2(*(u32 *)(Pico.rom + 0x3d4)) & ~0xf0000000;
idl_dst = CPU_BE2(*(u32 *)(Pico.rom + 0x3d8)) & ~0xf0000000;
idl_size= CPU_BE2(*(u32 *)(Pico.rom + 0x3dc));
if (idl_size > Pico.romsize || idl_src + idl_size > Pico.romsize ||
idl_size > 0x40000 || idl_dst + idl_size > 0x40000 || (idl_src & 3) || (idl_dst & 3)) {
elprintf(EL_STATUS|EL_ANOMALY, "32x: invalid initial data ptrs: %06x -> %06x, %06x",
@ -154,11 +154,11 @@ void p32x_reset_sh2s(void)
memcpy(Pico32xMem->sdram + idl_dst, Pico.rom + idl_src, idl_size);
// VBR
vbr = CPU_BE2(*(unsigned int *)(Pico.rom + 0x3e8));
vbr = CPU_BE2(*(u32 *)(Pico.rom + 0x3e8));
sh2_set_vbr(0, vbr);
// checksum and M_OK
Pico32x.regs[0x28 / 2] = *(unsigned short *)(Pico.rom + 0x18e);
Pico32x.regs[0x28 / 2] = *(u16 *)(Pico.rom + 0x18e);
}
// program will set M_OK
}
@ -168,7 +168,7 @@ void p32x_reset_sh2s(void)
unsigned int vbr;
// GBR/VBR
vbr = CPU_BE2(*(unsigned int *)(Pico.rom + 0x3ec));
vbr = CPU_BE2(*(u32 *)(Pico.rom + 0x3ec));
sh2_set_gbr(1, 0x20004000);
sh2_set_vbr(1, vbr);
// program will set S_OK
@ -328,7 +328,7 @@ void p32x_event_schedule_sh2(SH2 *sh2, enum p32x_event event, int after)
left_to_next = C_M68K_TO_SH2(sh2, (int)(event_time_next - now));
if (sh2_cycles_left(sh2) > left_to_next) {
if (left_to_next < 1)
left_to_next = 1;
left_to_next = 0;
sh2_end_run(sh2, left_to_next);
}
}
@ -421,7 +421,7 @@ void p32x_sync_other_sh2(SH2 *sh2, unsigned int m68k_target)
left_to_event = C_M68K_TO_SH2(sh2, (int)(event_time_next - m68k_target));
if (sh2_cycles_left(sh2) > left_to_event) {
if (left_to_event < 1)
left_to_event = 1;
left_to_event = 0;
sh2_end_run(sh2, left_to_event);
}
}

View File

@ -10,7 +10,7 @@
// BGR555 to native conversion
#if defined(USE_BGR555)
#define PXCONV(t) (t)
#define PXCONV(t) ((t)&(mr|mg|mb|mp))
#define PXPRIO 0x8000 // prio in MSB
#elif defined(USE_BGR565)
#define PXCONV(t) (((t)&mr) | (((t)&(mg|mb)) << 1) | (((t)&mp) >> 10))

View File

@ -101,10 +101,46 @@
mov r6, #320
add r5, r1, r12, lsl #1 @ p32x = dram + dram[l]
ldrh r7, [r5], #2
2: @ loop_inner:
ldrh r8, [r5], #2
mov r8, r7
subs lr, r6, #1
blt 0b @ loop_outer
beq 7f @ single_pix
ldrh r7, [r5], #2 @ 32x pixel
cmp r7, r8 @ do RLE only if we have at least 2 px
@ ldreqh r7, [r5]
@ cmpeq r7, r8
subeq lr, lr, #1
beq 3f @ loop_innermost
7: @ single_pix:
mov r6, lr
eor r12,r8, r10
tst r12, #0x8000 @ !((t ^ inv) & 0x8000)
addeq r11,r11,#1
beq 8f @ single_pix_32x
ldrb r12,[r11], #1 @ MD pixel
cmp r3, r12,lsl #26 @ MD has bg pixel?
.if \do_md
movne r12,r12,lsl #1
ldrneh r12,[r9, r12]
strneh r12,[r0], #2 @ *dst++ = palmd[*pmd]
.else
addne r0, r0, #2
.endif
bne 2b @ loop_inner
8: @ single_pix_32x:
and r12,r8, #0x03e0
mov r8, r8, lsl #11
orr r8, r8, r8, lsr #(10+11)
orr r8, r8, r12,lsl #1
bic r8, r8, #0x0020 @ kill prio bit
strh r8, [r0], #2
b 2b @ loop_inner
3: @ loop_innermost:
ldrh r7, [r5], #2 @ 32x pixel
@ -112,7 +148,6 @@
cmpge r7, r8
beq 3b @ loop_innermost
sub r5, r5, #2
add lr, lr, #1
sub lr, r6, lr
sub r6, r6, lr
@ -121,10 +156,10 @@
tst r12, #0x8000 @ !((t ^ inv) & 0x8000)
bne 5f @ draw_md
and r7 ,r8, #0x03e0
and r12,r8, #0x03e0
mov r8, r8, lsl #11
orr r8, r8, r8, lsr #(10+11)
orr r8, r8, r7 ,lsl #1
orr r8, r8, r12,lsl #1
bic r8, r8, #0x0020 @ kill prio bit
add r11,r11,lr
@ -148,35 +183,35 @@
5: @ draw_md:
subs lr, lr, #1
ldrgeb r7, [r11], #1 @ MD pixel
ldrgeb r12,[r11], #1 @ MD pixel
blt 2b @ loop_inner
cmp r3, r7, lsl #26 @ MD has bg pixel?
cmp r3, r12,lsl #26 @ MD has bg pixel?
.if \do_md
mov r7, r7, lsl #1
ldrneh r7 ,[r9, r7]
strneh r7 ,[r0], #2 @ *dst++ = palmd[*pmd]
mov r12,r12,lsl #1
ldrneh r12,[r9, r12]
strneh r12,[r0], #2 @ *dst++ = palmd[*pmd]
.else
addne r0, r0, #2
.endif
bne 5b @ draw_md
and r7 ,r8, #0x03e0
and r12,r8, #0x03e0
mov r8, r8, lsl #11
orr r8, r8, r8, lsr #(10+11)
orr r8, r8, r7 ,lsl #1
orr r8, r8, r12,lsl #1
bic r8, r8, #0x0020 @ kill prio bit
strh r8, [r0], #2 @ *dst++ = bgr2rgb(*p32x++)
6: @ draw_md_32x:
subs lr, lr, #1
ldrgeb r7, [r11], #1 @ MD pixel
ldrgeb r12,[r11], #1 @ MD pixel
blt 2b @ loop_inner
cmp r3, r7, lsl #26 @ MD has bg pixel?
cmp r3, r12,lsl #26 @ MD has bg pixel?
.if \do_md
mov r7, r7, lsl #1
ldrneh r7 ,[r9, r7] @ *dst++ = palmd[*pmd]
moveq r7 ,r8 @ *dst++ = bgr2rgb(*p32x++)
strh r7 ,[r0], #2
mov r12,r12,lsl #1
ldrneh r12,[r9, r12] @ *dst++ = palmd[*pmd]
moveq r12,r8 @ *dst++ = bgr2rgb(*p32x++)
strh r12,[r0], #2
.else
streqh r8, [r0] @ *dst++ = bgr2rgb(*p32x++)
add r0, r0, #2

View File

@ -119,14 +119,14 @@ void NOINLINE p32x_sh2_poll_detect(u32 a, SH2 *sh2, u32 flags, int maxcnt)
// reading 2 consecutive 16bit values is probably a 32bit access. detect this
// by checking address (max 2 bytes away) and cycles (max 2 cycles later).
// no polling if more than 20 cycles have passed since last detect call.
if (a - sh2->poll_addr <= 2 && CYCLES_GE(20, cycles_diff)) {
if (a - sh2->poll_addr <= 2 && CYCLES_GE(10, cycles_diff)) {
if (CYCLES_GT(cycles_diff, 2) && ++sh2->poll_cnt >= maxcnt) {
if (!(sh2->state & flags))
elprintf_sh2(sh2, EL_32X, "state: %02x->%02x",
sh2->state, sh2->state | flags);
sh2->state |= flags;
sh2_end_run(sh2, 1);
sh2_end_run(sh2, 0);
pevt_log_sh2(sh2, EVT_POLL_START);
#ifdef DRC_SH2
// mark this as an address used for polling if SDRAM
@ -324,7 +324,7 @@ static u32 sh2_comm_faker(u32 a)
static int f = 0;
if (a == 0x28 && !p32x_csum_faked) {
p32x_csum_faked = 1;
return *(unsigned short *)(Pico.rom + 0x18e);
return *(u16 *)(Pico.rom + 0x18e);
}
if (f >= sizeof(comm_fakevals) / sizeof(comm_fakevals[0]))
f = 0;
@ -511,7 +511,7 @@ static void p32x_reg_write8(u32 a, u32 d)
case 0x2d:
case 0x2e:
case 0x2f:
if (REG8IN16(r, a) != d) {
if (REG8IN16(r, a) != (u8)d) {
unsigned int cycles = SekCyclesDone();
if (CYCLES_GT(cycles - msh2.m68krcycles_done, 64))
@ -608,7 +608,7 @@ static void p32x_reg_write16(u32 a, u32 d)
case 0x2a/2:
case 0x2c/2:
case 0x2e/2:
if (r[a / 2] != d) {
if (r[a / 2] != (u16)d) {
unsigned int cycles = SekCyclesDone();
if (CYCLES_GT(cycles - msh2.m68krcycles_done, 64))
@ -736,7 +736,7 @@ static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2)
return (r[0] & P32XS_FM) | Pico32x.sh2_regs[0]
| Pico32x.sh2irq_mask[sh2->is_slave];
case 0x04/2: // H count (often as comm too)
p32x_sh2_poll_detect(a, sh2, SH2_STATE_CPOLL, 9);
p32x_sh2_poll_detect(a, sh2, SH2_STATE_CPOLL, 5);
cycles = sh2_cycles_done_m68k(sh2);
sh2s_sync_on_read(sh2, cycles);
return sh2_poll_read(a, Pico32x.sh2_regs[4 / 2], cycles, sh2);
@ -770,7 +770,7 @@ static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2)
case 0x2a/2:
case 0x2c/2:
case 0x2e/2:
p32x_sh2_poll_detect(a, sh2, SH2_STATE_CPOLL, 9);
p32x_sh2_poll_detect(a, sh2, SH2_STATE_CPOLL, 5);
cycles = sh2_cycles_done_m68k(sh2);
sh2s_sync_on_read(sh2, cycles);
return sh2_poll_read(a, r[a / 2], cycles, sh2);
@ -823,7 +823,7 @@ static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2)
return;
case 0x05: // H count
d &= 0xff;
if (Pico32x.sh2_regs[4 / 2] != d) {
if (Pico32x.sh2_regs[4 / 2] != (u8)d) {
unsigned int cycles = sh2_cycles_done_m68k(sh2);
Pico32x.sh2_regs[4 / 2] = d;
p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL, cycles);
@ -848,14 +848,14 @@ static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2)
case 0x2d:
case 0x2e:
case 0x2f:
if (REG8IN16(r, a) != d) {
if (REG8IN16(r, a) != (u8)d) {
unsigned int cycles = sh2_cycles_done_m68k(sh2);
REG8IN16(r, a) = d;
p32x_m68k_poll_event(P32XF_68KCPOLL);
p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL, cycles);
if (p32x_sh2_ready(sh2->other_sh2, cycles+8))
sh2_end_run(sh2, 1);
sh2_end_run(sh2, 0);
sh2_poll_write(a & ~1, r[a / 2], cycles, sh2);
}
return;
@ -941,14 +941,14 @@ static void p32x_sh2reg_write16(u32 a, u32 d, SH2 *sh2)
case 0x2a/2:
case 0x2c/2:
case 0x2e/2:
if (Pico32x.regs[a / 2] != d) {
if (Pico32x.regs[a / 2] != (u16)d) {
unsigned int cycles = sh2_cycles_done_m68k(sh2);
Pico32x.regs[a / 2] = d;
p32x_m68k_poll_event(P32XF_68KCPOLL);
p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL, cycles);
if (p32x_sh2_ready(sh2->other_sh2, cycles+8))
sh2_end_run(sh2, 1);
sh2_end_run(sh2, 0);
sh2_poll_write(a, d, cycles, sh2);
}
return;
@ -1457,7 +1457,7 @@ static u32 REGPARM(2) sh2_read8_cs0(u32 a, SH2 *sh2)
if ((a & 0x3fff0) == 0x4100) {
d = p32x_vdp_read16(a);
p32x_sh2_poll_detect(a, sh2, SH2_STATE_VPOLL, 9);
p32x_sh2_poll_detect(a, sh2, SH2_STATE_VPOLL, 7);
goto out_16to8;
}
@ -1520,7 +1520,7 @@ static u32 REGPARM(2) sh2_read16_cs0(u32 a, SH2 *sh2)
if ((a & 0x3fff0) == 0x4100) {
d = p32x_vdp_read16(a);
p32x_sh2_poll_detect(a, sh2, SH2_STATE_VPOLL, 9);
p32x_sh2_poll_detect(a, sh2, SH2_STATE_VPOLL, 7);
goto out;
}
@ -1583,7 +1583,7 @@ static void sh2_sdram_poll(u32 a, u32 d, SH2 *sh2)
sh2_poll_write(a, d, cycles, sh2);
p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_RPOLL, cycles);
if (p32x_sh2_ready(sh2->other_sh2, cycles+8))
sh2_end_run(sh2, 1);
sh2_end_run(sh2, 0);
DRC_RESTORE_SR(sh2);
}
@ -1690,16 +1690,21 @@ static void REGPARM(3) sh2_write8_da(u32 a, u32 d, SH2 *sh2)
}
#endif
static NOINLINE void REGPARM(3) sh2_write8_sdram_sync(u32 a, u32 d, SH2 *sh2)
{
DRC_SAVE_SR(sh2);
sh2_end_run(sh2, 32);
DRC_RESTORE_SR(sh2);
sh2_write8_sdram(a, d, sh2);
}
static void REGPARM(3) sh2_write8_sdram_wt(u32 a, u32 d, SH2 *sh2)
{
// xmen sync hack..
if (a < 0x26000200) {
DRC_SAVE_SR(sh2);
sh2_end_run(sh2, 32);
DRC_RESTORE_SR(sh2);
}
sh2_write8_sdram(a, d, sh2);
if ((a << 8) >> 17) // ((a & 0x00ffffff) < 0x200)
sh2_write8_sdram(a, d, sh2);
else
sh2_write8_sdram_sync(a, d, sh2);
}
// write16

View File

@ -480,10 +480,12 @@ void REGPARM(3) sh2_peripheral_write32(u32 a, u32 d, SH2 *sh2)
if (!(dmac->dmaor & DMA_DME))
return;
DRC_SAVE_SR(sh2);
if ((dmac->chan[0].chcr & (DMA_TE|DMA_DE)) == DMA_DE)
dmac_trigger(sh2, &dmac->chan[0]);
if ((dmac->chan[1].chcr & (DMA_TE|DMA_DE)) == DMA_DE)
dmac_trigger(sh2, &dmac->chan[1]);
DRC_RESTORE_SR(sh2);
break;
}
@ -538,7 +540,9 @@ static void dreq1_do(SH2 *sh2, struct dma_chan *chan)
if ((chan->dar & ~0xf) != 0x20004030)
elprintf(EL_32XP|EL_ANOMALY, "dreq1: bad dar?: %08x\n", chan->dar);
sh2->state |= SH2_STATE_SLEEP;
dmac_transfer_one(sh2, chan);
sh2->state &= ~SH2_STATE_SLEEP;
if (chan->tcr == 0)
dmac_transfer_complete(sh2, chan);
}

View File

@ -187,7 +187,7 @@ zip_failed:
else if (strcasecmp(ext, "cso") == 0)
{
cso_struct *cso = NULL, *tmp = NULL;
int size;
int i, size;
f = fopen(path, "rb");
if (f == NULL)
goto cso_failed;
@ -229,6 +229,8 @@ zip_failed:
elprintf(EL_STATUS, "cso: premature EOF");
goto cso_failed;
}
for (i = 0; i < size/4; i++)
cso->index[i] = CPU_LE4(cso->index[i]);
// all ok
cso->fpos_in = ftell(f);
@ -280,7 +282,7 @@ cso_failed:
chd->file.file = chd;
chd->file.type = PMT_CHD;
// subchannel data is skipped, remove it from total size
chd->file.size = chd_get_header(cf)->logicalbytes / CD_FRAME_SIZE * CD_MAX_SECTOR_DATA;
chd->file.size = head->logicalbytes / CD_FRAME_SIZE * CD_MAX_SECTOR_DATA;
strncpy(chd->file.ext, ext, sizeof(chd->file.ext) - 1);
return &chd->file;
@ -359,7 +361,7 @@ static size_t _pm_read_chd(void *ptr, size_t bytes, pm_file *stream, int is_audi
if (len > bytes)
len = bytes;
#ifdef CPU_IS_LE
#if CPU_IS_LE
if (is_audio) {
// convert big endian audio samples
u16 *dst = ptr, v;
@ -821,7 +823,7 @@ int PicoCartInsert(unsigned char *rom, unsigned int romsize, const char *carthw_
// This will hang the emu, but will prevent nasty crashes.
// note: 4 bytes are padded to every ROM
if (rom != NULL)
*(unsigned long *)(rom+romsize) = CPU_BE2(0x4EFAFFFE);
*(u32 *)(rom+romsize) = CPU_BE2(0x4EFAFFFE);
Pico.rom=rom;
Pico.romsize=romsize;
@ -1254,11 +1256,11 @@ static void PicoCartDetect(const char *carthw_cfg)
int fill_sram = 0;
memset(&Pico.sv, 0, sizeof(Pico.sv));
if (Pico.rom[0x1B1] == 'R' && Pico.rom[0x1B0] == 'A')
if (Pico.rom[MEM_BE2(0x1B0)] == 'R' && Pico.rom[MEM_BE2(0x1B1)] == 'A')
{
Pico.sv.start = rom_read32(0x1B4) & ~0xff000001; // align
Pico.sv.end = (rom_read32(0x1B8) & ~0xff000000) | 1;
if (Pico.rom[0x1B2] & 0x40)
if (Pico.rom[MEM_BE2(0x1B3)] & 0x40)
// EEPROM
Pico.sv.flags |= SRF_EEPROM;
Pico.sv.flags |= SRF_ENABLED;
@ -1309,7 +1311,7 @@ static void PicoCartDetect(const char *carthw_cfg)
// Unusual region 'code'
if (rom_strcmp(0x1f0, "EUROPE") == 0 || rom_strcmp(0x1f0, "Europe") == 0)
*(int *) (Pico.rom + 0x1f0) = 0x20204520;
*(u32 *) (Pico.rom + 0x1f0) = CPU_LE4(0x20204520);
}
// vim:shiftwidth=2:expandtab

View File

@ -367,7 +367,7 @@ void cdc_dma_update(void)
{
/* update IRQ level */
elprintf(EL_INTS, "cdc DTE irq 5");
SekInterruptS68k(5);
pcd_irq_s68k(5, 1);
}
}
@ -411,7 +411,7 @@ int cdc_decoder_update(uint8 header[4])
{
/* update IRQ level */
elprintf(EL_INTS, "cdc DEC irq 5");
SekInterruptS68k(5);
pcd_irq_s68k(5, 1);
}
}
@ -469,13 +469,13 @@ void cdc_reg_w(unsigned char data)
{
/* update IRQ level */
elprintf(EL_INTS, "cdc pending irq 5");
SekInterruptS68k(5);
pcd_irq_s68k(5, 1);
}
}
else // if (scd.pending & (1 << 5))
{
/* clear pending level 5 interrupts */
SekInterruptClearS68k(5);
pcd_irq_s68k(5, 0);
}
/* abort any data transfer if data output is disabled */
@ -614,7 +614,7 @@ void cdc_reg_w(unsigned char data)
if ((cdc.ifstat | BIT_DECI) || !(cdc.ifctrl & BIT_DECIEN))
{
/* clear pending level 5 interrupt */
SekInterruptClearS68k(5);
pcd_irq_s68k(5, 0);
}
#endif
Pico_mcd->s68k_regs[0x04+1] = 0x08;
@ -774,7 +774,7 @@ unsigned char cdc_reg_r(void)
if ((cdc.ifstat | BIT_DTEI) || !(cdc.ifctrl & BIT_DTEIEN))
{
/* clear pending level 5 interrupt */
SekInterruptClearS68k(5);
pcd_irq_s68k(5, 0);
}
#endif
@ -826,7 +826,7 @@ unsigned short cdc_host_r(void)
{
/* update IRQ level */
elprintf(EL_INTS, "cdc DTE irq 5");
SekInterruptS68k(5);
pcd_irq_s68k(5, 1);
}
}

View File

@ -444,6 +444,9 @@ int cdd_unload(void)
{
int i;
/* stop audio streaming */
Pico_mcd->cdda_stream = NULL;
/* close CD tracks */
if (cdd.toc.tracks[0].fd)
{

View File

@ -421,7 +421,7 @@ void gfx_update(unsigned int cycles)
if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN1) {
elprintf(EL_INTS|EL_CD, "s68k: gfx_cd irq 1");
SekInterruptS68k(1);
pcd_irq_s68k(1, 1);
}
}
else {

@ -1 +1 @@
Subproject commit ff3175ddb040b1a967c665a28868b16bf5aa97dd
Subproject commit 00319cf31f034e4d468a49a60265c7c5b8305b70

View File

@ -124,9 +124,6 @@ static void SekRunS68k(unsigned int to)
if ((cyc_do = SekCycleAimS68k - SekCycleCntS68k) <= 0)
return;
if (SekShouldInterrupt())
Pico_mcd->m.s68k_poll_a = 0;
pprof_start(s68k);
SekCycleCntS68k += cyc_do;
#if defined(EMU_C68K)
@ -177,7 +174,7 @@ static void pcd_cdc_event(unsigned int now)
if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN4) {
elprintf(EL_INTS|EL_CD, "s68k: cdd irq 4");
SekInterruptS68k(4);
pcd_irq_s68k(4, 1);
}
}
@ -188,7 +185,7 @@ static void pcd_int3_timer_event(unsigned int now)
{
if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN3) {
elprintf(EL_INTS|EL_CD, "s68k: timer irq 3");
SekInterruptS68k(3);
pcd_irq_s68k(3, 1);
}
if (Pico_mcd->s68k_regs[0x31] != 0)
@ -280,6 +277,17 @@ static void pcd_run_events(unsigned int until)
oldest, event_time_next);
}
void pcd_irq_s68k(int irq, int state)
{
if (state) {
SekInterruptS68k(irq);
if (SekIsStoppedS68k())
SekSetStopS68k(0);
Pico_mcd->m.s68k_poll_a = 0;
} else
SekInterruptClearS68k(irq);
}
int pcd_sync_s68k(unsigned int m68k_target, int m68k_poll_sync)
{
#define now SekCycleCntS68k
@ -307,7 +315,11 @@ int pcd_sync_s68k(unsigned int m68k_target, int m68k_poll_sync)
if (event_time_next && CYCLES_GT(target, event_time_next))
target = event_time_next;
SekRunS68k(target);
if (SekIsStoppedS68k())
SekCycleCntS68k = SekCycleAimS68k = target;
else
SekRunS68k(target);
if (m68k_poll_sync && Pico_mcd->m.m68k_poll_cnt == 0)
break;
}
@ -324,21 +336,31 @@ static void SekSyncM68k(void);
void pcd_run_cpus_normal(int m68k_cycles)
{
Pico.t.m68c_aim += m68k_cycles;
if (SekShouldInterrupt() || Pico_mcd->m.m68k_poll_cnt < 12)
Pico_mcd->m.m68k_poll_cnt = 0;
else if (Pico_mcd->m.m68k_poll_cnt >= 16) {
int s68k_left = pcd_sync_s68k(Pico.t.m68c_aim, 1);
if (s68k_left <= 0) {
elprintf(EL_CDPOLL, "m68k poll [%02x] x%d @%06x",
Pico_mcd->m.m68k_poll_a, Pico_mcd->m.m68k_poll_cnt, SekPc);
Pico.t.m68c_cnt = Pico.t.m68c_aim;
return;
}
Pico.t.m68c_cnt = Pico.t.m68c_aim - (s68k_left * mcd_s68k_cycle_mult >> 16);
}
while (CYCLES_GT(Pico.t.m68c_aim, Pico.t.m68c_cnt)) {
SekRunM68kOnce();
if (SekShouldInterrupt())
Pico_mcd->m.m68k_poll_cnt = 0;
#ifdef USE_POLL_DETECT
if (Pico_mcd->m.m68k_poll_cnt >= 16) {
int s68k_left;
// main CPU is polling, (wake and) run sub only
if (SekIsStoppedS68k())
SekSetStopS68k(0);
s68k_left = pcd_sync_s68k(Pico.t.m68c_aim, 1);
Pico.t.m68c_cnt = Pico.t.m68c_aim;
if (s68k_left > 0)
Pico.t.m68c_cnt -= ((long long)s68k_left * mcd_s68k_cycle_mult >> 16);
if (SekIsStoppedS68k()) {
// slave has stopped, wake master to avoid lockups
Pico_mcd->m.m68k_poll_cnt = 0;
}
elprintf(EL_CDPOLL, "m68k poll [%02x] x%d @%06x",
Pico_mcd->m.m68k_poll_a, Pico_mcd->m.m68k_poll_cnt, SekPc);
} else
#endif
SekRunM68kOnce();
if (Pico_mcd->m.need_sync) {
Pico_mcd->m.need_sync = 0;
pcd_sync_s68k(Pico.t.m68c_cnt, 0);

View File

@ -68,20 +68,25 @@ static void remap_word_ram(u32 r3);
void m68k_comm_check(u32 a)
{
pcd_sync_s68k(SekCyclesDone(), 0);
u32 cycles = SekCyclesDone();
u32 clkdiff = cycles - Pico_mcd->m.m68k_poll_clk;
pcd_sync_s68k(cycles, 0);
if (a >= 0x0e && !Pico_mcd->m.need_sync) {
// there are cases when slave updates comm and only switches RAM
// over after that (mcd1b), so there must be a resync..
SekEndRun(64);
Pico_mcd->m.need_sync = 1;
}
if (SekNotPolling || a != Pico_mcd->m.m68k_poll_a) {
Pico_mcd->m.m68k_poll_clk = cycles;
if (SekNotPolling || a != Pico_mcd->m.m68k_poll_a || clkdiff > POLL_CYCLES || clkdiff <= 16) {
Pico_mcd->m.m68k_poll_a = a;
Pico_mcd->m.m68k_poll_cnt = 0;
SekNotPolling = 0;
return;
}
Pico_mcd->m.m68k_poll_cnt++;
if(Pico_mcd->m.m68k_poll_cnt == POLL_LIMIT)
SekEndRun(0);
}
#ifndef _ASM_CD_MEMORY_C
@ -144,13 +149,15 @@ void m68k_reg_write8(u32 a, u32 d)
u32 dold;
a &= 0x3f;
Pico_mcd->m.m68k_poll_cnt = 0;
switch (a) {
case 0:
d &= 1;
if (d && (Pico_mcd->s68k_regs[0x33] & PCDS_IEN2)) {
elprintf(EL_INTS, "m68k: s68k irq 2");
pcd_sync_s68k(SekCyclesDone(), 0);
SekInterruptS68k(2);
pcd_irq_s68k(2, 1);
}
return;
case 1:
@ -180,8 +187,7 @@ void m68k_reg_write8(u32 a, u32 d)
return;
case 2:
elprintf(EL_CDREGS, "m68k: prg wp=%02x", d);
Pico_mcd->s68k_regs[2] = d; // really use s68k side register
return;
goto write_comm;
case 3:
dold = Pico_mcd->s68k_regs[3];
elprintf(EL_CDREG3, "m68k_regs w3: %02x @%06x", (u8)d, SekPc);
@ -205,10 +211,10 @@ void m68k_reg_write8(u32 a, u32 d)
goto write_comm;
case 6:
Pico_mcd->bios[0x72 + 1] = d; // simple hint vector changer
Pico_mcd->bios[MEM_BE2(0x72)] = d; // simple hint vector changer
return;
case 7:
Pico_mcd->bios[0x72] = d;
Pico_mcd->bios[MEM_BE2(0x73)] = d;
elprintf(EL_CDREGS, "hint vector set to %04x%04x",
((u16 *)Pico_mcd->bios)[0x70/2], ((u16 *)Pico_mcd->bios)[0x72/2]);
return;
@ -277,7 +283,7 @@ u32 s68k_poll_detect(u32 a, u32 d)
#define READ_FONT_DATA(basemask) \
{ \
unsigned int fnt = *(unsigned int *)(Pico_mcd->s68k_regs + 0x4c); \
unsigned int fnt = CPU_LE4(*(u32 *)(Pico_mcd->s68k_regs + 0x4c)); \
unsigned int col0 = (fnt >> 8) & 0x0f, col1 = (fnt >> 12) & 0x0f; \
if (fnt & (basemask << 0)) d = col1 ; else d = col0; \
if (fnt & (basemask << 1)) d |= col1 << 4; else d |= col0 << 4; \
@ -425,7 +431,7 @@ void s68k_reg_write8(u32 a, u32 d)
// XXX: emulate pending irq instead?
if (Pico_mcd->s68k_regs[0x37] & 4) {
elprintf(EL_INTS, "cdd export irq 4 (unmask)");
SekInterruptS68k(4);
pcd_irq_s68k(4, 1);
}
}
break;
@ -443,7 +449,7 @@ void s68k_reg_write8(u32 a, u32 d)
if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN4) {
elprintf(EL_INTS, "cdd export irq 4");
SekInterruptS68k(4);
pcd_irq_s68k(4, 1);
}
}
return;
@ -494,6 +500,8 @@ void s68k_reg_write16(u32 a, u32 d)
{
u8 *r = Pico_mcd->s68k_regs;
Pico_mcd->m.s68k_poll_cnt = 0;
if ((a & 0x1f0) == 0x20)
goto write_comm;
@ -501,8 +509,8 @@ void s68k_reg_write16(u32 a, u32 d)
case 0x0e:
// special case, 2 byte writes would be handled differently
// TODO: verify
r[0xf] = d;
return;
d = (u8)d | (r[0xe] << 8);
goto write_comm;
case 0x58: // stamp data size
r[0x59] = d & 7;
return;
@ -1094,7 +1102,7 @@ void pcd_state_loaded_mem(void)
Pico_mcd->m.dmna_ret_2m &= 3;
// restore hint vector
*(unsigned short *)(Pico_mcd->bios + 0x72) = Pico_mcd->m.hint_vector;
*(u16 *)(Pico_mcd->bios + 0x72) = Pico_mcd->m.hint_vector;
}
#ifdef EMU_M68K

View File

@ -88,18 +88,18 @@ void pcd_pcm_sync(unsigned int to)
}
addr = ch->addr;
inc = *(unsigned short *)&ch->regs[2];
mul_l = ((int)ch->regs[0] * (ch->regs[1] & 0xf)) >> (5+1);
mul_r = ((int)ch->regs[0] * (ch->regs[1] >> 4)) >> (5+1);
inc = ch->regs[2] + (ch->regs[3]<<8);
mul_l = (int)ch->regs[0] * (ch->regs[1] & 0xf);
mul_r = (int)ch->regs[0] * (ch->regs[1] >> 4);
for (s = 0; s < steps; s++, addr = (addr + inc) & 0x7FFFFFF)
for (s = 0; s < steps; s++, addr = (addr + inc) & 0x07FFFFFF)
{
smp = Pico_mcd->pcm_ram[addr >> PCM_STEP_SHIFT];
// test for loop signal
if (smp == 0xff)
{
addr = *(unsigned short *)&ch->regs[4]; // loop_addr
addr = ch->regs[4] + (ch->regs[5]<<8); // loop_addr
smp = Pico_mcd->pcm_ram[addr];
addr <<= PCM_STEP_SHIFT;
if (smp == 0xff)
@ -109,8 +109,8 @@ void pcd_pcm_sync(unsigned int to)
if (smp & 0x80)
smp = -(smp & 0x7f);
out[s*2 ] += smp * mul_l; // max 128 * 119 = 15232
out[s*2+1] += smp * mul_r;
out[s*2 ] += (smp * mul_l) >> 5; // max 127 * 255 * 15 / 32 = 15180
out[s*2+1] += (smp * mul_r) >> 5;
}
ch->addr = addr;
}
@ -120,7 +120,7 @@ end:
Pico_mcd->pcm_mixpos += steps;
}
void pcd_pcm_update(int *buf32, int length, int stereo)
void pcd_pcm_update(s32 *buf32, int length, int stereo)
{
int step, *pcm;
int p = 0;

View File

@ -81,9 +81,9 @@ cyclone_fetch32:
ldr r1, [r1, r2, lsl #2]
bic r0, r0, #1
movs r1, r1, lsl #1
ldrcch r0, [r1, r0]!
ldrcch r2, [r1, r0]!
ldrcch r1, [r1, #2]
orrcc r0, r1, r0, lsl #16
orrcc r0, r1, r2, lsl #16
bxcc lr
stmfd sp!,{r0,r1,r2,lr}

View File

@ -1,7 +1,6 @@
/*
* rarely used EEPROM code
* (C) notaz, 2006-2008
* (C) kub, 2020
*
* This work is licensed under the terms of MAME license.
* See COPYING file in the top-level directory.
@ -9,181 +8,6 @@
#include "pico_int.h"
// H-counter table for hvcounter reads in 40col mode, starting at HINT
const unsigned char hcounts_40[] = {
0xa5,0xa6,0xa7,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xae,0xaf,0xb0,0xb1,0xb2,
0xb3,0xb4,0xb5,0xb5,0xe4,0xe5,0xe6,0xe7,0xe8,0xe8,0xe9,0xea,0xea,0xeb,0xec,0xed,
0xed,0xee,0xef,0xef,0xf0,0xf1,0xf2,0xf2,0xf3,0xf4,0xf4,0xf5,0xf6,0xf7,0xf7,0xf8,
0xf9,0xfa,0xfb,0xfc,0xfd,0xfd,0xfe,0xff,0x00,0x01,0x02,0x03,0x04,0x04,0x05,0x06,
0x07,0x08,0x09,0x0a,0x0b,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x12,0x13,0x14,
0x15,0x16,0x17,0x18,0x19,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x20,0x21,0x22,
0x23,0x24,0x25,0x26,0x27,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2e,0x2f,0x30,
0x31,0x32,0x33,0x34,0x35,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3c,0x3d,0x3e,
0x3f,0x40,0x41,0x42,0x43,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4a,0x4b,0x4c,
0x4d,0x4e,0x4f,0x50,0x51,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x58,0x59,0x5a,
0x5b,0x5c,0x5d,0x5e,0x5f,0x5f,0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x66,0x67,0x68,
0x69,0x6a,0x6b,0x6c,0x6d,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x74,0x75,0x76,
0x77,0x78,0x79,0x7a,0x7b,0x7b,0x7c,0x7d,0x7e,0x7f,0x80,0x81,0x82,0x82,0x83,0x84,
0x85,0x86,0x87,0x88,0x89,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,0x90,0x90,0x91,0x92,
0x93,0x94,0x95,0x96,0x97,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9e,0x9f,0xa0,
0xa1,0xa2,0xa3,0xa4,0xa5,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xac,0xad,0xae,
};
// H-counter table for hvcounter reads in 32col mode, starting at HINT
const unsigned char hcounts_32[] = {
0x85,0x86,0x86,0x87,0x88,0x88,0x89,0x8a,0x8a,0x8b,0x8c,0x8d,0x8d,0x8e,0x8f,0x8f,
0x90,0x91,0x91,0x92,0x93,0xe9,0xe9,0xea,0xeb,0xeb,0xec,0xed,0xed,0xee,0xef,0xf0,
0xf0,0xf1,0xf2,0xf2,0xf3,0xf4,0xf4,0xf5,0xf6,0xf7,0xf7,0xf8,0xf9,0xf9,0xfa,0xfb,
0xfb,0xfc,0xfd,0xfe,0xfe,0xff,0x00,0x00,0x01,0x02,0x02,0x03,0x04,0x05,0x05,0x06,
0x07,0x07,0x08,0x09,0x09,0x0a,0x0b,0x0c,0x0c,0x0d,0x0e,0x0e,0x0f,0x10,0x10,0x11,
0x12,0x13,0x13,0x14,0x15,0x15,0x16,0x17,0x17,0x18,0x19,0x1a,0x1a,0x1b,0x1c,0x1c,
0x1d,0x1e,0x1e,0x1f,0x20,0x21,0x21,0x22,0x23,0x23,0x24,0x25,0x25,0x26,0x27,0x28,
0x28,0x29,0x2a,0x2a,0x2b,0x2c,0x2c,0x2d,0x2e,0x2f,0x2f,0x30,0x31,0x31,0x32,0x33,
0x33,0x34,0x35,0x36,0x36,0x37,0x38,0x38,0x39,0x3a,0x3a,0x3b,0x3c,0x3d,0x3d,0x3e,
0x3f,0x3f,0x40,0x41,0x41,0x42,0x43,0x44,0x44,0x45,0x46,0x46,0x47,0x48,0x48,0x49,
0x4a,0x4b,0x4b,0x4c,0x4d,0x4d,0x4e,0x4f,0x4f,0x50,0x51,0x52,0x52,0x53,0x54,0x54,
0x55,0x56,0x56,0x57,0x58,0x59,0x59,0x5a,0x5b,0x5b,0x5c,0x5d,0x5d,0x5e,0x5f,0x60,
0x60,0x61,0x62,0x62,0x63,0x64,0x64,0x65,0x66,0x67,0x67,0x68,0x69,0x69,0x6a,0x6b,
0x6b,0x6c,0x6d,0x6e,0x6e,0x6f,0x70,0x70,0x71,0x72,0x72,0x73,0x74,0x75,0x75,0x76,
0x77,0x77,0x78,0x79,0x79,0x7a,0x7b,0x7c,0x7c,0x7d,0x7e,0x7e,0x7f,0x80,0x80,0x81,
0x82,0x83,0x83,0x84,0x85,0x85,0x86,0x87,0x87,0x88,0x89,0x8a,0x8a,0x8b,0x8c,0x8c,
};
// VDP transfer slots for blanked and active display in 32col and 40col mode.
// 1 slot is 488/171 = 2.8538 68k cycles in h32, and 488/210 = 2.3238 in h40
// In blanked display, all slots but 5(h32) / 6(h40) are usable for transfers,
// in active display only 16(h32) / 18(h40) slots can be used.
// NB the cyc2sl tables should cover 2 slot into the next scanline, in case the
// last insn in the old scanline is a 32 bit VDP access. That is currently not
// the case for active display.
// XXX inactive tables by slot#=cycles*maxslot#/488. should be through hv tables
// VDP transfer slots in inactive (blanked) display 32col mode.
// refresh slots: 250, 26, 58, 90, 122 -> 32, 64, 96, 128, 160
const unsigned char vdpcyc2sl_32_bl[] = { // 68k cycles/2 to slot #
// 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30
0, 0, 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10,
10, 11, 12, 12, 13, 14, 14, 15, 16, 17, 17, 18, 19, 19, 20, 21,
21, 22, 23, 23, 24, 25, 25, 26, 27, 27, 28, 29, 29, 30, 31, 31,
32, 33, 34, 34, 35, 36, 36, 37, 38, 38, 39, 40, 40, 41, 42, 42,
43, 44, 44, 45, 46, 46, 47, 48, 48, 49, 50, 51, 51, 52, 53, 53,
54, 55, 55, 56, 57, 57, 58, 59, 59, 60, 61, 61, 62, 63, 63, 64,
65, 65, 66, 67, 68, 68, 69, 70, 70, 71, 72, 72, 73, 74, 74, 75,
76, 76, 77, 78, 78, 79, 80, 80, 81, 82, 83, 83, 84, 85, 85, 86,
87, 87, 88, 89, 89, 90, 91, 91, 92, 93, 93, 94, 95, 95, 96, 97,
97, 98, 99,100,100,101,102,102,103,104,104,105,106,106,107,108,
108,109,110,110,111,112,112,113,114,114,115,116,117,117,118,119,
119,120,121,121,122,123,123,124,125,125,126,127,127,128,129,129,
130,131,131,132,133,134,134,135,136,136,137,138,138,139,140,140,
141,142,142,143,144,144,145,146,146,147,148,148,149,150,151,151,
152,153,153,154,155,155,156,157,157,158,159,159,160,161,161,162,
163,163,164,165,166,166,167,168,168,169,170,170,171,172,172,173,
};
// VDP transfer slots in inactive (blanked) display 40col mode.
// refresh slots: 250, 26, 58, 90, 122, 154 -> 40, 72, 104, 136, 168, 200
const unsigned char vdpcyc2sl_40_bl[] = { // 68k cycles/2 to slot #
// 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30
0, 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10, 10, 11, 12,
13, 14, 15, 15, 16, 17, 18, 19, 20, 20, 21, 22, 23, 24, 25, 25,
26, 27, 28, 29, 30, 30, 31, 32, 33, 34, 35, 35, 36, 37, 38, 39,
40, 40, 41, 42, 43, 44, 45, 45, 46, 47, 48, 49, 50, 51, 51, 52,
53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 61, 62, 63, 64, 65, 66,
66, 67, 68, 69, 70, 71, 71, 72, 73, 74, 75, 76, 76, 77, 78, 79,
80, 81, 81, 82, 83, 84, 85, 86, 86, 87, 88, 89, 90, 91, 91, 92,
93, 94, 95, 96, 96, 97, 98, 99,100,101,102,102,103,104,105,106,
107,107,108,109,110,111,112,112,113,114,115,116,117,117,118,119,
120,121,122,122,123,124,125,126,127,127,128,129,130,131,132,132,
133,134,135,136,137,137,138,139,140,141,142,142,143,144,145,146,
147,147,148,149,150,151,152,153,153,154,155,156,157,158,158,159,
160,161,162,163,163,164,165,166,167,168,168,169,170,171,172,173,
173,174,175,176,177,178,178,179,180,181,182,183,183,184,185,186,
187,188,188,189,190,191,192,193,193,194,195,196,197,198,198,199,
200,201,202,203,204,204,205,206,207,208,209,209,210,211,212,213,
};
// VDP transfer slots in active display 32col mode. Transfer slots (Hint=0):
// 11,25,40,48,56,72,80,88,104,112,120,136,144,152,167,168
const unsigned char vdpcyc2sl_32[] = { // 68k cycles/2 to slot #
// 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
};
// VDP transfer slots in active display 40col mode. Transfer slots (Hint=0):
// 21,47,55,63,79,87,95,111,119,127,143,151,159,175,183,191,206,207
const unsigned char vdpcyc2sl_40[] = { // 68k cycles/2 to slot #
// 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 32
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64
1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 96
3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, // 128
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, // 160
5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, // 192
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 224
7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, // 256
9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, // 288
10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, // 320
12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, // 352
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, // 384
14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, // 416
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, // 448
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, // 480
};
// NB the sl2cyc tables must cover all slots present in the cyc2sl tables.
// XXX inactive tables by cyc=slot#*488/maxslot#. should be through hv tables
const unsigned short vdpsl2cyc_32_bl[] = { // slot # to 68k cycles/2
0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 15, 17, 18, 20, 21, 23,
24, 25, 27, 28, 30, 31, 33, 34, 36, 37, 39, 40, 42, 43, 45, 46,
48, 49, 50, 52, 53, 55, 56, 58, 59, 61, 62, 64, 65, 67, 68, 70,
71, 73, 74, 75, 77, 78, 80, 81, 83, 84, 86, 87, 89, 90, 92, 93,
95, 96, 98, 99,100,102,103,105,106,108,109,111,112,114,115,117,
118,120,121,122,124,125,127,128,130,131,133,134,136,137,139,140,
142,143,145,146,147,149,150,152,153,155,156,158,159,161,162,164,
165,167,168,170,171,172,174,175,177,178,180,181,183,184,186,187,
189,190,192,193,195,196,197,199,200,202,203,205,206,208,209,211,
212,214,215,217,218,220,221,222,224,225,227,228,230,231,233,234,
236,237,239,240,242,243,244,246,247,249,250,252,253,255,256
};
const unsigned short vdpsl2cyc_40_bl[] = { // slot # to 68k cycles/2
0, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18,
20, 21, 22, 23, 24, 26, 27, 28, 29, 30, 32, 33, 34, 35, 36, 38,
39, 40, 41, 42, 44, 45, 46, 47, 48, 50, 51, 52, 53, 54, 56, 57,
58, 59, 60, 61, 63, 64, 65, 66, 67, 69, 70, 71, 72, 73, 75, 76,
77, 78, 79, 81, 82, 83, 84, 85, 87, 88, 89, 90, 91, 93, 94, 95,
96, 97, 99,100,101,102,103,105,106,107,108,109,111,112,113,114,
115,117,118,119,120,121,122,124,125,126,127,128,130,131,132,133,
134,136,137,138,139,140,142,143,144,145,146,148,149,150,151,152,
154,155,156,157,158,160,161,162,163,164,166,167,168,169,170,172,
173,174,175,176,178,179,180,181,182,183,185,186,187,188,189,191,
192,193,194,195,197,198,199,200,201,203,204,205,206,207,209,210,
211,212,213,215,216,217,218,219,221,222,223,224,225,227,228,229,
230,231,233,234,235,236,237,239,240,241,242,243,244,246,247,248,
249,250,252,253,254,255,257
};
const unsigned short vdpsl2cyc_32[] = { // slot # to 68k cycles/2
0, 16, 36, 56, 67, 79,102,113,125,148,159,171,194,205,217,239,
240,260,280
};
const unsigned short vdpsl2cyc_40[] = { // slot # to 68k cycles/2
0, 24, 55, 64, 73, 92,101,110,129,138,147,166,175,184,203,212,
221,239,240,268,299
};
#ifndef _ASM_MISC_C
PICO_INTERNAL_ASM void memcpy16bswap(unsigned short *dest, void *src, int count)

View File

@ -446,11 +446,11 @@ void PicoPatchPrepare(void)
addr=PicoPatches[i].addr;
addr &= ~1;
if (addr < Pico.romsize)
PicoPatches[i].data_old = *(unsigned short *)(Pico.rom + addr);
PicoPatches[i].data_old = *(u16 *)(Pico.rom + addr);
else
{
if(!(PicoIn.AHW & PAHW_SMS))
PicoPatches[i].data_old = (unsigned short) m68k_read16(addr);
PicoPatches[i].data_old = (u16) m68k_read16(addr);
else
;// wrong: PicoPatches[i].data_old = (unsigned char) PicoRead8_z80(addr);
}
@ -473,7 +473,7 @@ void PicoPatchApply(void)
if (PicoPatches[i].active)
{
if (!(PicoIn.AHW & PAHW_SMS))
*(unsigned short *)(Pico.rom + addr) = PicoPatches[i].data;
*(u16 *)(Pico.rom + addr) = PicoPatches[i].data;
else if (!PicoPatches[i].comp || PicoPatches[i].comp == *(char *)(Pico.rom + addr))
*(char *)(Pico.rom + addr) = (char) PicoPatches[i].data;
}
@ -485,13 +485,13 @@ void PicoPatchApply(void)
if (u == i)
{
if (!(PicoIn.AHW & PAHW_SMS))
*(unsigned short *)(Pico.rom + addr) = PicoPatches[i].data_old;
*(u16 *)(Pico.rom + addr) = PicoPatches[i].data_old;
else
*(char *)(Pico.rom + addr) = (char) PicoPatches[i].data_old;
}
}
// fprintf(stderr, "patched %i: %06x:%04x\n", PicoPatches[i].active, addr,
// *(unsigned short *)(Pico.rom + addr));
// *(u16 *)(Pico.rom + addr));
}
else
{

View File

@ -40,6 +40,7 @@ void PicoInit(void)
Pico32xInit();
PsndInit();
PicoVideoInit();
PicoDrawInit();
PicoDraw2Init();
}

View File

@ -67,7 +67,8 @@ static void do_hint(struct PicoVideo *pv)
pv->pending_ints |= 0x10;
if (pv->reg[0] & 0x10) {
elprintf(EL_INTS, "hint: @ %06x [%u]", SekPc, SekCyclesDone());
SekInterrupt(4);
if (SekIrqLevel < 4)
SekInterrupt(4);
}
}

View File

@ -102,16 +102,16 @@ extern m68ki_cpu_core PicoCpuMM68k, PicoCpuMS68k;
#define SekSr m68k_get_reg(&PicoCpuMM68k, M68K_REG_SR)
#define SekSrS68k m68k_get_reg(&PicoCpuMS68k, M68K_REG_SR)
#define SekSetStop(x) { \
if(x) { SET_CYCLES(0); PicoCpuMM68k.stopped=STOP_LEVEL_STOP; } \
if(x) { PicoCpuMM68k.cyc_remaining_cycles = 0; PicoCpuMM68k.stopped=STOP_LEVEL_STOP; } \
else PicoCpuMM68k.stopped=0; \
}
#define SekSetStopS68k(x) { \
if(x) { SET_CYCLES(0); PicoCpuMS68k.stopped=STOP_LEVEL_STOP; } \
if(x) { PicoCpuMS68k.cyc_remaining_cycles = 0; PicoCpuMS68k.stopped=STOP_LEVEL_STOP; } \
else PicoCpuMS68k.stopped=0; \
}
#define SekIsStoppedM68k() (PicoCpuMM68k.stopped==STOP_LEVEL_STOP)
#define SekIsStoppedS68k() (PicoCpuMS68k.stopped==STOP_LEVEL_STOP)
#define SekShouldInterrupt() (CPU_INT_LEVEL > FLAG_INT_MASK)
#define SekShouldInterrupt() (PicoCpuMM68k.int_level > PicoCpuMM68k.int_mask)
#define SekNotPolling PicoCpuMM68k.not_polling
#define SekNotPollingS68k PicoCpuMS68k.not_polling
@ -491,7 +491,8 @@ struct mcd_misc
unsigned char dmna_ret_2m;
unsigned char need_sync;
unsigned char pad3;
int pad4[9];
unsigned int m68k_poll_clk;
int pad4[8];
};
typedef struct
@ -773,6 +774,7 @@ void pcd_event_schedule(unsigned int now, enum pcd_event event, int after);
void pcd_event_schedule_s68k(enum pcd_event event, int after);
void pcd_prepare_frame(void);
unsigned int pcd_cycles_m68k_to_s68k(unsigned int c);
void pcd_irq_s68k(int irq, int state);
int pcd_sync_s68k(unsigned int m68k_target, int m68k_poll_sync);
void pcd_run_cpus(int m68k_cycles);
void pcd_soft_reset(void);
@ -780,7 +782,7 @@ void pcd_state_loaded(void);
// cd/pcm.c
void pcd_pcm_sync(unsigned int to);
void pcd_pcm_update(int *buffer, int length, int stereo);
void pcd_pcm_update(s32 *buffer, int length, int stereo);
void pcd_pcm_write(unsigned int a, unsigned int d);
unsigned int pcd_pcm_read(unsigned int a);
@ -876,6 +878,7 @@ void PicoVideoFIFOSync(int cycles);
int PicoVideoFIFOHint(void);
void PicoVideoFIFOMode(int active, int h40);
int PicoVideoFIFOWrite(int count, int byte_p, unsigned sr_mask, unsigned sr_flags);
void PicoVideoInit(void);
void PicoVideoSave(void);
void PicoVideoLoad(void);
void PicoVideoCacheSAT(void);

View File

@ -57,7 +57,7 @@
#define MEM_LE2(a) (a)
#define MEM_LE4(a) (a)
// swapping
#define CPU_BE2(v) ((u32)((u64)(v)<<16)|((v)>>16))
#define CPU_BE2(v) ((u32)((u64)(v)<<16)|((u32)(v)>>16))
#define CPU_BE4(v) (((u32)(v)>>24)|(((v)>>8)&0x00ff00)| \
(((v)<<8)&0xff0000)|(u32)((v)<<24))
#define CPU_LE2(v) (v) // swap of 2*u16 in u32
@ -71,7 +71,7 @@
// swapping
#define CPU_BE2(v) (v)
#define CPU_BE4(v) (v)
#define CPU_LE2(v) ((u32)((u64)(v)<<16)|((v)>>16))
#define CPU_LE2(v) ((u32)((u64)(v)<<16)|((u32)(v)>>16))
#define CPU_LE4(v) (((u32)(v)>>24)|(((v)>>8)&0x00ff00)| \
(((v)<<8)&0xff0000)|(u32)((v)<<24))
#endif

View File

@ -192,14 +192,14 @@ PICO_INTERNAL void SekSetRealTAS(int use_real)
// XXX: rename
PICO_INTERNAL void SekPackCpu(unsigned char *cpu, int is_sub)
{
unsigned int pc=0;
u32 pc=0;
#if defined(EMU_C68K)
struct Cyclone *context = is_sub ? &PicoCpuCS68k : &PicoCpuCM68k;
memcpy(cpu,context->d,0x40);
pc=context->pc-context->membase;
*(unsigned int *)(cpu+0x44)=CycloneGetSr(context);
*(unsigned int *)(cpu+0x48)=context->osp;
*(u32 *)(cpu+0x44)=CycloneGetSr(context);
*(u32 *)(cpu+0x48)=context->osp;
cpu[0x4c] = context->irq;
cpu[0x4d] = context->state_flags & 1;
#elif defined(EMU_M68K)
@ -207,8 +207,8 @@ PICO_INTERNAL void SekPackCpu(unsigned char *cpu, int is_sub)
m68k_set_context(is_sub ? &PicoCpuMS68k : &PicoCpuMM68k);
memcpy(cpu,m68ki_cpu_p->dar,0x40);
pc=m68ki_cpu_p->pc;
*(unsigned int *)(cpu+0x44)=m68k_get_reg(NULL, M68K_REG_SR);
*(unsigned int *)(cpu+0x48)=m68ki_cpu_p->sp[m68ki_cpu_p->s_flag^SFLAG_SET];
*(u32 *)(cpu+0x44)=m68k_get_reg(NULL, M68K_REG_SR);
*(u32 *)(cpu+0x48)=m68ki_cpu_p->sp[m68ki_cpu_p->s_flag^SFLAG_SET];
cpu[0x4c] = CPU_INT_LEVEL>>8;
cpu[0x4d] = CPU_STOPPED;
m68k_set_context(oldcontext);
@ -216,14 +216,14 @@ PICO_INTERNAL void SekPackCpu(unsigned char *cpu, int is_sub)
M68K_CONTEXT *context = is_sub ? &PicoCpuFS68k : &PicoCpuFM68k;
memcpy(cpu,context->dreg,0x40);
pc=context->pc;
*(unsigned int *)(cpu+0x44)=context->sr;
*(unsigned int *)(cpu+0x48)=context->asp;
*(u32 *)(cpu+0x44)=context->sr;
*(u32 *)(cpu+0x48)=context->asp;
cpu[0x4c] = context->interrupts[0];
cpu[0x4d] = (context->execinfo & FM68K_HALTED) ? 1 : 0;
#endif
*(unsigned int *)(cpu+0x40) = pc;
*(unsigned int *)(cpu+0x50) =
*(u32 *)(cpu+0x40) = pc;
*(u32 *)(cpu+0x50) =
is_sub ? SekCycleCntS68k : Pico.t.m68c_cnt;
}
@ -231,11 +231,11 @@ PICO_INTERNAL void SekUnpackCpu(const unsigned char *cpu, int is_sub)
{
#if defined(EMU_C68K)
struct Cyclone *context = is_sub ? &PicoCpuCS68k : &PicoCpuCM68k;
CycloneSetSr(context, *(unsigned int *)(cpu+0x44));
context->osp=*(unsigned int *)(cpu+0x48);
CycloneSetSr(context, *(u32 *)(cpu+0x44));
context->osp=*(u32 *)(cpu+0x48);
memcpy(context->d,cpu,0x40);
context->membase = 0;
context->pc = *(unsigned int *)(cpu+0x40);
context->pc = *(u32 *)(cpu+0x40);
CycloneUnpack(context, NULL); // rebase PC
context->irq = cpu[0x4c];
context->state_flags = 0;
@ -244,27 +244,27 @@ PICO_INTERNAL void SekUnpackCpu(const unsigned char *cpu, int is_sub)
#elif defined(EMU_M68K)
void *oldcontext = m68ki_cpu_p;
m68k_set_context(is_sub ? &PicoCpuMS68k : &PicoCpuMM68k);
m68k_set_reg(M68K_REG_SR, *(unsigned int *)(cpu+0x44));
m68k_set_reg(M68K_REG_SR, *(u32 *)(cpu+0x44));
memcpy(m68ki_cpu_p->dar,cpu,0x40);
m68ki_cpu_p->pc=*(unsigned int *)(cpu+0x40);
m68ki_cpu_p->sp[m68ki_cpu_p->s_flag^SFLAG_SET]=*(unsigned int *)(cpu+0x48);
m68ki_cpu_p->pc=*(u32 *)(cpu+0x40);
m68ki_cpu_p->sp[m68ki_cpu_p->s_flag^SFLAG_SET]=*(u32 *)(cpu+0x48);
CPU_INT_LEVEL = cpu[0x4c] << 8;
CPU_STOPPED = cpu[0x4d];
m68k_set_context(oldcontext);
#elif defined(EMU_F68K)
M68K_CONTEXT *context = is_sub ? &PicoCpuFS68k : &PicoCpuFM68k;
memcpy(context->dreg,cpu,0x40);
context->pc =*(unsigned int *)(cpu+0x40);
context->sr =*(unsigned int *)(cpu+0x44);
context->asp=*(unsigned int *)(cpu+0x48);
context->pc =*(u32 *)(cpu+0x40);
context->sr =*(u32 *)(cpu+0x44);
context->asp=*(u32 *)(cpu+0x48);
context->interrupts[0] = cpu[0x4c];
context->execinfo &= ~FM68K_HALTED;
if (cpu[0x4d]&1) context->execinfo |= FM68K_HALTED;
#endif
if (is_sub)
SekCycleCntS68k = *(unsigned int *)(cpu+0x50);
SekCycleCntS68k = *(u32 *)(cpu+0x50);
else
Pico.t.m68c_cnt = *(unsigned int *)(cpu+0x50);
Pico.t.m68c_cnt = *(u32 *)(cpu+0x50);
}
@ -398,7 +398,7 @@ int SekRegisterIdlePatch(unsigned int pc, int oldop, int newop, void *ctx)
// XXX: probably shouldn't patch RAM too
v = m68k_read16_map[pc >> M68K_MEM_SHIFT];
if (!(v & 0x80000000))
if (~v & ~((uptr)-1LL >> 1)) // MSB clear?
target = (u16 *)((v << 1) + pc);
else {
if (++idledet_bads > 128)

View File

@ -156,7 +156,7 @@ m16_32_s2_no_unal2:
@ limit
@ reg=int_sample, r12=1, r8=tmp, kills flags
.macro Limit reg
sub \reg, \reg, \reg, asr #2 @ reduce audio lvl some to avoid clipping
@ sub \reg, \reg, \reg, asr #2 @ reduce audio lvl to avoid clipping
add r8, r12, \reg, asr #15
bics r8, r8, #1 @ in non-overflow conditions r8 is 0 or 1
movne \reg, #0x8000
@ -166,7 +166,7 @@ m16_32_s2_no_unal2:
@ limit and shift up by 16
@ reg=int_sample, r12=1, r8=tmp, kills flags
.macro Limitsh reg
sub \reg, \reg, \reg, asr #2 @ reduce audio lvl some to avoid clipping
@ sub \reg, \reg, \reg, asr #2 @ reduce audio lvl to avoid clipping
add r8, r12,\reg, asr #15
bics r8, r8, #1 @ in non-overflow conditions r8 is 0 or 1
moveq \reg, \reg, lsl #16

View File

@ -17,10 +17,10 @@
void (*PsndMix_32_to_16l)(short *dest, int *src, int count) = mix_32_to_16l_stereo;
// master int buffer to mix to
static int PsndBuffer[2*(44100+100)/50];
static s32 PsndBuffer[2*(44100+100)/50];
// cdda output buffer
short cdda_out_buffer[2*1152];
s16 cdda_out_buffer[2*1152];
// sn76496
extern int *sn76496_regs;
@ -236,7 +236,7 @@ PICO_INTERNAL void PsndDoFM(int cyc_to)
// Q16, number of samples since last call
len = (cyc_to * Pico.snd.clkl_mult) - Pico.snd.fm_pos;
// don't do this too often (about once every canline)
// don't do this too often (about once every scanline)
if (len >> 16 <= PicoIn.sndRate >> 10)
return;

View File

@ -2185,6 +2185,7 @@ int YM2612PicoStateLoad2(int *tat, int *tbt)
blk = ym2612.CH[c].block_fnum >> 11;
ym2612.CH[c].kcode= (blk<<2) | opn_fktable[fn >> 7];
ym2612.CH[c].fc = fn_table[fn*2]>>(7-blk);
refresh_fc_eg_chan( &ym2612.CH[c] );
}
// chans 4,5,6
ptr = &ym2612.REGS[0x1b8];
@ -2205,6 +2206,7 @@ int YM2612PicoStateLoad2(int *tat, int *tbt)
blk = ym2612.CH[c].block_fnum >> 11;
ym2612.CH[c].kcode= (blk<<2) | opn_fktable[fn >> 7];
ym2612.CH[c].fc = fn_table[fn*2]>>(7-blk);
refresh_fc_eg_chan( &ym2612.CH[c] );
}
for (c = 0; c < 3; c++)
{

View File

@ -2,7 +2,7 @@
* PicoDrive
* (c) Copyright Dave, 2004
* (C) notaz, 2006-2009
* (C) kub, 2020
* (C) kub, 2020,2021
*
* This work is licensed under the terms of MAME license.
* See COPYING file in the top-level directory.
@ -12,11 +12,131 @@
#define NEED_DMA_SOURCE
#include "memory.h"
extern const unsigned char hcounts_32[], hcounts_40[];
extern const unsigned char vdpcyc2sl_32_bl[], vdpcyc2sl_40_bl[];
extern const unsigned char vdpcyc2sl_32[], vdpcyc2sl_40[];
extern const unsigned short vdpsl2cyc_32_bl[], vdpsl2cyc_40_bl[];
extern const unsigned short vdpsl2cyc_32[], vdpsl2cyc_40[];
enum { clkdiv = 2 }; // CPU clock granularity: one of 1,2,4,8
// VDP Slot timing, taken from http://gendev.spritesmind.net/
// forum/viewtopic.php?f=22&t=851&sid=d5701a71396ee7f700c74fb7cd85cb09
// Thank you very much for the great work, Nemesis!
// Slot clock is sysclock/20 for h32 and sysclock/16 for h40.
// One scanline is 63.7us/63.5us (h32/h40) long which is 488.6/487.4 68k cycles.
// Assume 488 for everything.
// 1 slot is 488/171 = 2.8538 68k cycles in h32, and 488/210 = 2.3238 in h40.
enum { slcpu = 488 };
// VDP has a slot counter running from 0x00 to 0xff every scanline, but it has
// a gap depending on the video mode. The slot in which a horizontal interrupt
// is generated also depends on the video mode.
enum { hint32 = 0x85, gapstart32 = 0x94, gapend32 = 0xe9};
enum { hint40 = 0xa5, gapstart40 = 0xb7, gapend40 = 0xe5};
// The horizontal sync period (HBLANK) is 30/37 slots (h32/h40):
// h32: 4 slots front porch (1.49us), 13 HSYNC (4.84us), 13 back porch (4.84us)
// h40: 5 slots front porch (1.49us), 16 HSYNC (4.77us), 16 back porch (4.77us)
// HBLANK starts in slot 0x93/0xb4, according to Nemesis' measurements.
enum { hboff32 = 0x93-hint32, hblen32 = 0xf8-(gapend32-gapstart32)-hint32};//30
enum { hboff40 = 0xb4-hint40, hblen40 = 0xf8-(gapend40-gapstart40)-hint40};//37
// number of slots in a scanline
#define slots32 (0x100-(gapend32-gapstart32)) // 171
#define slots40 (0x100-(gapend40-gapstart40)) // 210
// In blanked display, all slots but the refresh slots are usable for transfers,
// in active display only 16(h32) / 18(h40) slots can be used.
// dma and refresh slots for active display, 16 for H32
static u8 dmaslots32[] =
{ 145,243, 2,10,18, 34,42,50, 66,74,82, 98,106,114, 129,130 };
static u8 refslots32[] =
{ 250, 26, 58, 90, 122 };
// dma and refresh slots for active display, 18 for H40
static u8 dmaslots40[] =
{ 232, 2,10,18, 34,42,50, 66,74,82, 98,106,114, 130,138,146, 161,162 };
static u8 refslots40[] =
{ 250, 26, 58, 90, 122, 154 };
// table sizes
enum { cycsz = slcpu/clkdiv };
enum { sl32blsz=slots32-sizeof(refslots32)+1, sl32acsz=sizeof(dmaslots32)+1 };
enum { sl40blsz=slots40-sizeof(refslots40)+1, sl40acsz=sizeof(dmaslots40)+1 };
// Tables must be considerably larger than one scanline, since 68k emulation
// isn't stopping in the middle of an operation. If the last op is a 32 bit
// VDP access 2 slots may need to be taken from the next scanline, which can be
// more than 100 CPU cycles. For safety just cover 2 scanlines.
// table for hvcounter mapping. check: Sonic 3D Blast bonus, Cannon Fodder,
// Chase HQ II, 3 Ninjas kick back, Road Rash 3, Skitchin', Wheel of Fortune
static u8 hcounts_32[2*cycsz], hcounts_40[2*cycsz];
// tables mapping cycles to slots
static u16 vdpcyc2sl_32_bl[2*cycsz],vdpcyc2sl_40_bl[2*cycsz];
static u16 vdpcyc2sl_32_ac[2*cycsz],vdpcyc2sl_40_ac[2*cycsz];
// tables mapping slots to cycles
// NB the sl2cyc tables must cover all slots present in the cyc2sl tables.
static u16 vdpsl2cyc_32_bl[2*sl32blsz],vdpsl2cyc_40_bl[2*sl40blsz];
static u16 vdpsl2cyc_32_ac[2*sl32acsz],vdpsl2cyc_40_ac[2*sl40acsz];
// calculate timing tables for one mode (H32 or H40)
// NB tables aligned to HINT, since the main loop uses HINT as synchronization
#define INITTABLES(s) { \
float factor = (float)slcpu/slots##s; \
int ax, bx, rx, ac, bc; \
int i, n; \
\
/* calculate internal VDP slot numbers */ \
for (i = 0; i < cycsz; i++) { \
n = hint##s + i*clkdiv/factor; \
if (n >= gapstart##s) n += gapend##s-gapstart##s; \
hcounts_##s[i] = n % 256; \
} \
\
ax = bx = ac = bc = rx = 0; \
for (i = 0; i < cycsz; i++) { \
n = hcounts_##s[i]; \
if (i == 0 || n != hcounts_##s[i-1]) { \
/* fill slt <=> cycle tables, active scanline */ \
if (ax < ARRAY_SIZE(dmaslots##s) && dmaslots##s[ax] == n) { \
vdpsl2cyc_##s##_ac[++ax]=i; \
while (ac < i) vdpcyc2sl_##s##_ac[ac++] = ax-1; \
} \
/* fill slt <=> cycle tables, scanline off */ \
if (rx >= ARRAY_SIZE(refslots##s) || refslots##s[rx] != n) { \
vdpsl2cyc_##s##_bl[++bx]=i; \
while (bc < i) vdpcyc2sl_##s##_bl[bc++] = bx-1; \
} else \
++rx; \
} \
} \
/* fill up cycle to slot mappings for last slot */ \
while (ac < cycsz) \
vdpcyc2sl_##s##_ac[ac] = ARRAY_SIZE(dmaslots##s), ac++; \
while (bc < cycsz) \
vdpcyc2sl_##s##_bl[bc] = slots##s-ARRAY_SIZE(refslots##s), bc++; \
\
/* extend tables for 2nd scanline */ \
memcpy(hcounts_##s+cycsz, hcounts_##s, ARRAY_SIZE(hcounts_##s)-cycsz);\
i = ARRAY_SIZE(dmaslots##s); \
while (ac < ARRAY_SIZE(vdpcyc2sl_##s##_ac)) \
vdpcyc2sl_##s##_ac[ac] = vdpcyc2sl_##s##_ac[ac-cycsz]+i, ac++; \
while (ax < ARRAY_SIZE(vdpsl2cyc_##s##_ac)-1) ax++, \
vdpsl2cyc_##s##_ac[ax] = vdpsl2cyc_##s##_ac[ax-i]+cycsz; \
i = slots##s - ARRAY_SIZE(refslots##s); \
while (bc < ARRAY_SIZE(vdpcyc2sl_##s##_bl)) \
vdpcyc2sl_##s##_bl[bc] = vdpcyc2sl_##s##_bl[bc-cycsz]+i, bc++; \
while (bx < ARRAY_SIZE(vdpsl2cyc_##s##_bl)-1) bx++, \
vdpsl2cyc_##s##_bl[bx] = vdpsl2cyc_##s##_bl[bx-i]+cycsz; \
}
// initialize VDP timing tables
void PicoVideoInit(void)
{
INITTABLES(32);
INITTABLES(40);
}
static int blankline; // display disabled for this line
@ -69,16 +189,17 @@ static struct VdpFIFO { // XXX this must go into save file!
unsigned short fifo_slot; // last executed slot in current scanline
unsigned short fifo_maxslot;// #slots in scanline
const unsigned char *fifo_cyc2sl;
const unsigned short *fifo_cyc2sl;
const unsigned short *fifo_sl2cyc;
} VdpFIFO;
enum { FQ_BYTE = 1, FQ_BGDMA = 2, FQ_FGDMA = 4 }; // queue flags, NB: BYTE = 1!
// NB must limit cyc2sl to table size in case 68k overdraws its aim. That can
// happen if the last insn is a blocking acess to VDP, or for exceptions (e.g.irq)
#define Cyc2Sl(vf,lc) ((lc) < 256*2 ? vf->fifo_cyc2sl[(lc)>>1] : vf->fifo_cyc2sl[255])
#define Sl2Cyc(vf,sl) (vf->fifo_sl2cyc[sl]*2)
// NB should limit cyc2sl to table size in case 68k overdraws its aim. That can
// happen if the last op is a blocking acess to VDP, or for exceptions (e.g.irq)
#define Cyc2Sl(vf,lc) (vf->fifo_cyc2sl[(lc)/clkdiv])
#define Sl2Cyc(vf,sl) (vf->fifo_sl2cyc[sl]*clkdiv)
// do the FIFO math
static __inline int AdvanceFIFOEntry(struct VdpFIFO *vf, struct PicoVideo *pv, int slots)
@ -90,7 +211,8 @@ static __inline int AdvanceFIFOEntry(struct VdpFIFO *vf, struct PicoVideo *pv, i
if (l > cnt)
l = cnt;
if (!(vf->fifo_queue[vf->fifo_qx] & FQ_BGDMA))
if ((vf->fifo_total -= ((cnt & b) + l) >> b) < 0) vf->fifo_total = 0;
vf->fifo_total -= ((cnt & b) + l) >> b;
if (vf->fifo_total < 0) vf->fifo_total = 0;
cnt -= l;
// if entry has been processed...
@ -263,7 +385,7 @@ int PicoVideoFIFOWrite(int count, int flags, unsigned sr_mask,unsigned sr_flags)
// update FIFO state if it was empty
if (!(pv->status & PVS_FIFORUN)) {
vf->fifo_slot = Cyc2Sl(vf, lc+9); // FIFO latency ~3 vdp slots
vf->fifo_slot = Cyc2Sl(vf, lc+7); // FIFO latency ~3 vdp slots
pv->status |= PVS_FIFORUN;
pv->fifo_cnt = count << (flags & FQ_BYTE);
}
@ -300,10 +422,10 @@ int PicoVideoFIFOHint(void)
// switch FIFO mode between active/inactive display
void PicoVideoFIFOMode(int active, int h40)
{
static const unsigned char *vdpcyc2sl[2][2] =
{ {vdpcyc2sl_32_bl, vdpcyc2sl_40_bl} , {vdpcyc2sl_32, vdpcyc2sl_40} };
static const unsigned short *vdpcyc2sl[2][2] =
{ {vdpcyc2sl_32_bl, vdpcyc2sl_40_bl},{vdpcyc2sl_32_ac, vdpcyc2sl_40_ac} };
static const unsigned short *vdpsl2cyc[2][2] =
{ {vdpsl2cyc_32_bl, vdpsl2cyc_40_bl} , {vdpsl2cyc_32, vdpsl2cyc_40} };
{ {vdpsl2cyc_32_bl, vdpsl2cyc_40_bl},{vdpsl2cyc_32_ac, vdpsl2cyc_40_ac} };
struct VdpFIFO *vf = &VdpFIFO;
struct PicoVideo *pv = &Pico.video;
@ -316,11 +438,10 @@ void PicoVideoFIFOMode(int active, int h40)
vf->fifo_cyc2sl = vdpcyc2sl[active][h40];
vf->fifo_sl2cyc = vdpsl2cyc[active][h40];
// recalculate FIFO slot for new mode
vf->fifo_slot = Cyc2Sl(vf, lc)-1;
vf->fifo_slot = Cyc2Sl(vf, lc);
vf->fifo_maxslot = Cyc2Sl(vf, 488);
}
// VDP memory rd/wr
static __inline void AutoIncrement(void)
@ -722,8 +843,8 @@ PICO_INTERNAL_ASM void PicoVideoWrite(u32 a,unsigned short d)
case 0x00: // Data port 0 or 2
// try avoiding the sync..
if (Pico.m.scanline < (pvid->reg[1]&0x08 ? 240 : 224) && (pvid->reg[1]&0x40) &&
!(!pvid->pending &&
((pvid->command & 0xc00000f0) == 0x40000010 && PicoMem.vsram[pvid->addr>>1] == (d & 0x7ff)))
!(!pvid->pending && ((pvid->command & 0xc00000f0) == 0x40000010 &&
PicoMem.vsram[(pvid->addr>>1) & 0x3f] == (d & 0x7ff)))
)
DrawSync(0); // XXX it's unclear when vscroll data is fetched from vsram?
@ -881,10 +1002,10 @@ update_irq:
static u32 VideoSr(const struct PicoVideo *pv)
{
unsigned int hp = pv->reg[12]&1 ? 15*488/210+1 : 15*488/171+1; // HBLANK start
unsigned int hl = pv->reg[12]&1 ? 37*488/210+1 : 28*488/171+1; // HBLANK len
unsigned int hp = pv->reg[12]&1 ? hboff40*488/slots40 : hboff32*488/slots32;
unsigned int hl = pv->reg[12]&1 ? hblen40*488/slots40 : hblen32*488/slots32;
unsigned int c;
u32 d = pv->status;
u32 d = (u16)pv->status;
c = SekCyclesDone() - Pico.t.m68c_line_start;
if (c - hp < hl)
@ -914,32 +1035,17 @@ PICO_INTERNAL_ASM u32 PicoVideoRead(u32 a)
return d;
}
// H-counter info (based on Generator):
// frame:
// | <- hblank? -> |
// start <416> hint <36> hdisplay <38> end // CPU cycles
// |---------...---------|------------|-------------|
// 0 B6 E4 FF // 40 cells
// 0 93 E8 FF // 32 cells
// Gens (?) v-render
// start <hblank=84> hint hdisplay <404> |
// |---------------------|--------------------------|
// E4 (hc[0x43]==0) 07 B1 // 40
// E8 (hc[0x45]==0) 05 91 // 32
// check: Sonic 3D Blast bonus, Cannon Fodder, Chase HQ II, 3 Ninjas kick back, Road Rash 3, Skitchin', Wheel of Fortune
if ((a&0x1c)==0x08)
{
unsigned int c;
u32 d;
c = (SekCyclesDone() - Pico.t.m68c_line_start) & 0x1ff; // FIXME
c = SekCyclesDone() - Pico.t.m68c_line_start;
if (Pico.video.reg[0]&2)
d = Pico.video.hv_latch;
else if (Pico.video.reg[12]&1)
d = hcounts_40[c/2] | (Pico.video.v_counter << 8);
else d = hcounts_32[c/2] | (Pico.video.v_counter << 8);
d = hcounts_40[c/clkdiv] | (Pico.video.v_counter << 8);
else d = hcounts_32[c/clkdiv] | (Pico.video.v_counter << 8);
elprintf(EL_HVCNT, "hv: %02x %02x [%u] @ %06x", d, Pico.video.v_counter, SekCyclesDone(), SekPc);
return d;
@ -996,12 +1102,12 @@ unsigned char PicoVideoRead8HV_H(int is_from_z80)
// FIXME: broken
unsigned char PicoVideoRead8HV_L(int is_from_z80)
{
u32 d = (SekCyclesDone() - Pico.t.m68c_line_start) & 0x1ff; // FIXME
u32 d = SekCyclesDone() - Pico.t.m68c_line_start;
if (Pico.video.reg[0]&2)
d = Pico.video.hv_latch;
else if (Pico.video.reg[12]&1)
d = hcounts_40[d/2];
else d = hcounts_32[d/2];
d = hcounts_40[d/clkdiv];
else d = hcounts_32[d/clkdiv];
elprintf(EL_HVCNT, "hcounter: %02x [%u] @ %06x", d, SekCyclesDone(), SekPc);
return d;
}

View File

@ -280,7 +280,7 @@ static int custom_read(menu_entry *me, const char *var, const char *val)
return 1;
case MA_OPT_SOUND_ALPHA:
if (strcasecmp(var, "Filter strength (alpha)") != 0) return 0;
if (strcasecmp(var, "Filter strength") != 0) return 0;
PicoIn.sndFilterAlpha = 0x10000 * atof(val);
return 1;

@ -0,0 +1 @@
Subproject commit b20f7512a69b732ab4082c05e01fc29d42333fae

File diff suppressed because it is too large Load Diff

View File

@ -7,10 +7,10 @@
#include <stdint.h>
#include <string.h>
#ifdef __mips__
#if defined __mips__
#include "dismips.c"
#define disasm dismips
#else
#elif defined __arm__
#include "disarm.c"
#define disasm disarm
#endif
@ -36,6 +36,7 @@ static const char *lookup_name(void *addr)
return NULL;
}
#ifdef disasm
void host_dasm(void *addr, int len)
{
void *end = (char *)addr + len;
@ -65,6 +66,30 @@ void host_dasm(void *addr, int len)
addr = (char *)addr + sizeof(long);
}
}
#else
void host_dasm(void *addr, int len)
{
uint8_t *end = (uint8_t *)addr + len;
char buf[64];
uint8_t *p = addr;
int i = 0, o = 0;
o = snprintf(buf, sizeof(buf), "%p: ", p);
while (p < end) {
o += snprintf(buf+o, sizeof(buf)-o, "%02x ", *p++);
if (++i >= 16) {
buf[o] = '\0';
printf("%s\n", buf);
o = snprintf(buf, sizeof(buf), "%p: ", p);
i = 0;
}
}
if (i) {
buf[o] = '\0';
printf("%s\n", buf);
}
}
#endif
void host_dasm_new_symbol_(void *addr, const char *name)
{

@ -1 +1 @@
Subproject commit ef9e212fa29bb72d23558da21bb5694fd2d01768
Subproject commit b18d274b998cd4406070ddc1f370f53392241af0

View File

@ -0,0 +1,65 @@
/*
* MP3 decoding using dr_mp3
* (C) kub, 2020
*
* This work is licensed under the terms of MAME license.
* See COPYING file in the top-level directory.
*/
#include <stdio.h>
#include <pico/pico_int.h>
#define DR_MP3_IMPLEMENTATION
#include "dr_libs/dr_mp3.h"
#include "mp3.h"
static drmp3dec mp3dec;
static unsigned char mp3_input_buffer[2 * 1024];
int mp3dec_start(FILE *f, int fpos_start)
{
drmp3dec_init(&mp3dec);
return 0;
}
int mp3dec_decode(FILE *f, int *file_pos, int file_len)
{
drmp3dec_frame_info info;
unsigned char *readPtr;
int bytesLeft;
int offset; // mp3 frame offset from readPtr
int len;
int retry = 3;
do
{
if (*file_pos >= file_len)
return 1; /* EOF, nothing to do */
fseek(f, *file_pos, SEEK_SET);
bytesLeft = fread(mp3_input_buffer, 1, sizeof(mp3_input_buffer), f);
offset = mp3_find_sync_word(mp3_input_buffer, bytesLeft);
if (offset < 0) {
lprintf("find_sync_word (%i/%i) err %i\n",
*file_pos, file_len, offset);
*file_pos = file_len;
return 1; // EOF
}
*file_pos += offset;
readPtr = mp3_input_buffer + offset;
bytesLeft -= offset;
len = drmp3dec_decode_frame(&mp3dec, readPtr, bytesLeft, cdda_out_buffer, &info);
if (len > 0) // retrieved decoded data
*file_pos += info.frame_bytes;
else if (info.frame_bytes > 0) // no output but input consumed?
*file_pos += 1; // try to skip frame
else if (offset == 0) // bad frame?
*file_pos += 1; // try resyncing
// else // truncated frame, try more data
}
while (len <= 0 && --retry > 0);
return len <= 0;
}

View File

@ -1726,7 +1726,7 @@ void plat_video_loop_prepare(void)
// take over any new vout settings XXX ask plat_sdl for scaling instead!
plat_sdl_change_video_mode(g_menuscreen_w, g_menuscreen_h, 0);
// switch over to scaled output if available
if (plat_sdl_overlay != NULL || plat_sdl_gl_active) {
if (plat_sdl_overlay != NULL || plat_sdl_gl_active || currentConfig.scaling != EOPT_SCALE_NONE) {
g_screen_width = 320;
g_screen_height = 240;
g_screen_ppitch = g_screen_width;

View File

@ -353,7 +353,7 @@ static void munmap(void *addr, size_t length)
void* mmap(void *desired_addr, size_t len, int mmap_prot, int mmap_flags, int fildes, size_t off)
{
return malloc(len);
return calloc(1, len);
}
void munmap(void *base_addr, size_t len)
@ -706,6 +706,8 @@ void lprintf(const char *fmt, ...)
}
/* libretro */
bool libretro_supports_bitmasks = false;
void retro_set_environment(retro_environment_t cb)
{
#ifdef USE_LIBRETRO_VFS
@ -1638,6 +1640,7 @@ void retro_run(void)
bool updated = false;
int pad, i;
static void *buff;
int16_t input;
PicoIn.skipFrame = 0;
@ -1647,10 +1650,18 @@ void retro_run(void)
input_poll_cb();
PicoIn.pad[0] = PicoIn.pad[1] = 0;
for (pad = 0; pad < 2; pad++)
for (i = 0; i < RETRO_PICO_MAP_LEN; i++)
if (input_state_cb(pad, RETRO_DEVICE_JOYPAD, 0, i))
PicoIn.pad[pad] |= retro_pico_map[i];
for (pad = 0; pad < 2; pad++) {
if (libretro_supports_bitmasks) {
input = input_state_cb(pad, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_MASK);
for (i = 0; i < RETRO_PICO_MAP_LEN; i++)
if (input & (1 << i))
PicoIn.pad[pad] |= retro_pico_map[i];
} else {
for (i = 0; i < RETRO_PICO_MAP_LEN; i++)
if (input_state_cb(pad, RETRO_DEVICE_JOYPAD, 0, i))
PicoIn.pad[pad] |= retro_pico_map[i];
}
}
if (PicoPatches)
PicoPatchApply();
@ -1785,6 +1796,9 @@ void retro_init(void)
environ_cb(RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE, &disk_control);
if (environ_cb(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, NULL))
libretro_supports_bitmasks = true;
#ifdef _3DS
ctr_svchack_successful = ctr_svchack_init();
check_rosalina();
@ -1853,4 +1867,6 @@ void retro_deinit(void)
#endif
vout_buf = NULL;
PicoExit();
libretro_supports_bitmasks = false;
}

View File

@ -32,7 +32,7 @@ void pemu_prep_defconfig(void)
void pemu_validate_config(void)
{
#if !defined(__arm__) && !defined(__aarch64__) && !defined(__mips__) && !defined(__riscv__) && !defined(__riscv) && !defined(__powerpc__) && !defined(__i386__) && !defined(__x86_64__)
#if !defined(__arm__) && !defined(__aarch64__) && !defined(__mips__) && !defined(__riscv__) && !defined(__riscv) && !defined(__powerpc__) && !defined(__ppc__) && !defined(__i386__) && !defined(__x86_64__)
PicoIn.opt &= ~POPT_EN_DRC;
#endif
}

16
platform/linux/menu.c Normal file
View File

@ -0,0 +1,16 @@
#include "../libpicofe/gp2x/plat_gp2x.h"
// ------------ gfx options menu ------------
const char *men_scaling_opts[] = { "OFF", "ON", NULL };
#define MENU_OPTIONS_GFX \
// mee_enum ("screen scaling", MA_OPT_SCALING, currentConfig.scaling, men_scaling_opts), \
#define MENU_OPTIONS_ADV
void linux_menu_init(void)
{
}

View File

@ -6,4 +6,4 @@ Exec=PicoDrive %f
Icon=megadrive
Terminal=false
Categories=emulators;
MimeType=.md;.smd;.bin;.sms;.cue;.32x;.zip;.7z
MimeType=.md;.smd;.bin;.sms;.cue;.chd;.32x;.zip;.7z

View File

@ -3,10 +3,10 @@ Name=Picodrive
Comment=A megadrive/genesis emulator
Exec=PicoDrive %f
Icon=megadrive
Categories=games;
Categories=emulators;
X-OD-Manual=
X-OD-Selector=
X-OD-Filter=.md,.smd,.bin,.sms,.cue,.32x,.zip,.7z
X-OD-Filter=.md,.smd,.bin,.sms,.cue,.chd,.32x,.zip,.7z
Terminal=true
Type=Application
StartupNotify=true

View File

@ -15,7 +15,7 @@
# rg350: rg350-toolchain (+ mips-toolchain for newer gcc)
# psp: pspdev
mkdir -p release
mkdir -p release-$1
trap "exit" ERR
# GPH devices: gp2x, wiz, caanoo, with ubuntu arm gcc 4.7
@ -23,18 +23,18 @@ trap "exit" ERR
TC=$HOME/opt/open2x/gcc-4.1.1-glibc-2.3.6 CROSS_COMPILE=arm-linux-gnueabi- CFLAGS="-I$TC/arm-open2x-linux/include -I$HOME/src/gp2x/armroot/include -U_FORTIFY_SOURCE" LDFLAGS="-B$TC/lib/gcc/arm-open2x-linux/4.1.1 -B$TC/arm-open2x-linux/lib -L$TC/arm-open2x-linux/lib -L$HOME/src/gp2x/armroot/lib" ./configure --platform=gp2x
make clean all
make -C platform/gp2x rel VER=$1
mv PicoDrive_$1.zip release/PicoDrive-gph_$1.zip
mv PicoDrive_$1.zip release-$1/PicoDrive-gph_$1.zip
# dingux: dingoo a320, ritmix rzx-50, JZ4755 or older (mips32r1 w/o fpu)
# NB works for legacy dingux and possibly opendingux before gcw0
TC=$HOME/opt/opendingux-toolchain PATH=$TC/usr/bin:$PATH CROSS_COMPILE=mipsel-linux- CFLAGS="-I $TC/usr/include -I $TC/usr/include/SDL -Wno-unused-result -mabicalls" LDFLAGS="--sysroot $TC" ./configure --platform=dingux
TC=$HOME/opt/opendingux-toolchain PATH=$TC/usr/bin:$PATH make clean all
mv PicoDrive-dge.zip release/PicoDrive-dge_$1.zip
mv PicoDrive-dge.zip release-$1/PicoDrive-dge_$1.zip
# retrofw: rs-97 and similar, JZ4760 (mips32r1 with fpu)
TC=$HOME/opt/mipsel-linux-uclibc PATH=$TC/bin:$PATH CROSS_COMPILE=mipsel-linux- CFLAGS="-I $TC/include -I $TC/include/SDL -Wno-unused-result" LDFLAGS="--sysroot $TC/mipsel-buildroot-linux-uclibc/sysroot" ./configure --platform=retrofw
TC=$HOME/opt/mipsel-linux-uclibc PATH=$TC/bin:$PATH make clean all
mv PicoDrive.opk release/PicoDrive-retrofw_$1.opk
mv PicoDrive.opk release-$1/PicoDrive-retrofw_$1.opk
# gcw0: JZ4770 (mips32r2 with fpu), swapped X/Y buttons, SDK toolchain
#TC=$HOME/opt/gcw0-toolchain PATH=$TC/usr/bin:$PATH CROSS_COMPILE=mipsel-linux- TS=$TC/usr/mipsel-gcw0-linux-uclibc/sysroot CFLAGS="-I$TS/usr/include -I$TS/usr/include/SDL" LDFLAGS="--sysroot $TS" ./configure --platform=gcw0
@ -43,7 +43,7 @@ mv PicoDrive.opk release/PicoDrive-retrofw_$1.opk
# gcw0: JZ4770 (mips32r2 with fpu), swapped X/Y buttons, newer generic gcc
TC=$HOME/opt/gcw0-toolchain PATH=$HOME/opt/mips-toolchain/bin:$PATH CROSS_COMPILE=mipsel-linux- TS=$TC/usr/mipsel-gcw0-linux-uclibc/sysroot CFLAGS="-I$TS/usr/include -I$TS/usr/include/SDL -mabicalls" LDFLAGS="--sysroot $TS -Wl,--dynamic-linker=/lib/ld-uClibc.so.0" ./configure --platform=gcw0
PATH=$HOME/opt/mips-toolchain/usr/bin:$PATH make clean all
mv PicoDrive.opk release/PicoDrive-gcw0_$1.opk
mv PicoDrive.opk release-$1/PicoDrive-gcw0_$1.opk
# rg350: JZ4770, SDK toolchain
#TC=$HOME/opt/rg350-toolchain PATH=$TC/usr/bin:$PATH CROSS_COMPILE=mipsel-linux- TS=$TC/usr/mipsel-gcw0-linux-uclibc/sysroot CFLAGS="-I$TS/usr/include -I$TS/usr/include/SDL" LDFLAGS="--sysroot $TS" ./configure --platform=rg350
@ -53,10 +53,10 @@ mv PicoDrive.opk release/PicoDrive-gcw0_$1.opk
# NB this may or may not work on the newer opendingux beta
TC=$HOME/opt/rg350-toolchain PATH=$HOME/opt/mips-toolchain/bin:$PATH CROSS_COMPILE=mipsel-linux- TS=$TC/usr/mipsel-gcw0-linux-uclibc/sysroot CFLAGS="-I$TS/usr/include -I$TS/usr/include/SDL -mabicalls" LDFLAGS="--sysroot $TS -Wl,--dynamic-linker=/lib/ld-uClibc.so.0" ./configure --platform=opendingux
PATH=$HOME/opt/mips-toolchain/usr/bin:$PATH make clean all
mv PicoDrive.opk release/PicoDrive-opendingux_$1.opk
mv PicoDrive.opk release-$1/PicoDrive-opendingux_$1.opk
# psp (experimental), pspdev SDK toolchain
TC=$HOME/opt/pspdev PATH=$TC/bin:$PATH CROSS_COMPILE=psp- CFLAGS="-I$TC/psp/sdk/include -D_POSIX_C_SOURCE=199506L" LDFLAGS="-L$TC/psp/sdk/lib" ./configure --platform=psp
TC=$HOME/opt/pspdev PATH=$TC/bin:$PATH make clean all
make -C platform/psp rel VER=$1
mv PicoDrive_psp_$1.zip release/PicoDrive-psp_$1.zip
mv PicoDrive_psp_$1.zip release-$1/PicoDrive-psp_$1.zip