mirror of
https://github.com/FunKey-Project/picodrive-irixxxx.git
synced 2026-01-25 09:14:43 +01:00
Merge pull request #8 from DrUm78/FunKey
Last irixxxx's optimizations for 32X and Sega-CD + volume fix
This commit is contained in:
commit
99a45bbe18
7
.gitmodules
vendored
7
.gitmodules
vendored
@ -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
|
||||
|
||||
3
Makefile
3
Makefile
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
@ -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) /**/
|
||||
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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 { \
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
16
pico/cart.c
16
pico/cart.c
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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}
|
||||
|
||||
176
pico/misc.c
176
pico/misc.c
@ -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)
|
||||
|
||||
10
pico/patch.c
10
pico/patch.c
@ -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
|
||||
{
|
||||
|
||||
@ -40,6 +40,7 @@ void PicoInit(void)
|
||||
Pico32xInit();
|
||||
PsndInit();
|
||||
|
||||
PicoVideoInit();
|
||||
PicoDrawInit();
|
||||
PicoDraw2Init();
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
42
pico/sek.c
42
pico/sek.c
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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++)
|
||||
{
|
||||
|
||||
194
pico/videoport.c
194
pico/videoport.c
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
1
platform/common/dr_libs
Submodule
1
platform/common/dr_libs
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit b20f7512a69b732ab4082c05e01fc29d42333fae
|
||||
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
65
platform/common/mp3_drmp3.c
Normal file
65
platform/common/mp3_drmp3.c
Normal 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;
|
||||
}
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
16
platform/linux/menu.c
Normal 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)
|
||||
{
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user