From 34168c3d55c745ed23ae562977666153bf4b9e80 Mon Sep 17 00:00:00 2001 From: Julian Uy Date: Wed, 23 Oct 2024 09:43:01 -0500 Subject: [PATCH 1/8] add: Dev5 MMIO definitions --- common/include/dev5_mmio_hwport.h | 90 +++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 common/include/dev5_mmio_hwport.h diff --git a/common/include/dev5_mmio_hwport.h b/common/include/dev5_mmio_hwport.h new file mode 100644 index 00000000000..8e382bce879 --- /dev/null +++ b/common/include/dev5_mmio_hwport.h @@ -0,0 +1,90 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +*/ + +/** + * @file + * Definitions for memory-mapped I/O for DEV5. + */ + +#ifndef __DEV5_MMIO_HWPORT__ +#define __DEV5_MMIO_HWPORT__ + +typedef struct dev5_mmio_hwport_ /* base -> 0xBF402000 */ +{ + vu8 m_dev5_reg_000; + vu8 m_dev5_reg_001; + vu8 m_dev5_reg_002; + vu8 m_dev5_reg_003; + vu8 m_dev5_reg_004; + vu8 m_dev5_reg_005; + vu8 m_dev5_reg_006; + vu8 m_dev5_reg_007; + vu8 m_dev5_reg_008; + vu8 m_dev5_reg_009; + vu8 m_dev5_reg_00A; + vu8 m_dev5_reg_00B; + vu8 m_dev5_reg_00C; + vu8 m_dev5_reg_00D; + vu8 m_dev5_reg_00E; + vu8 m_dev5_reg_00F; + vu8 m_dev5_reg_010; + vu8 m_dev5_reg_011; + vu8 m_dev5_reg_012; + vu8 m_dev5_reg_013; + vu8 m_dev5_reg_014; + vu8 m_dev5_reg_015; + vu8 m_dev5_reg_016; + vu8 m_dev5_reg_017; + vu8 m_dev5_reg_018; + vu8 m_dev5_reg_019; + vu8 m_dev5_reg_01A; + vu8 m_dev5_reg_01B; + vu8 m_dev5_reg_01C; + vu8 m_dev5_reg_01D; + vu8 m_dev5_reg_01E; + vu8 m_dev5_reg_01F; + vu8 m_dev5_reg_020; + vu8 m_dev5_reg_021; + vu8 m_dev5_reg_022; + vu8 m_dev5_reg_023; + vu8 m_dev5_reg_024; + vu8 m_dev5_reg_025; + vu8 m_dev5_reg_026; + vu8 m_dev5_reg_027; + vu8 m_dev5_reg_028; + vu8 m_dev5_reg_029; + vu8 m_dev5_reg_02A; + vu8 m_dev5_reg_02B; + vu8 m_dev5_reg_02C; + vu8 m_dev5_reg_02D; + vu8 m_dev5_reg_02E; + vu8 m_dev5_reg_02F; + vu8 m_dev5_reg_030; + vu8 m_dev5_reg_031; + vu8 m_dev5_reg_032; + vu8 m_dev5_reg_033; + vu8 m_dev5_reg_034; + vu8 m_dev5_reg_035; + vu8 m_dev5_reg_036; + vu8 m_dev5_reg_037; + vu8 m_dev5_reg_038; + vu8 m_dev5_reg_039; + vu8 m_dev5_reg_03A; +} dev5_mmio_hwport_t; + +#if !defined(USE_DEV5_MMIO_HWPORT) && defined(_IOP) +// cppcheck-suppress-macro constVariablePointer +#define USE_DEV5_MMIO_HWPORT() dev5_mmio_hwport_t *const dev5_mmio_hwport = (dev5_mmio_hwport_t *)0xBF402000 +#endif +#if !defined(USE_DEV5_MMIO_HWPORT) +#define USE_DEV5_MMIO_HWPORT() +#endif + +#endif /* __DEV5_MMIO_HWPORT__ */ From 906678c46304b9658c297a4db64f04d358e0f5ad Mon Sep 17 00:00:00 2001 From: Julian Uy Date: Wed, 23 Oct 2024 09:43:40 -0500 Subject: [PATCH 2/8] add: CDVDFSV RPC main packet definitions --- common/include/libcdvd-rpc.h | 288 +++++++++++++++++++++++++++++++++++ 1 file changed, 288 insertions(+) diff --git a/common/include/libcdvd-rpc.h b/common/include/libcdvd-rpc.h index 756bd736bf9..3736ff2020c 100644 --- a/common/include/libcdvd-rpc.h +++ b/common/include/libcdvd-rpc.h @@ -17,6 +17,7 @@ #define __LIBCDVD_RPC_H__ #include +#include /* S-command parameters */ @@ -58,4 +59,291 @@ struct cdvdReadKeyParam u32 command; }; +/* SIF RPC packet definitions */ + +typedef struct cdvdfsv_rpc1_inpacket_ +{ + int m_mode; +} cdvdfsv_rpc1_inpacket_t; + +typedef struct cdvdfsv_rpc1_outpacket_ +{ + int m_retres; + int m_cdvdfsv_ver; + int m_cdvdman_ver; + int m_debug_mode; +} cdvdfsv_rpc1_outpacket_t; + +typedef struct cdvdfsv_rpc2_inpacket_ +{ + int m_mode; +} cdvdfsv_rpc2_inpacket_t; + +typedef struct cdvdfsv_rpc2_outpacket_ +{ + int m_retres; +} cdvdfsv_rpc2_outpacket_t; + +typedef struct cdvdfsv_unaligned_data_outpacket_ +{ + u32 m_b1len; + u32 m_b2len; + u32 m_b1dst; + u32 m_b2dst; + u8 m_pbuf1[64]; + u8 m_pbuf2[64]; +} cdvdfsv_unaligned_data_outpacket_t; + +typedef struct cdvdfsv_rpc4_sz12c_inpacket_ +{ + sceCdlFILE m_fp; + int m_file_attributes; + char m_path[256]; + uiptr m_eedest; + int m_layer; +} cdvdfsv_rpc4_sz12c_inpacket_t; + +typedef struct cdvdfsv_rpc4_sz128_inpacket_ +{ + sceCdlFILE m_fp; + int m_file_attributes; + char m_path[256]; + uiptr m_eedest; +} cdvdfsv_rpc4_sz128_inpacket_t; + +typedef struct cdvdfsv_rpc4_sz124_inpacket_ +{ + sceCdlFILE m_fp; + char m_path[256]; + uiptr m_eedest; +} cdvdfsv_rpc4_sz124_inpacket_t; + +typedef union cdvdfsv_rpc4_inpacket_ +{ + cdvdfsv_rpc4_sz12c_inpacket_t m_pkt_sz12c; + cdvdfsv_rpc4_sz128_inpacket_t m_pkt_sz128; + cdvdfsv_rpc4_sz124_inpacket_t m_pkt_sz124; +} cdvdfsv_rpc4_inpacket_t; + +typedef struct cdvdfsv_rpc4_outpacket_ +{ + int m_retres; + int m_padding[3]; +} cdvdfsv_rpc4_outpacket_t; + +typedef struct cdvdfsv_rpc3_05_inpacket_ +{ + int m_param; +} cdvdfsv_rpc3_05_inpacket_t; + +typedef struct cdvdfsv_rpc3_0B_inpacket_ +{ + u8 m_cmdNum; + u8 m_gap1; + u16 m_inBuffSize; + u8 m_inBuff[16]; +} cdvdfsv_rpc3_0B_inpacket_t; + +typedef struct cdvdfsv_rpc3_15_inpacket_ +{ + int m_mode; +} cdvdfsv_rpc3_15_inpacket_t; + +typedef struct cdvdfsv_rpc3_22_inpacket_ +{ + int m_media; + char m_char4; +} cdvdfsv_rpc3_22_inpacket_t; + +typedef struct cdvdfsv_rpc3_23_inpacket_ +{ + int m_priority; +} cdvdfsv_rpc3_23_inpacket_t; + +typedef struct cdvdfsv_rpc3_25_inpacket_ +{ + int m_param; + int m_timeout; +} cdvdfsv_rpc3_25_inpacket_t; + +typedef union cdvdfsv_rpc3_inpacket_ +{ + cdvdfsv_rpc3_05_inpacket_t m_pkt_05; + cdvdfsv_rpc3_0B_inpacket_t m_pkt_0B; + cdvdfsv_rpc3_15_inpacket_t m_pkt_15; + cdvdfsv_rpc3_22_inpacket_t m_pkt_22; + cdvdfsv_rpc3_23_inpacket_t m_pkt_23; + cdvdfsv_rpc3_25_inpacket_t m_pkt_25; +} cdvdfsv_rpc3_inpacket_t; + +typedef struct cdvdfsv_rpc3_01_outpacket_ +{ + int m_retres; + sceCdCLOCK m_clock; +} cdvdfsv_rpc3_01_outpacket_t; + +typedef struct cdvdfsv_rpc3_05_outpacket_ +{ + int m_retres; + u32 m_traychk; +} cdvdfsv_rpc3_05_outpacket_t; + +typedef struct cdvdfsv_rpc3_06_outpacket_ +{ + int m_retres; + u32 m_result; + u8 m_buffer[8]; +} cdvdfsv_rpc3_06_outpacket_t; + +typedef struct cdvdfsv_rpc3_0B_outpacket_ +{ + u8 m_outbuf[16]; +} cdvdfsv_rpc3_0B_outpacket_t; + +typedef struct cdvdfsv_rpc3_15_outpacket_ +{ + int m_retres; + u32 m_status; +} cdvdfsv_rpc3_15_outpacket_t; + +typedef struct cdvdfsv_rpc3_1A_outpacket_ +{ + int m_retres; + u32 m_status; + char m_buffer[16]; +} cdvdfsv_rpc3_1A_outpacket_t; + +typedef struct cdvdfsv_rpc3_21_outpacket_ +{ + int m_retres; + u32 m_result; +} cdvdfsv_rpc3_21_outpacket_t; + +typedef struct cdvdfsv_rpc3_24_outpacket_ +{ + int m_retres; + u64 m_guid; +} cdvdfsv_rpc3_24_outpacket_t; + +typedef struct cdvdfsv_rpc3_26_outpacket_ +{ + int m_retres; + unsigned int m_id; +} cdvdfsv_rpc3_26_outpacket_t; + +typedef struct cdvdfsv_rpc3_27_outpacket_ +{ + int m_retres; + int m_on_dual; + unsigned int m_layer1_start; +} cdvdfsv_rpc3_27_outpacket_t; + +typedef union cdvdfsv_rpc3_outpacket_ +{ + int m_retres; + cdvdfsv_rpc3_01_outpacket_t m_pkt_01; + cdvdfsv_rpc3_05_outpacket_t m_pkt_05; + cdvdfsv_rpc3_06_outpacket_t m_pkt_06; + cdvdfsv_rpc3_0B_outpacket_t m_pkt_0B; + cdvdfsv_rpc3_15_outpacket_t m_pkt_15; + cdvdfsv_rpc3_1A_outpacket_t m_pkt_1A; + cdvdfsv_rpc3_21_outpacket_t m_pkt_21; + cdvdfsv_rpc3_24_outpacket_t m_pkt_24; + cdvdfsv_rpc3_26_outpacket_t m_pkt_26; + cdvdfsv_rpc3_27_outpacket_t m_pkt_27; +} cdvdfsv_rpc3_outpacket_t; + +typedef struct cdvdfsv_rpc5_01_inpacket_ +{ + u32 m_lbn; + u32 m_sectors; + uiptr m_paddr; + sceCdRMode m_rmodeee; + uiptr m_eeremaindest; + uiptr m_eedest; + u32 m_decval; +} cdvdfsv_rpc5_01_inpacket_t; + +typedef struct cdvdfsv_rpc5_02_inpacket_ +{ + u32 m_lbn; + u32 m_sectors; + uiptr m_buf; + sceCdRMode m_mode; + uiptr m_eeremaindest; + uiptr m_eedest; +} cdvdfsv_rpc5_02_inpacket_t; + +typedef struct cdvdfsv_rpc5_04_inpacket_ +{ + uiptr m_eedest; +} cdvdfsv_rpc5_04_inpacket_t; + +typedef struct cdvdfsv_rpc5_05_inpacket_ +{ + u32 m_lbn; +} cdvdfsv_rpc5_05_inpacket_t; + +typedef struct cdvdfsv_rpc5_0C_inpacket_ +{ + u8 m_cmdNum; + u8 m_gap1; + u16 m_inBuffSize; + u8 m_inBuff[16]; +} cdvdfsv_rpc5_0C_inpacket_t; + +typedef struct cdvdfsv_rpc5_0D_inpacket_ +{ + u32 m_lbn; + u32 m_sectors; + void *m_buf; + sceCdRMode m_mode; + u8 m_unused[4]; + uiptr m_eedest; +} cdvdfsv_rpc5_0D_inpacket_t; + +typedef struct cdvdfsv_rpc5_0F_inpacket_ +{ + sceCdRChain m_readChain[65]; + sceCdRMode m_mode; + uiptr m_eedest; +} cdvdfsv_rpc5_0F_inpacket_t; + +typedef union cdvdfsv_rpc5_inpacket_ +{ + cdvdfsv_rpc5_01_inpacket_t m_pkt_01; + cdvdfsv_rpc5_02_inpacket_t m_pkt_02; + cdvdfsv_rpc5_04_inpacket_t m_pkt_04; + cdvdfsv_rpc5_05_inpacket_t m_pkt_05; + cdvdfsv_rpc5_0C_inpacket_t m_pkt_0C; + cdvdfsv_rpc5_0D_inpacket_t m_pkt_0D; + cdvdfsv_rpc5_0F_inpacket_t m_pkt_0F; +} cdvdfsv_rpc5_inpacket_t; + +typedef struct cdvdfsv_rpc5_04_outpacket_ +{ + int m_retres; + int m_isdvd; +} cdvdfsv_rpc5_04_outpacket_t; + +typedef struct cdvdfsv_rpc5_11_outpacket_ +{ + int m_retres; + u8 m_diskid[5]; +} cdvdfsv_rpc5_11_outpacket_t; + +typedef struct cdvdfsv_rpc5_17_outpacket_ +{ + int m_retres; + u32 m_status; +} cdvdfsv_rpc5_17_outpacket_t; + +typedef union cdvdfsv_rpc5_outpacket_ +{ + int m_retres; + cdvdfsv_rpc5_04_outpacket_t m_pkt_04; + cdvdfsv_rpc5_11_outpacket_t m_pkt_11; + cdvdfsv_rpc5_17_outpacket_t m_pkt_17; +} cdvdfsv_rpc5_outpacket_t; + #endif /* _LIBCDVD_RPC_H_ */ From 15937ac0ecf782ec111e40382dcdde33e8c35b9c Mon Sep 17 00:00:00 2001 From: Julian Uy Date: Wed, 23 Oct 2024 09:44:07 -0500 Subject: [PATCH 3/8] add: cdvdstm devctl structure definition --- common/include/cdvd-ioctl.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/common/include/cdvd-ioctl.h b/common/include/cdvd-ioctl.h index 30bae5459d8..de99b42363e 100644 --- a/common/include/cdvd-ioctl.h +++ b/common/include/cdvd-ioctl.h @@ -16,6 +16,8 @@ #ifndef __CDVD_IOCTL_H__ #define __CDVD_IOCTL_H__ +#include + /////////////////////////////////////////////////////////////////////////////// // CDVDMAN.IRX @@ -53,4 +55,18 @@ #define CDIOC_FSCACHEINIT 0x4395 #define CDIOC_FSCACHEDELETE 0x4397 +/////////////////////////////////////////////////////////////////////////////// +// CDVDSTM.IRX + +typedef struct cdrom_stm_devctl_ +{ + u32 m_posszarg1; + u32 m_posszarg2; + void *m_buffer; + u32 m_cmdid; + sceCdRMode m_rmode; + u32 m_error; +} cdrom_stm_devctl_t; + + #endif /* __CDVD_IOCTL_H__ */ From 73362da31b492bc9535fb22b45a4518167e3c655 Mon Sep 17 00:00:00 2001 From: Julian Uy Date: Wed, 23 Oct 2024 09:44:42 -0500 Subject: [PATCH 4/8] add: internal structure and verbose wrappers as used by cdvdman --- iop/kernel/include/cdvdman.h | 95 ++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/iop/kernel/include/cdvdman.h b/iop/kernel/include/cdvdman.h index f5632c18c1d..7622cbab9b8 100644 --- a/iop/kernel/include/cdvdman.h +++ b/iop/kernel/include/cdvdman.h @@ -25,6 +25,101 @@ extern "C" { #endif +#ifdef BUILDING_CDVD_MODULE +#define PRINTF(...) \ + { \ + printf(__VA_ARGS__); \ + } +#define KPRINTF(...) \ + { \ + Kprintf(__VA_ARGS__); \ + } +#define VERBOSE_PRINTF(level, ...) \ + { \ + if ( g_verbose_level >= (level) ) \ + { \ + printf(__VA_ARGS__);\ + } \ + } +#define VERBOSE_KPRINTF(level, ...) \ + { \ + if ( g_verbose_level >= (level) ) \ + { \ + Kprintf(__VA_ARGS__);\ + } \ + } +#endif + +typedef struct cdvdman_dma3_parameter_ +{ + u16 m_dma3_blkwords; + u16 m_dma3_blkcount; + void *m_dma3_maddress; + int (*m_dma3_callback)(void); + u16 m_dma3_csectors; + u16 m_cdvdreg_howto; + u32 m_dma3_msectors; +} cdvdman_dma3_parameter_t; + +typedef struct cdvdman_internal_struct_ +{ + char m_cdvdman_command; + char m_last_error; + char m_unused_002; + char m_ncmd_intr_count; + int m_wait_flag; + int m_thread_id; + int m_stream_flag; + int m_read2_flag; + int m_cdvdman_lsn; + int m_cdvdman_rbuffer; + int m_cdvdman_nsec; + int m_cdvdman_csec; + int m_cdvdman_rsec; + int m_cdvdman_pattern; + sceCdRMode m_cdvdman_cdrmode; + int m_recover_status; + int m_dvd_flag; + int m_read_lsn; + void *m_read_buf; + int m_read_sectors; + sceCdRMode m_read_mode; + int m_read_chunk_reprocial_32; + int m_dintrlsn; + void *m_read_callback; + int m_read_chunk; + char m_scmd_flag; + char m_scmd; + char m_sdlen; + char m_rdlen; + char m_scmd_sd[16]; + char m_scmd_rd[16]; + int m_sync_error; + int m_last_read_timeout; + int m_power_flag; + u32 m_layer_1_lsn; + char m_use_toc; + char m_opo_or_para; + char m_current_dvd; + char m_dual_layer_emulation; + u32 m_current_dvd_lsn; + int m_check_version; + int m_dec_shift; + int m_dec_state; + int m_no_dec_flag; + cdvdman_dma3_parameter_t m_dma3_param; + int m_cdvdman_dma3sec; + int m_drive_interupt_request; + u16 m_dec_mode_set; + u16 m_dec_mode_last_set; + int m_waf_set_test; + int m_interupt_read_state; + int m_cd_inited; + int m_tray_is_open; + int m_break_cdvdfsv_readchain; + int m_unused[10]; +} cdvdman_internal_struct_t; + //IOP-only libcdvd function prototypes. int sceCdCheckCmd(void); int sceCdNop(void); From 0351588b7f16b40f9eaec9117382b86bc6382aa0 Mon Sep 17 00:00:00 2001 From: Julian Uy Date: Wed, 23 Oct 2024 09:44:59 -0500 Subject: [PATCH 5/8] add: implementation of cdvdman module --- iop/cdvd/cdvdman/Makefile | 15 + iop/cdvd/cdvdman/src/cdvdman.c | 6074 ++++++++++++++++++++++++++++ iop/cdvd/cdvdman/src/exports.tab | 210 + iop/cdvd/cdvdman/src/imports.lst | 90 + iop/cdvd/cdvdman/src/irx_imports.h | 28 + 5 files changed, 6417 insertions(+) create mode 100644 iop/cdvd/cdvdman/Makefile create mode 100644 iop/cdvd/cdvdman/src/cdvdman.c create mode 100644 iop/cdvd/cdvdman/src/exports.tab create mode 100644 iop/cdvd/cdvdman/src/imports.lst create mode 100644 iop/cdvd/cdvdman/src/irx_imports.h diff --git a/iop/cdvd/cdvdman/Makefile b/iop/cdvd/cdvdman/Makefile new file mode 100644 index 00000000000..8c03c234e1a --- /dev/null +++ b/iop/cdvd/cdvdman/Makefile @@ -0,0 +1,15 @@ +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. + +IOP_CFLAGS += -DBUILDING_CDVD_MODULE +IOP_OBJS = cdvdman.o imports.o exports.o + +include $(PS2SDKSRC)/Defs.make +include $(PS2SDKSRC)/iop/Rules.bin.make +include $(PS2SDKSRC)/iop/Rules.make +include $(PS2SDKSRC)/iop/Rules.release diff --git a/iop/cdvd/cdvdman/src/cdvdman.c b/iop/cdvd/cdvdman/src/cdvdman.c new file mode 100644 index 00000000000..1ce8d781cef --- /dev/null +++ b/iop/cdvd/cdvdman/src/cdvdman.c @@ -0,0 +1,6074 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +*/ + +#include "irx_imports.h" + +#include + +#include +#include +#include +#include +#include + +IRX_ID("cdvd_driver", 2, 38); +// Based on the module from SCE SDK 3.1.0. + +extern struct irx_export_table _exp_cdvdman; + +typedef struct cdvdman_dirtbl_entry_ +{ + int m_number; + int m_parent; + int m_extent; + char m_name[32]; +} cdvdman_dirtbl_entry_t; + +typedef struct cdvdman_fhinfo_ +{ + u32 m_file_lsn; + u32 m_read_pos; + u32 m_file_size; + u32 m_filemode; + int m_fd_flags; + int m_fd_layer; + int m_cache_file_fd; + u8 *m_fd_rcvbuf; + u32 m_fd_rbsize; + void *m_max_cluster; + int m_sector_count_total; + int m_cluster_cur; +} cdvdman_fhinfo_t; + +typedef struct cdvdman_pathtbl_ +{ + int m_cache_path_sz; + int m_lsn; + unsigned int m_nsec; + int m_layer; + unsigned int m_cache_hit_count; +} cdvdman_pathtbl_t; + +typedef struct cdvdman_filetbl_entry_ +{ + sceCdlFILE m_file_struct; + int m_flags; +} cdvdman_filetbl_entry_t; + +typedef struct iso9660_desc_ +{ + // cppcheck-suppress unusedStructMember + unsigned char m_type[1]; + unsigned char m_id[5]; + // cppcheck-suppress unusedStructMember + unsigned char m_version[1]; + // cppcheck-suppress unusedStructMember + unsigned char m_unused1[1]; + // cppcheck-suppress unusedStructMember + unsigned char m_system_id[32]; + // cppcheck-suppress unusedStructMember + unsigned char m_volume_id[32]; + // cppcheck-suppress unusedStructMember + unsigned char m_unused2[8]; + // cppcheck-suppress unusedStructMember + unsigned char m_volume_space_size[8]; + // cppcheck-suppress unusedStructMember + unsigned char m_unused3[32]; + // cppcheck-suppress unusedStructMember + unsigned char m_volume_set_size[4]; + // cppcheck-suppress unusedStructMember + unsigned char m_volume_sequence_number[4]; + // cppcheck-suppress unusedStructMember + unsigned char m_logical_block_size[4]; + // cppcheck-suppress unusedStructMember + unsigned char m_path_table_size[8]; + unsigned char m_type_l_path_table[4]; + // cppcheck-suppress unusedStructMember + unsigned char m_opt_type_l_path_table[4]; + // cppcheck-suppress unusedStructMember + unsigned char m_type_m_path_table[4]; + // cppcheck-suppress unusedStructMember + unsigned char m_opt_type_m_path_table[4]; + // cppcheck-suppress unusedStructMember + unsigned char m_root_directory_record[34]; + // cppcheck-suppress unusedStructMember + unsigned char m_volume_set_id[128]; + // cppcheck-suppress unusedStructMember + unsigned char m_publisher_id[128]; + // cppcheck-suppress unusedStructMember + unsigned char m_preparer_id[128]; + // cppcheck-suppress unusedStructMember + unsigned char m_application_id[128]; + // cppcheck-suppress unusedStructMember + unsigned char m_copyright_file_id[37]; + // cppcheck-suppress unusedStructMember + unsigned char m_abstract_file_id[37]; + // cppcheck-suppress unusedStructMember + unsigned char m_bibliographic_file_id[37]; + // cppcheck-suppress unusedStructMember + unsigned char m_creation_date[17]; + // cppcheck-suppress unusedStructMember + unsigned char m_modification_date[17]; + // cppcheck-suppress unusedStructMember + unsigned char m_expiration_date[17]; + // cppcheck-suppress unusedStructMember + unsigned char m_effective_date[17]; + // cppcheck-suppress unusedStructMember + unsigned char m_file_structure_version[1]; + // cppcheck-suppress unusedStructMember + unsigned char m_unused4[1]; + // cppcheck-suppress unusedStructMember + unsigned char m_application_data[512]; + // cppcheck-suppress unusedStructMember + unsigned char m_unused5[653]; +} iso9660_desc_t; + +typedef struct iso9660_path_ +{ + unsigned char m_name_len[2]; + unsigned char m_extent[4]; + unsigned char m_parent[2]; + unsigned char m_name[]; +} iso9660_path_t; + +typedef struct iso9660_dirent_ +{ + unsigned char m_length[1]; + unsigned char m_ext_attr_length[1]; + unsigned char m_extent[8]; + unsigned char m_size[8]; + unsigned char m_date[7]; + unsigned char m_flags[1]; + unsigned char m_file_unit_size[1]; + unsigned char m_interleave[1]; + unsigned char m_volume_sequence_number[4]; + unsigned char m_name_len[1]; + unsigned char m_name[]; +} iso9660_dirent_t; + +static int cdrom_init(iop_device_t *dev); +void cdvdman_termcall(int with_stop); +static int cdrom_deinit(); +static int cdrom_dopen(iop_file_t *f, const char *dirname); +static int cdrom_getstat(iop_file_t *f, const char *name, iox_stat_t *buf); +static int cdrom_dread(iop_file_t *f, iox_dirent_t *buf); +static int cdrom_open(iop_file_t *f, const char *name, int mode, int arg4); +static int cdrom_close(iop_file_t *f); +static int cdrom_read(iop_file_t *f, void *buf, int nbytes); +static int cdrom_ioctl(iop_file_t *f, int arg, void *param); +static int cdrom_ioctl2(iop_file_t *f, int request, void *argp, size_t arglen, void *bufp, size_t buflen); +static int +cdrom_devctl(iop_file_t *f, const char *, int cmd, void *argp, unsigned int arglen, void *bufp, unsigned int buflen); +static int cdrom_lseek(iop_file_t *f, int offset, int pos); +static int cdrom_nulldev(); +static s64 cdrom_nulldev64(); +static int CdSearchFileInner(cdvdman_filetbl_entry_t *fp, const char *name, int layer); +static int sceCdSearchDir(char *dirname, int layer); +static int sceCdReadDir(sceCdlFILE *fp, int dsec, int index, int layer); +static int cdvdman_cmpname(const char *p, const char *q); +static int CD_newmedia(int arg); +static int cdvdman_finddir(int target_parent, const char *target_name); +static int CD_cachefile(int dsec, int layer); +static int disc_read(int size, int loc, void *buffer, int layer); +static int path_tbl_init(u32 blocks, char *fname, int action); +unsigned int optimized_memcpy(char *dst, const char *src, unsigned int n); +static int vSetAlarm(iop_sys_clock_t *sys_clock, unsigned int (*alarm_cb)(void *), void *arg); +static int vCancelAlarm(unsigned int (*alarm_cb)(void *), void *arg); +static int vSetEventFlag(int ef, u32 bits); +static int vDelayThread(int usec); +static int DvdDual_infochk(); +static void cdvdman_init(); +static void cdvdman_write_scmd(cdvdman_internal_struct_t *s); +static int intrh_dma_3(cdvdman_internal_struct_t *s); +static int cdvdman_mediactl(int code); +static int cdvdman_ncmd_sender_06(); +static int cdvdman_gettoc(u8 *toc); +static int cdvdman_isdvd(); +static int sceCdRead0_Rty(u32 lsn, u32 nsec, void *buf, const sceCdRMode *mode, int ncmd, int dintrsec, void *func); +static int cdvdman_syncdec(int decflag, int decxor, int shift, u32 data); +static void Read2intrCDVD(int read2_flag); +static int sceCdGetMVersion(u8 *buffer, u32 *status); +static int cdvdman_scmd_sender_03_48(u8 *buf, u32 *status); +static int cdvdman_scmd_sender_3B(int arg1); +#ifdef CDVD_VARIANT_DNAS +static int cdvdman_ncmd_sender_0C(int arg1, u32 arg2, u32 arg3); +#endif + +static char g_cdvdman_cache_name[256] = "host0:"; +static int g_cdvdman_cache_sector_size_count = 1; +static int g_cdvdman_srchspd = 0; +static int g_cdvdman_spinctl = -1; +static int g_cdvdman_spinnom = -1; +static int g_cdvdman_trycnt = -1; +static int g_cdvdman_iocache = 0; +static unsigned int g_cdvdman_lcn_offset = 0; +static unsigned int g_cdvdman_numbytes_offset = 0; +static int g_cdvdman_strmerr = 0; +static iop_device_ops_t g_cdvdman_cddev_ops = { + &cdrom_init, + &cdrom_deinit, + (void *)&cdrom_nulldev, + &cdrom_open, + &cdrom_close, + &cdrom_read, + (void *)&cdrom_nulldev, + &cdrom_lseek, + &cdrom_ioctl, + (void *)&cdrom_nulldev, + (void *)&cdrom_nulldev, + (void *)&cdrom_nulldev, + &cdrom_dopen, + &cdrom_close, + &cdrom_dread, + &cdrom_getstat, + (void *)&cdrom_nulldev, + (void *)&cdrom_nulldev, + (void *)&cdrom_nulldev, + (void *)&cdrom_nulldev, + (void *)&cdrom_nulldev, + (void *)&cdrom_nulldev, + (void *)&cdrom_nulldev64, + &cdrom_devctl, + (void *)&cdrom_nulldev, + (void *)&cdrom_nulldev, + &cdrom_ioctl2, +}; +static iop_device_t g_cdvdman_cddev = {"cdrom", IOP_DT_FSEXT | IOP_DT_FS, 1, "CD-ROM ", &g_cdvdman_cddev_ops}; +static int g_cdvdman_sync_timeout = 15000; +static int g_cdvdman_stream_timeout = 5000; +#ifdef CDVD_VARIANT_DNAS +static iop_sys_clock_t g_readid_systemtime = {0, 0}; +#endif +static int g_verbose_level = 0; +static cdvdman_pathtbl_t *g_cdvdman_pathtbl = NULL; +static unsigned int g_cache_count = 0; +static unsigned int g_cache_table = 0; +static unsigned int g_cdvdman_pathtblsize = 0; +static int g_cache_path_size = 0; +static int g_cache_path_fd = -1; +static int g_cdvdman_fs_cdsec = 0; +static int g_cdvdman_fs_layer = -1; +static int g_cdvdman_fs_cache = 0; +static int g_cdvdman_fs_base2 = 0; +static int g_cdvdman_clk_flg = 0; +static int g_cdvdman_cd36key = 0; +static int g_cdvdman_ee_rpc_fno = 0; +static int g_cdvdman_mmode = 0; +static int g_cdvdman_last_cmdfunc = 0; +static int g_cdvdman_minver_10700 = 0; +static int g_cdvdman_minver_20200 = 0; +static int g_cdvdman_minver_20400 = 0; +static int g_cdvdman_minver_20800 = 0; +static int g_cdvdman_emudvd9 = 0; +static int g_cdvdman_minver_50000 = 0; +static int g_cdvdman_minver_50200 = 0; +static int g_cdvdman_minver_50400 = 0; +static int g_cdvdman_minver_50600 = 0; +static int g_cdvdman_minver_60000 = 0; +static int g_cdvdman_minver_60200 = 0; +static int g_cdvdman_minver_x_model_15 = 0; +static char *g_masterdisc_header = "PlayStation Master Disc"; +static char g_cdvdman_ncmd = 6; +static int g_cdvdman_chmedia = 0; +static int g_cdvdman_chflags[4] = {1, 1, 1, 1}; +static int g_cdvdman_rtindex = 0; +static int g_cdvdman_retries = 0; +static u8 *g_cdvdman_ptoc; +static int g_scmd_evid; +static void *g_cdvdman_temp_buffer_ptr; +static int g_sfile_evid; +static int g_ncmd_evid; +static int g_fio_fsv_evid; +static int g_cdvdman_intr_efid; +static sceCdCBFunc g_cdvdman_user_cb; +static void *g_cdvdman_poffarg; +static void (*g_cdvdman_cdstm0cb)(int); +static sceCdCLOCK g_cdvdman_clock; +static void (*g_cdvdman_poff_cb)(void *userdata); +static void (*g_cdvdman_cdstm1cb)(int); +static int g_cdvdman_cmdfunc; +static cdvdman_fhinfo_t g_cdvdman_fhinfo[16]; +static char g_cdvdman_sfname[1024]; +static cdvdman_filetbl_entry_t g_cdvdman_filetbl[64]; +static cdvdman_dirtbl_entry_t g_cdvdman_dirtbl[128]; +static int g_cdvdman_pathtblflag; +static char g_cdvdman_fs_rbuf[2048]; +static int g_cdvdman_readptr; +static iop_sys_clock_t g_cdvdman_read_alarm_cb_timeout; +static iop_sys_clock_t g_cdvdman_ncmd_timeout; +static void *g_cdvdman_readbuf; +static iop_sys_clock_t g_cdvdman_power_off_timeout; +static char g_cdvdman_fsvrbuf[42128]; +static cdvdman_internal_struct_t g_cdvdman_istruct; + +int _start(int ac, char **av) +{ + (void)ac; + (void)av; + + if ( RegisterLibraryEntries(&_exp_cdvdman) ) + { + return MODULE_NO_RESIDENT_END; + } + DelDrv(g_cdvdman_cddev.name); + if ( AddDrv(&g_cdvdman_cddev) ) + { + cdrom_deinit(); + return MODULE_NO_RESIDENT_END; + } + g_cdvdman_ptoc = (u8 *)&g_cdvdman_fsvrbuf[0x924]; + g_cdvdman_temp_buffer_ptr = g_cdvdman_fsvrbuf; + cdvdman_init(); +#if 0 + SetRebootTimeLibraryHandlingMode(&_exp_cdvdman, 2); +#else + // Call termination before disabling interrupts + _exp_cdvdman.mode &= ~6; + _exp_cdvdman.mode |= 2; +#endif + return MODULE_RESIDENT_END; +} + +void *sceGetFsvRbuf(void) +{ + return g_cdvdman_fsvrbuf; +} + +static int cdrom_init(iop_device_t *dev) +{ + unsigned int i; + iop_event_t event; + int scres_unused; + + (void)dev; + + PRINTF("cdvdman Init\n"); + g_cdvdman_istruct.m_wait_flag = 1; + g_cdvdman_istruct.m_scmd_flag = 1; + g_cdvdman_istruct.m_read2_flag = 0; + g_cdvdman_istruct.m_stream_flag = 0; + g_cdvdman_istruct.m_last_error = 0; + g_cdvdman_istruct.m_layer_1_lsn = 0; + g_cdvdman_istruct.m_use_toc = 0; + g_cdvdman_istruct.m_last_read_timeout = 0; + g_cdvdman_istruct.m_power_flag = 0; + g_cdvdman_istruct.m_current_dvd = 0; + g_cdvdman_istruct.m_dual_layer_emulation = 0; + g_cdvdman_istruct.m_dec_state = 0; + g_cdvdman_istruct.m_check_version = 0; + g_cdvdman_istruct.m_dec_shift = 0; + g_cdvdman_istruct.m_opo_or_para = -1; + g_cdvdman_istruct.m_no_dec_flag = 0; + g_cdvdman_istruct.m_cd_inited = 0; + g_cdvdman_istruct.m_tray_is_open = 0; + g_cdvdman_ee_rpc_fno = 0; + g_cdvdman_spinctl = -1; + event.attr = EA_MULTI; + event.bits = 0; + event.option = 0; + g_cdvdman_intr_efid = CreateEventFlag(&event); + g_scmd_evid = CreateEventFlag(&event); + g_ncmd_evid = CreateEventFlag(&event); + g_sfile_evid = CreateEventFlag(&event); + g_fio_fsv_evid = CreateEventFlag(&event); + ClearEventFlag(g_cdvdman_intr_efid, ~0x4); + ClearEventFlag(g_cdvdman_intr_efid, ~0x10); + SetEventFlag(g_cdvdman_intr_efid, 0x29); + SetEventFlag(g_ncmd_evid, 1); + SetEventFlag(g_scmd_evid, 1); + SetEventFlag(g_sfile_evid, 1); + SetEventFlag(g_fio_fsv_evid, 1); + g_cdvdman_spinnom = -1; + g_cdvdman_trycnt = -1; + sceCdSC(0xFFFFFFF3, &scres_unused); + for ( i = 0; i < (sizeof(g_cdvdman_fhinfo) / sizeof(g_cdvdman_fhinfo[0])); i += 1 ) + { + g_cdvdman_fhinfo[i].m_fd_flags = 0; + } + return 0; +} + +void cdvdman_termcall(int with_stop) +{ + int i; + int oldstate; + USE_DEV5_MMIO_HWPORT(); + + VERBOSE_KPRINTF(1, "CDVD:library Terminate Call %d\n", with_stop); + if ( with_stop ) + { + return; + } + sceCdBreak(); + sceCdSync(0); + if ( g_cdvdman_istruct.m_cd_inited ) + { + cdvdman_ncmd_sender_06(); + } + for ( i = 0; i < 50000; i += 1 ) + { + if ( !(dev5_mmio_hwport->m_dev5_reg_017 & 0x80) ) + { + break; + } + DelayThread(100); + } + sceCdDecSet(0, 0, 0); + if ( (dmac_ch_get_chcr(3) & 0x1000000) ) + { + dev5_mmio_hwport->m_dev5_reg_007 = 1; + } + dmac_ch_set_chcr(3, 0); + DisableIntr(IOP_IRQ_DMA_CDVD, &oldstate); + ReleaseIntrHandler(IOP_IRQ_DMA_CDVD); + DisableIntr(IOP_IRQ_CDVD, &oldstate); + ReleaseIntrHandler(IOP_IRQ_CDVD); +} + +static int cdrom_deinit() +{ + unsigned int i; + + for ( i = 0; i < (sizeof(g_cdvdman_fhinfo) / sizeof(g_cdvdman_fhinfo[0])); i += 1 ) + { + g_cdvdman_fhinfo[i].m_fd_flags = 0; + } + DeleteEventFlag(g_fio_fsv_evid); + DeleteEventFlag(g_cdvdman_intr_efid); + DeleteEventFlag(g_ncmd_evid); + DeleteEventFlag(g_scmd_evid); + DeleteEventFlag(g_sfile_evid); + return 0; +} + +static int cdvdman_devready() +{ + int i; + USE_DEV5_MMIO_HWPORT(); + + for ( i = 0; i < 100; i += 1 ) + { + if ( (dev5_mmio_hwport->m_dev5_reg_00A & 1) ) + { + g_cdvdman_iocache = 0; + return -EIO; + } + if ( (dev5_mmio_hwport->m_dev5_reg_005 & 0xC0) == 0x40 && !g_cdvdman_istruct.m_read2_flag && !g_cdvdman_ee_rpc_fno ) + { + return 1; + } + DelayThread(10000); + } + return -EBUSY; +} + +static int cdvdman_l0check(int layer) +{ + return !layer + && (g_cdvdman_istruct.m_dual_layer_emulation || g_cdvdman_istruct.m_opo_or_para == 1 || g_cdvdman_istruct.m_opo_or_para == 2); +} + +static void cdvdman_iormode(sceCdRMode *rmode, int fmode, int layer) +{ + rmode->datapattern = SCECdSecS2048; + rmode->trycount = (g_cdvdman_trycnt == -1) ? 16 : g_cdvdman_trycnt; + if ( cdvdman_l0check(layer) ) + { + if ( g_cdvdman_spinnom == -1 ) + { + rmode->spindlctrl = (fmode == SCECdSpinX1 || fmode == SCECdSpinMx) ? fmode : SCECdSpinStm; + return; + } + if ( fmode != SCECdSpinX1 && fmode != SCECdSpinMx ) + { + rmode->spindlctrl = SCECdSpinStm; + return; + } + } + else if ( g_cdvdman_spinnom == -1 ) + { + switch ( fmode ) + { + case SCECdSpinStm: + rmode->spindlctrl = SCECdSpinStm; + break; + case SCECdSpinNom: + rmode->spindlctrl = SCECdSpinNom; + break; + case SCECdSpinX1: + rmode->spindlctrl = SCECdSpinX1; + break; + case SCECdSpinX2: + rmode->spindlctrl = SCECdSpinX2; + break; + case SCECdSpinX4: + rmode->spindlctrl = SCECdSpinX4; + break; + case SCECdSpinX12: + rmode->spindlctrl = SCECdSpinX12; + break; + case SCECdSpinMx: + rmode->spindlctrl = SCECdSpinMx; + break; + default: + rmode->spindlctrl = SCECdSpinNom; + break; + } + return; + } + rmode->spindlctrl = (u8)g_cdvdman_spinnom; +} + +static int cdrom_dopen(iop_file_t *f, const char *dirname) +{ + unsigned int i; + int is_devready; + size_t path_name_ind; + int file_lsn_tmp; + char path_name[128]; + u32 efbits; + + VERBOSE_PRINTF(1, "fileIO DOPEN name= %s layer %d\n", dirname, f->unit); + WaitEventFlag(g_fio_fsv_evid, 1, WEF_AND | WEF_CLEAR, &efbits); + for ( i = 0; (i < (sizeof(g_cdvdman_fhinfo) / sizeof(g_cdvdman_fhinfo[0]))) && g_cdvdman_fhinfo[i].m_fd_flags; + i += 1 ) + { + } + if ( i == (sizeof(g_cdvdman_fhinfo) / sizeof(g_cdvdman_fhinfo[0])) ) + { + SetEventFlag(g_fio_fsv_evid, 1); + return -EMFILE; + } + f->privdata = (void *)i; + is_devready = cdvdman_devready(); + if ( is_devready < 0 ) + { + SetEventFlag(g_fio_fsv_evid, 1); + return is_devready; + } + strncpy(path_name, dirname, sizeof(path_name)); + if ( !strcmp(path_name, ".") ) + { + strcpy(path_name, "\\."); + } + path_name_ind = strlen(path_name); + path_name_ind -= (path_name_ind >= 2) ? 2 : 0; + if ( strcmp(&path_name[path_name_ind], "\\.") ) + { + strcat(path_name, "\\."); + } + if ( (unsigned int)(f->unit) >= 2 ) + { + PRINTF("open fail name %s\n", path_name); + SetEventFlag(g_fio_fsv_evid, 1); + return -ENOENT; + } + g_cdvdman_fhinfo[i].m_file_lsn = 0; + g_cdvdman_srchspd = 0; + file_lsn_tmp = sceCdSearchDir(path_name, f->unit); + if ( file_lsn_tmp < 0 ) + { + PRINTF("open fail directory %s\n", path_name); + SetEventFlag(g_fio_fsv_evid, 1); + return -ENOENT; + } + g_cdvdman_fhinfo[i].m_file_lsn = file_lsn_tmp; + g_cdvdman_fhinfo[i].m_read_pos = 0; + g_cdvdman_fhinfo[i].m_filemode = 0; + g_cdvdman_fhinfo[i].m_fd_flags = 1; + g_cdvdman_fhinfo[i].m_fd_layer = f->unit; + SetEventFlag(g_fio_fsv_evid, 1); + return 0; +} + +static void cdvdman_fillstat(void *dummy, iox_stat_t *buf, cdvdman_filetbl_entry_t *fp) +{ + unsigned int i; + + (void)dummy; + + buf->attr = 0; + buf->private_5 = 0; + buf->private_4 = 0; + buf->private_3 = 0; + buf->private_2 = 0; + buf->private_1 = 0; + buf->private_0 = 0; + buf->hisize = 0; + for ( i = 0; i < (sizeof(buf->mtime) / sizeof(buf->mtime[0])); i += 1 ) + { + buf->mtime[i] = fp->m_file_struct.date[i]; + buf->atime[i] = fp->m_file_struct.date[i]; + buf->ctime[i] = fp->m_file_struct.date[i]; + } + buf->size = fp->m_file_struct.size; + buf->mode = (((fp->m_flags & 2)) ? (FIO_S_IFDIR | FIO_S_IXUSR | FIO_S_IXGRP | FIO_S_IXOTH) : FIO_S_IFREG) + | (FIO_S_IRUSR | FIO_S_IRGRP | FIO_S_IROTH); +} + +static int cdvdman_cdfname(char *filename) +{ + size_t filename_len; + + filename_len = strlen(filename); + if ( filename_len >= 3 && !(filename[filename_len - 2] != ';' && filename[filename_len - 1] != '1') ) + { + return 0; + } + strcat(filename, ";1"); + return 1; +} + +static int cdrom_getstat(iop_file_t *f, const char *name, iox_stat_t *buf) +{ + int devready_tmp; + cdvdman_filetbl_entry_t fp; + char filename[128]; + u32 efbits; + + VERBOSE_PRINTF(1, "fileIO GETSTAT name= %s layer= %d\n", name, f->unit); + WaitEventFlag(g_fio_fsv_evid, 1, WEF_AND | WEF_CLEAR, &efbits); + devready_tmp = cdvdman_devready(); + if ( devready_tmp < 0 ) + { + SetEventFlag(g_fio_fsv_evid, 1); + return devready_tmp; + } + strncpy(filename, name, sizeof(filename)); + if ( !strcmp(filename, ".") ) + { + strcpy(filename, "\\."); + } + if ( !strcmp(filename, "\\") ) + { + strcpy(filename, "\\."); + } + if ( !strlen(filename) ) + { + strcpy(filename, "\\."); + } + g_cdvdman_srchspd = 0; + // Unofficial: initialize to 0 + memset(&fp, 0, sizeof(fp)); + if ( + !sceCdLayerSearchFile(&fp.m_file_struct, filename, f->unit) + && !(cdvdman_cdfname(filename) && sceCdLayerSearchFile(&fp.m_file_struct, filename, f->unit)) ) + { + PRINTF("open fail name %s\n", name); + SetEventFlag(g_fio_fsv_evid, 1); + return -ENOENT; + } + cdvdman_fillstat(filename, buf, &fp); + SetEventFlag(g_fio_fsv_evid, 1); + return 1; +} + +static int cdrom_dread(iop_file_t *f, iox_dirent_t *buf) +{ + int devready_tmp; + cdvdman_fhinfo_t *fh; + cdvdman_filetbl_entry_t fp; + u32 efbits; + + memset(&fp, 0, sizeof(fp)); + VERBOSE_PRINTF(1, "fileIO DREAD\n"); + WaitEventFlag(g_fio_fsv_evid, 1, WEF_AND | WEF_CLEAR, &efbits); + devready_tmp = cdvdman_devready(); + if ( devready_tmp < 0 ) + { + SetEventFlag(g_fio_fsv_evid, 1); + return devready_tmp; + } + fh = &g_cdvdman_fhinfo[(int)f->privdata]; + g_cdvdman_srchspd = 0; + devready_tmp = sceCdReadDir(&fp.m_file_struct, fh->m_file_lsn, fh->m_read_pos, fh->m_fd_layer); + if ( devready_tmp < 0 ) + { + SetEventFlag(g_fio_fsv_evid, 1); + return -ENOENT; + } + if ( devready_tmp ) + { + fh->m_read_pos += 1; + devready_tmp = strlen(fp.m_file_struct.name); + } + strncpy(buf->name, fp.m_file_struct.name, sizeof(buf->name)); + cdvdman_fillstat(fp.m_file_struct.name, &buf->stat, &fp); + SetEventFlag(g_fio_fsv_evid, 1); + return devready_tmp; +} + +static int cdvd_odcinit(cdvdman_fhinfo_t *fh, int open_or_close, int id) +{ + int cache_remove_result; + int cache_result; + int cache_file_fd_new; + u32 file_size_bsr_3; + unsigned int file_size_bsr_17; + char cache_filename[512]; + int state; + unsigned int ioctl_arg; + + g_cdvdman_iocache = 0; + sprintf( + cache_filename, + "%sCache_%d_%d_%d_%d", + g_cdvdman_cache_name, + fh->m_fd_layer, + (int)fh->m_file_lsn, + (int)fh->m_file_size, + id); + cache_remove_result = 0; + VERBOSE_KPRINTF(1, "Cachefile:%s Open_or_Close:%d\n", cache_filename, open_or_close); + cache_result = 0; + if ( open_or_close ) + { + u32 i; + + CpuSuspendIntr(&state); + fh->m_fd_rbsize = g_cdvdman_cache_sector_size_count ? (g_cdvdman_cache_sector_size_count << 11) : 0x800; + fh->m_fd_rcvbuf = (u8 *)AllocSysMemory(ALLOC_LAST, fh->m_fd_rbsize, 0); + if ( !fh->m_fd_rcvbuf ) + { + VERBOSE_KPRINTF(1, "Rcvbuf MemAlloc Fail\n"); + CpuResumeIntr(state); + return -ENOMEM; + } + CpuResumeIntr(state); + fh->m_cache_file_fd = -1; + cache_result = open(cache_filename, O_TRUNC | O_CREAT | O_RDWR, 0x1ff /* 0o777 */); + cache_file_fd_new = cache_result; + if ( cache_result >= 0 ) + { + u32 file_size_sectors; + unsigned int file_size_bsr_6; + + file_size_sectors = (fh->m_file_size >> 11) + ((!!((fh->m_file_size & 0x7FF)))); + file_size_bsr_3 = (file_size_sectors >> 3) + (!!(file_size_sectors & 7)); + file_size_bsr_6 = (file_size_bsr_3 >> 3) + (!!((file_size_bsr_3 & 7))); + file_size_bsr_17 = (file_size_bsr_6 >> 11) + (!!((file_size_bsr_6 & 0x7FF))); + ioctl_arg = (file_size_bsr_17 + file_size_sectors + 8) << 11; + for ( i = 0; i < fh->m_fd_rbsize; i += 1 ) + { + fh->m_fd_rcvbuf[i] = 0; + } + if ( !strncmp(cache_filename, "pfs", 3) ) + { + cache_result = ioctl2(cache_file_fd_new, PIOCALLOC, &ioctl_arg, 4, 0, 0); + } + } + if ( cache_result >= 0 ) + { + cache_result = lseek(cache_file_fd_new, 0, 0); + } + if ( cache_result >= 0 ) + { + for ( i = 0; i <= 0x7FFF; i += 1 ) + { + ((char *)g_cdvdman_temp_buffer_ptr)[i] = 0; + } + for ( i = 0; (int)i < (int)(ioctl_arg >> 15); i += 1 ) + { + cache_result = write(cache_file_fd_new, g_cdvdman_temp_buffer_ptr, 0x8000); + if ( cache_result != 0x8000 ) + { + if ( cache_result >= 0 ) + { + cache_result = -EIO; + } + break; + } + } + } + if ( cache_result >= 0 ) + { + for ( i = 0; (int)i < (int)((ioctl_arg >> 11) - 0x10 * (ioctl_arg >> 15)); i += 1 ) + { + cache_result = write(cache_file_fd_new, fh->m_fd_rcvbuf, 0x800); + if ( cache_result != 0x800 ) + { + if ( cache_result >= 0 ) + { + cache_result = -EIO; + } + break; + } + } + } + } + if ( !open_or_close || cache_result < 0 ) + { + if ( fh->m_cache_file_fd != -1 ) + { + cache_remove_result = close(fh->m_cache_file_fd); + VERBOSE_KPRINTF(1, "Cache File Close: %d\n", cache_remove_result); + if ( cache_remove_result >= 0 ) + { + if ( !strncmp(cache_filename, "pfs", 3) ) + { + cache_remove_result = remove(cache_filename); + } + else if ( !strncmp(cache_filename, "host", 4) ) + { + cache_remove_result = 0; + remove(cache_filename); + } + VERBOSE_KPRINTF(1, "Cache File %s remove: %d\n", cache_filename, cache_remove_result); + } + } + fh->m_cache_file_fd = -1; + fh->m_max_cluster = 0; + fh->m_cluster_cur = -1; + fh->m_sector_count_total = 0; + CpuSuspendIntr(&state); + FreeSysMemory(fh->m_fd_rcvbuf); + CpuResumeIntr(state); + fh->m_fd_rcvbuf = 0; + if ( cache_result < 0 ) + { + VERBOSE_KPRINTF(1, "cdvd_odcinit Open Error %d\n", cache_result); + } + if ( cache_remove_result < 0 ) + { + VERBOSE_KPRINTF(1, "cdvd_odcinit Close Error %d\n", cache_remove_result); + } + return (!open_or_close) ? cache_remove_result : cache_result; + } + fh->m_sector_count_total = file_size_bsr_17 << 11; + fh->m_cache_file_fd = cache_file_fd_new; + fh->m_max_cluster = (void *)file_size_bsr_3; + fh->m_cluster_cur = -1; + VERBOSE_KPRINTF(1, "Cache File Maked\n"); + return 0; +} + +static int cdvdman_cache_invalidate(cdvdman_fhinfo_t *fh, int index) +{ + u32 i; + int fileio_res; + + if ( fh->m_cluster_cur == -1 ) + { + return 0; + } + fh->m_cluster_cur = -1; + for ( i = 0; i < fh->m_fd_rbsize; i += 1 ) + { + fh->m_fd_rcvbuf[i] = 0; + } + fileio_res = lseek(fh->m_cache_file_fd, 0, 0); + if ( fileio_res >= 0 ) + { + for ( i = 0; i < ((unsigned int)fh->m_sector_count_total >> 11); i += 1 ) + { + fileio_res = write(fh->m_cache_file_fd, fh->m_fd_rcvbuf, 0x800); + if ( fileio_res < 0 ) + { + break; + } + } + } + if ( fileio_res >= 0 ) + { + return fileio_res; + } + fh->m_fd_flags &= ~4; + cdvd_odcinit(fh, 0, index); + return fileio_res; +} + +static int cdvdman_invcaches() +{ + unsigned int i; + + for ( i = 0; i < (sizeof(g_cdvdman_fhinfo) / sizeof(g_cdvdman_fhinfo[0])); i += 1 ) + { + if ( (g_cdvdman_fhinfo[i].m_fd_flags & 4) ) + { + cdvdman_cache_invalidate(&g_cdvdman_fhinfo[i], i); + } + } + return 0; +} + +static int cdrom_internal_cache_read(const iop_file_t *f, int nbytes) +{ + cdvdman_fhinfo_t *fh; + s16 readpos_plus_nbytes; + unsigned int readpos_plus_nbytes_bsr_14; + int readpos_bsr_14; + int cluster_cur; + unsigned int i; + + fh = &g_cdvdman_fhinfo[(int)f->privdata]; + if ( cdvdman_devready() < 0 ) + { + g_cdvdman_iocache = 0; + return -EBUSY; + } + if ( fh->m_cluster_cur == -1 ) + { + if ( (void *)(8 * fh->m_fd_rbsize) < fh->m_max_cluster ) + { + fh->m_cluster_cur = (fh->m_read_pos >> 14) & ~0x7; + if ( + lseek(fh->m_cache_file_fd, fh->m_cluster_cur >> 3, 0) < 0 + || read(fh->m_cache_file_fd, fh->m_fd_rcvbuf, fh->m_fd_rbsize) < 0 ) + { + fh->m_cluster_cur = -1; + return -EIO; + } + } + else + { + fh->m_cluster_cur = -2; + } + } + readpos_plus_nbytes = fh->m_read_pos + nbytes; + readpos_plus_nbytes_bsr_14 = (readpos_plus_nbytes >> 14) - (!(readpos_plus_nbytes & 0x3FFF)); + readpos_bsr_14 = fh->m_read_pos >> 14; + VERBOSE_KPRINTF( + 1, "max_claster %d meta_size_clst %d claster_cur %d\n", fh->m_max_cluster, 8 * fh->m_fd_rbsize, fh->m_cluster_cur); + cluster_cur = fh->m_cluster_cur; + if ( cluster_cur < 0 ) + { + cluster_cur = 0; + } + else if ( + (unsigned int)readpos_bsr_14 < (unsigned int)cluster_cur + || readpos_plus_nbytes_bsr_14 >= cluster_cur + 8 * fh->m_fd_rbsize ) + { + int cluster_write_tmp2; + unsigned int readpos_band; + + if ( lseek(fh->m_cache_file_fd, cluster_cur >> 3, 0) < 0 ) + { + fh->m_cluster_cur = -1; + return -EIO; + } + cluster_write_tmp2 = (unsigned int)fh->m_max_cluster >= fh->m_cluster_cur + 8 * fh->m_fd_rbsize ? + fh->m_fd_rbsize : + ((unsigned int)fh->m_max_cluster - fh->m_cluster_cur + 7) >> 3; + if ( write(fh->m_cache_file_fd, fh->m_fd_rcvbuf, cluster_write_tmp2) != cluster_write_tmp2 ) + { + fh->m_cluster_cur = -1; + return -EIO; + } + readpos_band = readpos_bsr_14 & ~0x7; + fh->m_cluster_cur = readpos_band; + readpos_band += (readpos_bsr_14 < 0) ? 7 : 0; + if ( (lseek(fh->m_cache_file_fd, readpos_band >> 3, 0) < 0) || (read(fh->m_cache_file_fd, fh->m_fd_rcvbuf, ( (unsigned int)fh->m_max_cluster < fh->m_cluster_cur + 8 * fh->m_fd_rbsize ) ? (((unsigned int)fh->m_max_cluster - fh->m_cluster_cur + 7) >> 3) : (fh->m_fd_rbsize)) < 0) ) + { + fh->m_cluster_cur = -1; + return -EIO; + } + cluster_cur = fh->m_cluster_cur; + } + for ( i = readpos_bsr_14; i <= readpos_plus_nbytes_bsr_14; i += 1 ) + { + if ( !(((int)fh->m_fd_rcvbuf[(i - cluster_cur) >> 3] >> ((i - cluster_cur) & 7)) & 1) ) + { + break; + } + } + return i <= readpos_plus_nbytes_bsr_14; +} + +static int cdrom_internal_write_cache(const iop_file_t *f, unsigned int nbytes) +{ + int lseek_result; + cdvdman_fhinfo_t *fh; + unsigned int cur; + unsigned int rst; + int cluster_cur; + int write_ret; + unsigned int i; + int tray_open; + int Error; + sceCdRMode rmode; + + g_cdvdman_iocache = 0; + if ( cdvdman_devready() < 0 ) + { + return -EBUSY; + } + fh = &g_cdvdman_fhinfo[(int)f->privdata]; + if ( nbytes > fh->m_file_size - fh->m_read_pos ) + { + nbytes = fh->m_file_size - fh->m_read_pos; + } + if ( !nbytes ) + { + return 0; + } + VERBOSE_KPRINTF(1, "_cdvdfile_cache_read %d<->%d\n", fh->m_read_pos, fh->m_read_pos + nbytes); + cur = ((fh->m_read_pos + nbytes) >> 14) - (!((fh->m_read_pos + nbytes) & 0x3FFF)); + rst = fh->m_read_pos >> 14; + cluster_cur = (fh->m_cluster_cur >= 0) ? fh->m_cluster_cur : 0; + cdvdman_iormode(&rmode, fh->m_filemode, f->unit); + write_ret = 0; + VERBOSE_KPRINTF(1, "cache_fill rst:%d<->%d cur:%d cnt:%d\n", rst, cur, fh->m_read_pos, nbytes); + for ( i = rst; i <= cur; i += 1 ) + { + VERBOSE_KPRINTF( + 1, + "FIO Usr addr LSN:%d SEC:%d ADDR:%08x cpos= %d\n", + fh->m_file_lsn + 8 * i, + 8, + g_cdvdman_temp_buffer_ptr, + (i * 0x4000) + fh->m_sector_count_total); + if ( !(((int)fh->m_fd_rcvbuf[(i - cluster_cur) >> 3] >> ((i - cluster_cur) & 7)) & 1) ) + { + tray_open = 0; + while ( !sceCdRE(fh->m_file_lsn + 8 * i, 8u, g_cdvdman_temp_buffer_ptr, &rmode) ) + { + if ( (sceCdStatus() & SCECdStatShellOpen) ) + { + g_cdvdman_iocache = 0; + tray_open = 1; + break; + } + DelayThread(10000); + } + sceCdSync(0); + Error = sceCdGetError(); + if ( Error || tray_open ) + { + VERBOSE_KPRINTF(0, "Read Error= 0x%02x\n", Error); + return -ECOMM; + } + lseek_result = lseek(fh->m_cache_file_fd, (i * 0x4000) + fh->m_sector_count_total, 0); + if ( lseek_result < 0 ) + { + return lseek_result; + } + write_ret = write(fh->m_cache_file_fd, g_cdvdman_temp_buffer_ptr, 0x4000); + if ( write_ret != 0x4000 ) + { + VERBOSE_KPRINTF(1, "write: ret:%d\n", write_ret); + if ( write_ret >= 0 ) + { + return -EIO; + } + break; + } + fh->m_fd_rcvbuf[(i - cluster_cur) >> 3] |= 1 << ((i - cluster_cur) & 7); + } + } + return write_ret; +} + +static int cdvdfile_cache_read(const iop_file_t *f, void *buf, int nbyte) +{ + int nbyte_tmp; + int fd_result; + cdvdman_fhinfo_t *fh; + + if ( nbyte < 0 ) + { + return -EINVAL; + } + fh = &g_cdvdman_fhinfo[(int)f->privdata]; + nbyte_tmp = + ((unsigned int)nbyte > fh->m_file_size - fh->m_read_pos) ? fh->m_file_size - fh->m_read_pos : (unsigned int)nbyte; + VERBOSE_KPRINTF(1, "_cdvdfile_cache_read %d<->%d\n", fh->m_read_pos, fh->m_read_pos + nbyte_tmp); + fd_result = 0; + if ( nbyte_tmp > 0 ) + { + fd_result = lseek(fh->m_cache_file_fd, fh->m_read_pos + fh->m_sector_count_total, 0); + if ( fd_result >= 0 ) + { + fd_result = read(fh->m_cache_file_fd, buf, nbyte_tmp); + fh->m_read_pos += (fd_result >= 0) ? fd_result : 0; + } + } + return fd_result; +} + +static int cdvdfile_cache_fill_read(const iop_file_t *f, void *buf, int nbytes) +{ + int op_result; + + op_result = cdvdman_devready(); + if ( op_result >= 0 ) + { + op_result = cdrom_internal_write_cache(f, nbytes); + } + else + { + g_cdvdman_iocache = 0; + } + if ( op_result >= 0 ) + { + op_result = cdvdfile_cache_read(f, buf, nbytes); + } + return op_result; +} + +static int cdrom_open(iop_file_t *f, const char *name, int mode, int arg4) +{ + int fds1; + unsigned int i; + int emptyfdfound; + int streamfdfound; + cdvdman_fhinfo_t *fh; + int devready_tmp; + char filename[128]; + sceCdlFILE fp; + u32 efbits; + + (void)arg4; + devready_tmp = 0; + fds1 = 0; + VERBOSE_PRINTF(1, "fileIO OPEN name= %s mode= 0x%08x layer %d\n", name, mode, f->unit); + WaitEventFlag(g_fio_fsv_evid, 1, WEF_AND | WEF_CLEAR, &efbits); + emptyfdfound = 0; + streamfdfound = 0; + for ( i = 0; i < (sizeof(g_cdvdman_fhinfo) / sizeof(g_cdvdman_fhinfo[0])); i += 1 ) + { + if ( !g_cdvdman_fhinfo[i].m_fd_flags && !emptyfdfound ) + { + fds1 = i; + emptyfdfound = 1; + } + if ( (g_cdvdman_fhinfo[i].m_fd_flags & 8) ) + { + streamfdfound = 1; + } + } + if ( !emptyfdfound || streamfdfound ) + { + PRINTF("open fail name %s\n", name); + SetEventFlag(g_fio_fsv_evid, 1); + return -EMFILE; + } + f->privdata = (void *)fds1; + fh = &g_cdvdman_fhinfo[fds1]; + strncpy(filename, name, sizeof(filename)); + cdvdman_cdfname(filename); + g_cdvdman_srchspd = (!(mode & 0x40000000) && !cdvdman_l0check(f->unit)) ? + ((g_cdvdman_spinnom == -1) ? (u16)mode : g_cdvdman_spinnom != SCECdSpinStm) : + 0; + if ( (unsigned int)(f->unit) >= 2u ) + { + devready_tmp = -ENOENT; + } + else + { + if ( !strncmp(name, "sce_cdvd_lsn", 12) ) + { + strncpy(filename, name, sizeof(filename)); + // Unofficial: Avoid out of bounds access + for ( i = 12; i < (sizeof(filename) - 5) && filename[i] && filename[i] != '_'; i += 1 ) + ; + if ( !filename[i] || i >= (sizeof(filename) - 5) ) + { + devready_tmp = -ENOENT; + } + else + { + fp.size = strtol(&filename[i + 5], 0, 10); + filename[i] = 0; + fp.lsn = strtol(&filename[12], 0, 10); + if ( f->unit ) + { + if ( cdvdman_devready() < 0 || !DvdDual_infochk() ) + { + devready_tmp = -ENOENT; + } + else + { + fp.lsn += g_cdvdman_istruct.m_layer_1_lsn; + } + } + } + } + else + { + devready_tmp = cdvdman_devready(); + if ( devready_tmp < 0 ) + { + SetEventFlag(g_fio_fsv_evid, 1); + return devready_tmp; + } + if ( !sceCdLayerSearchFile(&fp, filename, f->unit) ) + { + devready_tmp = -ENOENT; + } + } + } + if ( devready_tmp < 0 ) + { + PRINTF("open fail name %s\n", filename); + SetEventFlag(g_fio_fsv_evid, 1); + return devready_tmp; + } + fh->m_fd_flags = 1; + g_cdvdman_srchspd = 0; + if ( (mode & 0x40000000) ) + { + sceCdRMode rmode; + memset(&rmode, 0, sizeof(rmode)); + rmode.datapattern = SCECdSecS2048; + rmode.spindlctrl = SCECdSpinStm; + rmode.trycount = (g_cdvdman_trycnt != -1) ? g_cdvdman_trycnt : 0; + // The following call to sceCdStStart was inlined + if ( !sceCdStStart(fp.lsn, &rmode) ) + { + fh->m_fd_flags = 0; + SetEventFlag(g_fio_fsv_evid, 1); + return -ENOENT; + } + g_cdvdman_strmerr = 0; + fh->m_fd_flags |= 8; + } + fh->m_file_lsn = fp.lsn; + fh->m_read_pos = 0; + fh->m_filemode = mode & ~0x40000000; + fh->m_file_size = fp.size; + fh->m_fd_layer = f->unit; + if ( (mode & 0x50000000) == 0x10000000 ) + { + devready_tmp = -ENODEV; + if ( g_cache_path_fd != -1 ) + { + devready_tmp = cdvd_odcinit(fh, 1, (int)f->privdata); + if ( devready_tmp >= 0 ) + { + fh->m_fd_flags |= 4; + } + } + } + if ( devready_tmp < 0 ) + { + fh->m_fd_flags = 0; + fh->m_fd_layer = 0; + fh->m_filemode = 0; + fh->m_read_pos = 0; + fh->m_file_size = 0; + fh->m_file_lsn = 0; + SetEventFlag(g_fio_fsv_evid, 1); + return devready_tmp; + } + f->mode = O_RDONLY; + SetEventFlag(g_fio_fsv_evid, 1); + return 0; +} + +static int cdrom_close(iop_file_t *f) +{ + cdvdman_fhinfo_t *fh; + u32 efbits; + + VERBOSE_PRINTF(1, "fileIO CLOSE\n"); + WaitEventFlag(g_fio_fsv_evid, 1, WEF_AND | WEF_CLEAR, &efbits); + fh = &g_cdvdman_fhinfo[(int)f->privdata]; + if ( (fh->m_fd_flags & 8) ) + { + g_cdvdman_strmerr = 0; + // The following call to sceCdStStop was inlined + if ( !sceCdStStop() ) + { + SetEventFlag(g_fio_fsv_evid, 1); + return -EIO; + } + } + if ( ((fh->m_fd_flags & 0xC) == 4 && cdvd_odcinit(fh, 0, (int)f->privdata) < 0) ) + { + SetEventFlag(g_fio_fsv_evid, 1); + return -EIO; + } + fh->m_file_lsn = 0; + fh->m_file_size = 0; + fh->m_read_pos = 0; + fh->m_fd_flags = 0; + fh->m_fd_layer = 0; + fh->m_filemode = 1; + f->mode = 0; + SetEventFlag(g_fio_fsv_evid, 1); + return 0; +} + +static int cdrom_internal_read(const iop_file_t *f, char *addr, int nbytes) +{ + unsigned int sectors; + int op_result; + int nbytes_segment; + int nbytes_div_2048; + unsigned int sec; + int read_error; + unsigned int sectors_count; + int Error; + sceCdRMode rmode; + int i; + unsigned int filesize_bsr_11; + cdvdman_fhinfo_t *fh; + void *buf; + + sectors = 1; + VERBOSE_PRINTF(1, "cdvd fileIO read start\n"); + op_result = cdvdman_devready(); + if ( op_result < 0 ) + { + g_cdvdman_iocache = 0; + return op_result; + } + fh = &g_cdvdman_fhinfo[(uiptr)f->privdata]; + cdvdman_iormode(&rmode, fh->m_filemode, f->unit); + if ( nbytes < 0 ) + { + return -EINVAL; + } + if ( (unsigned int)nbytes > fh->m_file_size - fh->m_read_pos ) + { + nbytes = fh->m_file_size - fh->m_read_pos; + } + filesize_bsr_11 = (fh->m_file_size >> 11) + (!!((fh->m_file_size & 0x7FF))) + fh->m_file_lsn; + VERBOSE_PRINTF( + 1, "fds= %d read file_lbn= %d offset= %d\n", (int)(uiptr)f->privdata, (int)fh->m_file_lsn, (int)fh->m_read_pos); + buf = 0; + for ( i = 0; i < nbytes; i += nbytes_segment ) + { + unsigned int lbn; + int pos_extra; + int lbn_tmp; + int pos_sub_2048; + int nbytes_cur; + + nbytes_cur = nbytes - i; + if ( g_cdvdman_spinctl != -1 ) + { + rmode.spindlctrl = g_cdvdman_spinctl; + switch ( g_cdvdman_spinctl ) + { + case SCECdSpinStm: + fh->m_filemode = 0; + break; + case SCECdSpinNom: + fh->m_filemode = 1; + break; + case SCECdSpinX1: + fh->m_filemode = 2; + break; + case SCECdSpinX2: + fh->m_filemode = 3; + break; + case SCECdSpinX4: + fh->m_filemode = 4; + break; + case SCECdSpinX12: + fh->m_filemode = 5; + break; + default: + fh->m_filemode = 1; + break; + } + } + pos_sub_2048 = 0; + lbn = fh->m_file_lsn + ((fh->m_read_pos + i) >> 11); + lbn_tmp = lbn; + pos_extra = (fh->m_read_pos + i) & 0x7FF; + if ( nbytes_cur <= 0x4000 ) + { + nbytes_segment = nbytes_cur; + nbytes_div_2048 = (nbytes_cur / 0x800) + (!!((nbytes_cur & 0x7FF))); + sectors = nbytes_div_2048 + (!!pos_extra); + } + else + { + nbytes_segment = 0x4000; + if ( buf && ((fh->m_read_pos + i) & 0x7FF) && g_cdvdman_iocache ) + { + lbn += 1; + pos_sub_2048 = 0x800 - pos_extra; + optimized_memcpy( + &addr[i], &((const char *)g_cdvdman_temp_buffer_ptr)[0x800 * (sectors - 1) + pos_extra], 0x800 - pos_extra); + g_cdvdman_iocache = 0; + sectors = 8; + } + else + { + sectors = 8 + (!!(((fh->m_read_pos + i) & 0x7FF))); + } + } + buf = g_cdvdman_temp_buffer_ptr; + if ( (unsigned int)(sectors) > filesize_bsr_11 - lbn ) + { + sectors = filesize_bsr_11 - lbn; + } + VERBOSE_PRINTF(1, "sce_Read LBN= %d sectors= %d\n", (int)lbn, (int)sectors); + if ( + g_cdvdman_iocache && (lbn >= g_cdvdman_lcn_offset) + && (g_cdvdman_lcn_offset + g_cdvdman_numbytes_offset >= lbn + sectors) ) + { + optimized_memcpy(&addr[i], &((char *)buf)[0x800 * (lbn - g_cdvdman_lcn_offset) + pos_extra], nbytes_segment); + } + else if ( ((uiptr)(addr + i) & 3) || pos_extra || (nbytes_segment != 0x4000) ) + { + sec = (sectors >= 8) ? sectors : 8; + if ( sec > filesize_bsr_11 - lbn ) + { + sec = filesize_bsr_11 - lbn; + } + VERBOSE_PRINTF(1, "FIO Cache LSN:%d SEC:%d ADDR:%08x\n", (int)lbn, (int)sec, (unsigned int)(uiptr)buf); + sectors_count = (sec >= 9) ? (sec - 8) : 0; + if ( sectors_count ) + { + while ( !sceCdRE(lbn, sectors_count, buf, &rmode) ) + { + VERBOSE_PRINTF(1, "sce_Read ON Delay\n"); + if ( (sceCdStatus() & SCECdStatShellOpen) ) + { + g_cdvdman_iocache = 0; + g_cdvdman_spinctl = -1; + return -EIO; + } + DelayThread(10000); + } + sceCdSync(0); + Error = sceCdGetError(); + if ( Error ) + { + PRINTF("Read Error= 0x%02x\n", Error); + g_cdvdman_iocache = 0; + break; + } + } + while ( !sceCdRE(lbn + sectors_count, sec - sectors_count, (char *)buf + 0x800 * sectors_count, &rmode) ) + { + VERBOSE_PRINTF(1, "sce_Read ON Delay\n"); + if ( (sceCdStatus() & SCECdStatShellOpen) ) + { + g_cdvdman_iocache = 0; + g_cdvdman_spinctl = -1; + return -EIO; + } + DelayThread(10000); + } + sceCdSync(0); + Error = sceCdGetError(); + if ( Error ) + { + PRINTF("Read Error= 0x%02x\n", Error); + g_cdvdman_iocache = 0; + break; + } + g_cdvdman_lcn_offset = lbn_tmp; + g_cdvdman_numbytes_offset = sec; + g_cdvdman_iocache = 1; + optimized_memcpy( + &addr[pos_sub_2048 + i], + &((const char *)g_cdvdman_temp_buffer_ptr)[!pos_sub_2048 ? pos_extra : 0], + nbytes_segment - pos_sub_2048); + } + else + { + VERBOSE_PRINTF( + 1, "FIO Usr addr LSN:%d SEC:%d ADDR:%08x\n", (int)lbn, (int)sectors, (unsigned int)(uiptr)(addr + i)); + while ( !sceCdRE(lbn, sectors, addr + i, &rmode) ) + { + VERBOSE_PRINTF(1, "sce_Read ON Delay\n"); + if ( (sceCdStatus() & SCECdStatShellOpen) ) + { + g_cdvdman_iocache = 0; + g_cdvdman_spinctl = -1; + return -EIO; + } + DelayThread(10000); + } + sceCdSync(0); + read_error = sceCdGetError(); + g_cdvdman_iocache = 0; + if ( read_error ) + { + PRINTF("Read Error= 0x%02x\n", read_error); + break; + } + } + if ( nbytes_segment <= 0 ) + { + g_cdvdman_spinctl = -1; + return nbytes_segment; + } + } + fh->m_read_pos += i; + VERBOSE_PRINTF(1, "fileIO read ended\n"); + g_cdvdman_spinctl = -1; + return i; +} + +static int cdrom_stream_read(const iop_file_t *f, char *bbuf, int nbytes) +{ + cdvdman_fhinfo_t *fh; + sceCdRMode rmode; + int buf; + + fh = &g_cdvdman_fhinfo[(int)f->privdata]; + g_cdvdman_strmerr = 0; + cdvdman_iormode(&rmode, fh->m_filemode, f->unit); + rmode.spindlctrl = SCECdSpinStm; + rmode.trycount = 0; + // The following sceCdStRead call was inlined + buf = sceCdStRead(nbytes >> 11, (u32 *)bbuf, STMNBLK, (u32 *)&g_cdvdman_strmerr); + fh->m_read_pos += buf << 11; + return buf << 11; +} + +static int cdrom_read(iop_file_t *f, void *buf, int nbytes) +{ + cdvdman_fhinfo_t *fh; + int rc; + u32 efbits; + + if ( nbytes < 0 ) + { + return -EINVAL; + } + WaitEventFlag(g_fio_fsv_evid, 1, WEF_AND | WEF_CLEAR, &efbits); + fh = &g_cdvdman_fhinfo[(int)f->privdata]; + if ( cdvdman_mediactl(2) ) + { + g_cdvdman_iocache = 0; + cdvdman_invcaches(); + } + if ( (fh->m_fd_flags & 8) ) + { + rc = cdrom_stream_read(f, (char *)buf, nbytes); + } + else + { + if ( !(fh->m_fd_flags & 4) ) + { + rc = cdrom_internal_read(f, (char *)buf, nbytes); + } + else + { + rc = cdrom_internal_cache_read(f, nbytes); + if ( rc ) + { + if ( rc != -EBUSY ) + { + if ( rc != 1 ) + { + fh->m_fd_flags &= ~4; + rc = -EIO; + cdvd_odcinit(fh, 0, (int)f->privdata); + } + else + { + rc = cdvdfile_cache_fill_read(f, buf, nbytes); + VERBOSE_KPRINTF(1, "called _cdvdfile_cache_fill_read %d\n", rc); + } + } + } + else + { + rc = cdvdfile_cache_read(f, buf, nbytes); + VERBOSE_KPRINTF(1, "called _cdvdfile_cache_read %d\n", rc); + } + if ( rc == -EBUSY || rc == -ECOMM ) + { + cdvdman_cache_invalidate(fh, (int)f->privdata); + KPRINTF("_cdvdfile_cache Read_err OR Drive_not_ready\n", rc); + } + if ( rc < 0 ) + { + rc = cdrom_internal_read(f, (char *)buf, nbytes); + } + } + } + SetEventFlag(g_fio_fsv_evid, 1); + return rc; +} + +static int cdrom_ioctl(iop_file_t *f, int arg, void *param) +{ + (void)f; + + switch ( arg ) + { + case 0x10000: + g_cdvdman_spinnom = -1; + sceCdSpinCtrlIOP((u32)param); + return 0; + default: + return -EIO; + } +} + +static int cdrom_ioctl2(iop_file_t *f, int request, void *argp, size_t arglen, void *bufp, size_t buflen) +{ + const cdvdman_fhinfo_t *fh; + int retval; + u32 efbits; + + (void)argp; + (void)arglen; + (void)bufp; + (void)buflen; + + WaitEventFlag(g_fio_fsv_evid, 1, WEF_AND | WEF_CLEAR, &efbits); + fh = &g_cdvdman_fhinfo[(int)f->privdata]; + retval = -EIO; + if ( (fh->m_fd_flags & 8) ) + { + switch ( request ) + { + case CIOCSTREAMPAUSE: + // The following call to sceCdStPause was inlined + if ( sceCdStPause() ) + { + retval = 0; + } + break; + case CIOCSTREAMRESUME: + // The following call to sceCdStResume was inlined + if ( sceCdStResume() ) + { + retval = 0; + } + break; + case CIOCSTREAMSTAT: + // The following call to sceCdStStat was inlined + // Unofficial: return 0 instead of negative value + retval = sceCdStStat(); + break; + default: + break; + } + } + SetEventFlag(g_fio_fsv_evid, 1); + return retval; +} + +static int +cdrom_devctl(iop_file_t *f, const char *name, int cmd, void *argp, unsigned int arglen, void *bufp, unsigned int buflen) +{ + unsigned int i; + int retval2; + char *sc_tmp_2; + unsigned int sc_tmp_3; + u32 efbits; + int on_dual_tmp; + int scres_unused; + + (void)f; + (void)name; + (void)buflen; + + retval2 = 0; + if ( cmd != CDIOC_BREAK ) + { + WaitEventFlag(g_fio_fsv_evid, 1, WEF_AND | WEF_CLEAR, &efbits); + } + switch ( cmd ) + { + case CDIOC_READCLOCK: + for ( i = 0; i < 3 && !retval2; i += 1 ) + { + WaitEventFlag(g_scmd_evid, 1, WEF_AND, &efbits); + retval2 = sceCdReadClock((sceCdCLOCK *)bufp); + } + retval2 = (retval2 != 1) ? -EIO : 0; + break; +#ifdef CDVD_VARIANT_DNAS + case 0x431D: + for ( i = 0; i < 3 && !retval2; i += 1 ) + { + WaitEventFlag(g_scmd_evid, 1, WEF_AND, &efbits); + retval2 = sceCdReadGUID((u64 *)bufp); + } + retval2 = (retval2 != 1) ? -EIO : 0; + break; + case 0x431E: + retval2 = (sceCdReadDiskID((unsigned int *)bufp) != 1) ? -EIO : 0; + break; +#endif + case CDIOC_GETDISKTYP: + *(u32 *)bufp = sceCdGetDiskType(); + break; + case CDIOC_GETERROR: + *(u32 *)bufp = g_cdvdman_strmerr ? g_cdvdman_strmerr : sceCdGetError(); + break; + case CDIOC_TRAYREQ: + retval2 = (sceCdTrayReq(*(u32 *)argp, (u32 *)bufp) != 1) ? -EIO : 0; + break; + case CDIOC_STATUS: + *(u32 *)bufp = sceCdStatus(); + break; + case CDIOC_POWEROFF: + for ( i = 0; i < 3 && !retval2; i += 1 ) + { + WaitEventFlag(g_scmd_evid, 1, WEF_AND, &efbits); + retval2 = sceCdPowerOff((u32 *)bufp); + } + retval2 = (retval2 != 1) ? -EIO : 0; + break; + case CDIOC_MMODE: + sceCdMmode(*(u32 *)argp); + break; + case CDIOC_DISKRDY: + *(u32 *)bufp = sceCdDiskReady(*(u32 *)argp); + break; +#ifdef CDVD_VARIANT_DNAS + case 0x4326: + for ( i = 0; i < 3 && !retval2; i += 1 ) + { + WaitEventFlag(g_scmd_evid, 1, WEF_AND, &efbits); + retval2 = sceCdReadModelID((unsigned int *)bufp); + } + retval2 = (retval2 != 1) ? -EIO : 0; + break; +#endif + case CDIOC_STREAMINIT: + // The following call to sceCdStInit was inlined + retval2 = (!sceCdStInit(*(u32 *)argp, *((u32 *)argp + 1), (void *)*((u32 *)argp + 2))) ? -EIO : 0; + break; + case CDIOC_BREAK: + retval2 = (!sceCdBreak()) ? -EIO : 0; + sceCdSync(4); + break; + case CDIOC_SPINNOM: + g_cdvdman_spinnom = SCECdSpinNom; + break; + case CDIOC_SPINSTM: + g_cdvdman_spinnom = SCECdSpinStm; + break; + case CDIOC_TRYCNT: + g_cdvdman_trycnt = *(u8 *)argp; + break; + case 0x4383: + retval2 = (sceCdSeek(*(u32 *)argp) != 1) ? -EIO : 0; + sceCdSync(6); + break; + case CDIOC_STANDBY: + retval2 = (sceCdStandby() != 1) ? -EIO : 0; + sceCdSync(4); + break; + case CDIOC_STOP: + retval2 = (sceCdStop() != 1) ? -EIO : 0; + sceCdSync(4); + break; + case CDIOC_PAUSE: + retval2 = (sceCdPause() != 1) ? -EIO : 0; + sceCdSync(6); + break; + case CDIOC_GETTOC: + switch ( sceCdGetDiskType() ) + { + case SCECdPSCD: + case SCECdPSCDDA: + case SCECdPS2CD: + case SCECdPS2CDDA: + retval2 = (sceCdGetToc((u8 *)bufp) != 1) ? -EIO : 0; + break; + default: + break; + } + break; + case CDIOC_SETTIMEOUT: + retval2 = (sceCdSetTimeout(1, *(u32 *)argp) != 1) ? -EIO : 0; + break; + case CDIOC_READDVDDUALINFO: + retval2 = (!sceCdReadDvdDualInfo(&on_dual_tmp, (unsigned int *)bufp)) ? -EIO : 0; + break; + case CDIOC_INIT: + sceCdInit(*(u32 *)argp); + retval2 = 0; + break; + case 0x438C: + g_cdvdman_spinnom = SCECdSpinX1; + break; + case 0x438D: + g_cdvdman_spinnom = SCECdSpinX2; + break; + case 0x438E: + g_cdvdman_spinnom = SCECdSpinX4; + break; + case 0x438F: + g_cdvdman_spinnom = SCECdSpinX12; + break; + case 0x4390: + g_cdvdman_spinnom = SCECdSpinMx; + break; + case 0x4391: + *(u32 *)bufp = sceCdSC(0xFFFFFFF5, &scres_unused); + break; + case 0x4392: + retval2 = (sceCdApplySCmd(*(u8 *)argp, (char *)argp + 4, arglen - 4, bufp) != 1) ? -EIO : 0; + break; + case CDIOC_FSCACHEINIT: + retval2 = -EBUSY; + if ( g_cache_path_fd != -1 ) + { + break; + } + retval2 = -EINVAL; + sc_tmp_2 = (char *)argp; + for ( i = 0; i < arglen && sc_tmp_2[i] && sc_tmp_2[i] != ','; i += 1 ) + { + g_cdvdman_cache_name[i] = sc_tmp_2[i]; + } + sc_tmp_3 = i; + if ( i <= arglen ) + { + i += 1; + for ( ; (i < arglen) && sc_tmp_2[i] && sc_tmp_2[i] != ','; i += 1 ) + { + } + } + if ( i <= arglen ) + { + sc_tmp_2[i] = 0; + g_cdvdman_cache_sector_size_count = strtol((const char *)argp + sc_tmp_3, 0, 10); + retval2 = path_tbl_init(strtol(&sc_tmp_2[i + 1], 0, 10), g_cdvdman_cache_name, 1); + } + break; + case CDIOC_FSCACHEDELETE: + for ( i = 0; i < (sizeof(g_cdvdman_fhinfo) / sizeof(g_cdvdman_fhinfo[0])); i += 1 ) + { + if ( (g_cdvdman_fhinfo[i].m_fd_flags & 4) ) + { + break; + } + } + retval2 = (i == (sizeof(g_cdvdman_fhinfo) / sizeof(g_cdvdman_fhinfo[0]))) ? path_tbl_init(0, 0, 0) : -EBUSY; + break; + default: + retval2 = -EIO; + break; + } + if ( cmd != CDIOC_BREAK ) + { + SetEventFlag(g_fio_fsv_evid, 1); + } + return retval2; +} + +static int cdrom_lseek(iop_file_t *f, int offset, int pos) +{ + int retval; + cdvdman_fhinfo_t *fh; + u32 efbits; + + retval = -EPERM; + VERBOSE_PRINTF(1, "fileIO SEEK\n"); + WaitEventFlag(g_fio_fsv_evid, 1, WEF_AND | WEF_CLEAR, &efbits); + fh = &g_cdvdman_fhinfo[(int)f->privdata]; + switch ( pos ) + { + case 0: + retval = offset; + break; + case 1: + retval = fh->m_read_pos + offset; + break; + case 2: + retval = fh->m_file_size - offset; + break; + default: + break; + } + if ( retval > (int)(fh->m_file_size) ) + { + retval = fh->m_file_size; + } + fh->m_read_pos = retval; + if ( (fh->m_fd_flags & 8) ) + { + // The following call to sceCdStSeekF was inlined + if ( !sceCdStSeekF(fh->m_file_lsn + retval / 0x800) ) + { + retval = -EIO; + } + } + SetEventFlag(g_fio_fsv_evid, 1); + return retval; +} + +static int cdrom_nulldev() +{ + PRINTF("nulldev0 call\n"); + return -EIO; +} + +static s64 cdrom_nulldev64() +{ + PRINTF("nulldev0 call\n"); + return -EIO; +} + +static int sync_timeout_alarm_cb(const iop_sys_clock_t *sys_clock) +{ + KPRINTF("Cdvd Time Out %d(msec)\n", sys_clock->lo / 0x9000); + return !sceCdBreak(); +} + +int sceCdSetTimeout(int param, int timeout) +{ + if ( !sceCdCheckCmd() || g_cdvdman_istruct.m_read2_flag ) + { + return 0; + } + switch ( param ) + { + case 1: + g_cdvdman_sync_timeout = timeout; + return 1; + case 2: + g_cdvdman_stream_timeout = timeout; + return 1; + default: + return 0; + } +} + +int sceCdSync(int mode) +{ + iop_sys_clock_t sysclk; + iop_event_info_t efinfo; + u32 efbits; + + VERBOSE_KPRINTF(1, "sceCdSync: Call mode %d Com %x\n", mode, (u8)g_cdvdman_istruct.m_cdvdman_command); + switch ( mode ) + { + case 0: + while ( !sceCdCheckCmd() || g_cdvdman_istruct.m_read2_flag ) + { + WaitEventFlag(g_cdvdman_intr_efid, 1, WEF_AND, &efbits); + } + break; + case 1: + return !!(!sceCdCheckCmd() || (g_cdvdman_istruct.m_read2_flag)); + case 3: + sysclk.hi = 0; + sysclk.lo = 0x9000 * g_cdvdman_sync_timeout; + vSetAlarm(&sysclk, (unsigned int (*)(void *))sync_timeout_alarm_cb, &sysclk); + while ( !sceCdCheckCmd() || g_cdvdman_istruct.m_read2_flag ) + { + WaitEventFlag(g_cdvdman_intr_efid, 1, WEF_AND, &efbits); + } + vCancelAlarm((unsigned int (*)(void *))sync_timeout_alarm_cb, &sysclk); + break; + case 4: + sysclk.hi = 0; + sysclk.lo = 0x41EB0000; + vSetAlarm(&sysclk, (unsigned int (*)(void *))sync_timeout_alarm_cb, &sysclk); + while ( !sceCdCheckCmd() || g_cdvdman_istruct.m_read2_flag ) + { + WaitEventFlag(g_cdvdman_intr_efid, 1, WEF_AND, &efbits); + } + vCancelAlarm((unsigned int (*)(void *))sync_timeout_alarm_cb, &sysclk); + break; + case 5: + while ( !sceCdCheckCmd() ) + { + WaitEventFlag(g_cdvdman_intr_efid, 1, WEF_AND, &efbits); + } + break; + case 6: + sysclk.hi = 0; + sysclk.lo = 0x9000 * g_cdvdman_sync_timeout; + vSetAlarm(&sysclk, (unsigned int (*)(void *))sync_timeout_alarm_cb, &sysclk); + while ( !sceCdCheckCmd() || g_cdvdman_istruct.m_read2_flag ) + { + WaitEventFlag(g_cdvdman_intr_efid, 1, WEF_AND, &efbits); + } + vCancelAlarm((unsigned int (*)(void *))sync_timeout_alarm_cb, &sysclk); + break; + case 16: + while ( !sceCdCheckCmd() || g_cdvdman_istruct.m_read2_flag || g_cdvdman_ee_rpc_fno + || g_cdvdman_istruct.m_stream_flag ) + { + WaitEventFlag(g_cdvdman_intr_efid, 1, WEF_AND, &efbits); + if ( g_cdvdman_ee_rpc_fno ) + { + DelayThread(8000); + } + } + break; + case 17: + return !!( + !sceCdCheckCmd() || g_cdvdman_istruct.m_read2_flag || g_cdvdman_ee_rpc_fno + || (g_cdvdman_istruct.m_stream_flag)); + case 32: + WaitEventFlag(g_cdvdman_intr_efid, 0x21, WEF_OR, &efbits); + ReferEventFlagStatus(g_cdvdman_intr_efid, &efinfo); + if ( !(efinfo.currBits & 0x20) ) + { + if ( g_cdvdman_istruct.m_last_error ) + { + SetEventFlag(g_cdvdman_intr_efid, 0x20); + } + else + { + WaitEventFlag(g_cdvdman_intr_efid, 0x20, WEF_AND, &efbits); + } + } + break; + default: + while ( !sceCdCheckCmd() || g_cdvdman_istruct.m_read2_flag ) + { + WaitEventFlag(g_cdvdman_intr_efid, 1, WEF_AND, &efbits); + } + break; + } + VERBOSE_KPRINTF( + 1, + "sceCdSync: Command= %d Error= %d\n", + (u8)g_cdvdman_istruct.m_cdvdman_command, + (u8)g_cdvdman_istruct.m_last_error); + return 0; +} + +int sceCdSpinCtrlIOP(u32 speed) +{ + VERBOSE_KPRINTF(1, "sceCdSpinCtrlIOP speed= %d\n", speed); + g_cdvdman_spinctl = speed; + return 1; +} + +int sceCdLayerSearchFile(sceCdlFILE *fp, const char *path, int layer) +{ + unsigned int i; + int search_res; + u32 efbits; + + if ( PollEventFlag(g_sfile_evid, 1, WEF_AND | WEF_CLEAR, &efbits) == KE_EVF_COND ) + { + return 0; + } + for ( i = 0; i < ((sizeof(g_cdvdman_sfname) / sizeof(g_cdvdman_sfname[0])) - 1) && path[i]; i += 1 ) + { + g_cdvdman_sfname[i] = path[i]; + } + g_cdvdman_sfname[i] = 0; + g_cdvdman_srchspd = 1; + search_res = CdSearchFileInner((cdvdman_filetbl_entry_t *)fp, g_cdvdman_sfname, layer); + vSetEventFlag(g_sfile_evid, 1); + return search_res; +} + +int sceCdSearchFile(sceCdlFILE *file, const char *name) +{ + return sceCdLayerSearchFile(file, name, 0); +} + +int sceCdGetToc(u8 *toc) +{ + return cdvdman_gettoc(toc); +} + +int sceCdDiskReady(int mode) +{ + u32 efbits; + USE_DEV5_MMIO_HWPORT(); + + efbits = 0; + VERBOSE_KPRINTF(1, "DISK READY call from iop\n"); + switch ( mode ) + { + case 0: + VERBOSE_KPRINTF(1, "Wait Drive Ready %x\n", dev5_mmio_hwport->m_dev5_reg_005); + while ( 1 ) + { + if ( !g_cdvdman_istruct.m_read2_flag ) + { + return 2; + } + // The following call to sceCdGetDiskType was inlined + switch ( sceCdGetDiskType() ) + { + case SCECdDETCT: + case SCECdDETCTCD: + case SCECdDETCTDVDS: + case SCECdDETCTDVDD: + break; + default: + return 2; + } + while ( (dev5_mmio_hwport->m_dev5_reg_005 & 0xC0) != 0x40 ) + { + vDelayThread(2000); + WaitEventFlag(g_cdvdman_intr_efid, 1, WEF_AND, &efbits); + } + } + break; + case 8: + return (u8)dev5_mmio_hwport->m_dev5_reg_005; + case 1: + default: + if ( (dev5_mmio_hwport->m_dev5_reg_005 & 0xC0) == 0x40 && !g_cdvdman_istruct.m_read2_flag ) + { + return 2; + } + VERBOSE_KPRINTF(1, "Drive Not Ready\n"); + return 6; + } +} + +int sceCdGetDiskType(void) +{ + USE_DEV5_MMIO_HWPORT(); + + return (u8)dev5_mmio_hwport->m_dev5_reg_00F; +} + +int sceCdStatus(void) +{ + int reg_00A_tmp; + u32 status_tmp; + USE_DEV5_MMIO_HWPORT(); + + reg_00A_tmp = dev5_mmio_hwport->m_dev5_reg_00A; + // The following call to sceCdGetDiskType was inlined + if ( sceCdGetDiskType() == SCECdNODISC ) + { + u8 rdata_tmp; + + if ( !g_cdvdman_istruct.m_tray_is_open && cdvdman_scmd_sender_03_48(&rdata_tmp, &status_tmp) == 1 && !status_tmp ) + { + reg_00A_tmp &= ~SCECdStatShellOpen; + if ( (rdata_tmp & 8) ) + { + reg_00A_tmp |= SCECdStatShellOpen; + } + } + if ( (reg_00A_tmp & 0x1E) ) + { + reg_00A_tmp = SCECdStatStop; + } + } + if ( g_cdvdman_istruct.m_use_toc ) + { + reg_00A_tmp &= ~SCECdStatShellOpen; + } + if ( g_cdvdman_istruct.m_power_flag ) + { + return -1; + } + return reg_00A_tmp; +} + +sceCdlLOCCD *sceCdIntToPos(u32 i, sceCdlLOCCD *p) +{ + p->sector = 16 * ((i + 150) % 75 / 10) + (i + 150) % 75 % 10; + p->second = 16 * ((i + 150) / 75 % 60 / 10) + (i + 150) / 75 % 60 % 10; + p->minute = 16 * ((i + 150) / 75 / 60 / 10) + (i + 150) / 75 / 60 % 10; + return p; +} + +u32 sceCdPosToInt(sceCdlLOCCD *p) +{ + return 75 * (60 * (10 * (p->minute >> 4) + (p->minute & 0xF)) + 10 * (p->second >> 4) + (p->second & 0xF)) + + 10 * (p->sector >> 4) + (p->sector & 0xF) - 150; +} + +#ifdef CDVD_VARIANT_DNAS +static int read_id_from_rom(int mode, int *buf) +{ + int chksumint; + unsigned int i; + unsigned int j; + int idinfo[0x20]; + int chksumstk; + + chksumint = 0; + chksumstk = 0; + for ( i = 0; i < (sizeof(idinfo) / sizeof(idinfo[0])); i += 1 ) + { + for ( j = 0; j < sizeof(chksumstk); j += 1 ) + { + ((char *)&idinfo)[(i * 4) + j] = ((char *)0xBFBF0000)[(i * 4) + j]; + ((char *)&chksumstk)[j] = ((char *)0xBFBF0000)[(i * 4) + j]; + } + chksumint += chksumstk; + } + for ( ; i < 0x4000; i += 1 ) + { + for ( j = 0; j < sizeof(chksumstk); j += 1 ) + { + ((char *)&chksumstk)[j] = ((char *)0xBFBF0000)[(i * 4) + j]; + } + chksumint += chksumstk; + } + if ( chksumint ) + { + KPRINTF("# checksum error %d\n", chksumint); + return 0; + } + if ( mode ) + { + *buf = idinfo[11]; + } + else + { + *buf = idinfo[2]; + buf[1] = idinfo[3]; + } + return 1; +} + +static int query_boot_mode_6_nonzero() +{ + int *BootMode; + + BootMode = QueryBootMode(6); + return !(!BootMode || (*(u16 *)BootMode & 0xFFFC) != 0x60); +} + +static int query_boot_mode_6_zero() +{ + return !QueryBootMode(6); +} + +static int cdvdman_readID(int mode, int *buf) +{ + u8 id_val[8]; + iop_sys_clock_t sysclk; + u32 id_result; + + id_result = -1; + if ( query_boot_mode_6_nonzero() ) + { + if ( read_id_from_rom(mode, buf) && mode == 1 ) + { + if ( *buf == -1 ) + { + *buf = 0x1A0002; + } + return 1; + } + return 0; + } + else + { + if ( query_boot_mode_6_zero() ) + { + if ( !sceCdRI(id_val, &id_result) || id_result ) + { + return 0; + } + } + else + { + if ( !g_readid_systemtime.lo && !g_readid_systemtime.hi ) + { + GetSystemTime(&sysclk); + g_readid_systemtime = sysclk; + } + *(iop_sys_clock_t *)id_val = g_readid_systemtime; + } + if ( mode ) + { + *buf = *(u32 *)id_val >> 8; + } + else + { + *buf = id_val[0] | 0x8004600; + buf[1] = *(u32 *)&id_val[4]; + } + return 1; + } +} + +int sceCdReadGUID(u64 *guid) +{ + return cdvdman_readID(0, (int *)guid); +} + +int sceCdReadModelID(unsigned int *id) +{ + return cdvdman_readID(1, (int *)id); +} +#endif + +int sceCdStInit(u32 bufmax, u32 bankmax, void *buffer) +{ + cdrom_stm_devctl_t devctl_req; + int buf; + + memset(&devctl_req, 0, sizeof(devctl_req)); + devctl_req.m_cmdid = 5; + devctl_req.m_posszarg1 = bufmax; + devctl_req.m_posszarg2 = bankmax; + devctl_req.m_buffer = buffer; + return (devctl("cdrom_stm0:", 0x4393, &devctl_req, sizeof(devctl_req), &buf, 4) >= 0) ? buf : 0; +} + +int sceCdStStart(u32 lbn, sceCdRMode *mode) +{ + cdrom_stm_devctl_t devctl_req; + int buf; + + memset(&devctl_req, 0, sizeof(devctl_req)); + devctl_req.m_rmode.datapattern = mode->datapattern; + devctl_req.m_rmode.spindlctrl = mode->spindlctrl; + devctl_req.m_cmdid = 1; + devctl_req.m_posszarg1 = lbn; + devctl_req.m_rmode.trycount = mode->trycount; + return (devctl("cdrom_stm0:", 0x4393, &devctl_req, sizeof(devctl_req), &buf, 4) >= 0) ? buf : 0; +} + +int sceCdStSeekF(unsigned int lsn) +{ + cdrom_stm_devctl_t devctl_req; + int buf; + + memset(&devctl_req, 0, sizeof(devctl_req)); + devctl_req.m_cmdid = 9; + devctl_req.m_posszarg1 = lsn; + return (devctl("cdrom_stm0:", 0x4393, &devctl_req, sizeof(devctl_req), &buf, 4) >= 0) ? buf : 0; +} + +int sceCdStSeek(u32 lbn) +{ + cdrom_stm_devctl_t devctl_req; + int buf; + + memset(&devctl_req, 0, sizeof(devctl_req)); + devctl_req.m_posszarg1 = lbn; + devctl_req.m_cmdid = 4; + return (devctl("cdrom_stm0:", 0x4393, &devctl_req, sizeof(devctl_req), &buf, 4) >= 0) ? buf : 0; +} + +int sceCdStStop(void) +{ + cdrom_stm_devctl_t devctl_req; + int buf; + + memset(&devctl_req, 0, sizeof(devctl_req)); + devctl_req.m_cmdid = 3; + return (devctl("cdrom_stm0:", 0x4393, &devctl_req, sizeof(devctl_req), &buf, 4) >= 0) ? buf : 0; +} + +int sceCdStRead(u32 sectors, u32 *buffer, u32 mode, u32 *error) +{ + cdrom_stm_devctl_t devctl_req; + int buf; + + (void)mode; + + memset(&devctl_req, 0, sizeof(devctl_req)); + devctl_req.m_cmdid = 1; + devctl_req.m_posszarg2 = sectors; + devctl_req.m_buffer = buffer; + if ( devctl("cdrom_stm0:", 0x4394, &devctl_req, sizeof(devctl_req), &buf, 4) < 0 ) + { + buf = 0; + } + *error = devctl_req.m_error; + return buf; +} + +int sceCdStPause(void) +{ + cdrom_stm_devctl_t devctl_req; + int buf; + + memset(&devctl_req, 0, sizeof(devctl_req)); + devctl_req.m_cmdid = 7; + return (devctl("cdrom_stm0:", 0x4393, &devctl_req, sizeof(devctl_req), &buf, 4) >= 0) ? buf : 0; +} + +int sceCdStResume(void) +{ + cdrom_stm_devctl_t devctl_req; + int buf; + + memset(&devctl_req, 0, sizeof(devctl_req)); + devctl_req.m_cmdid = 8; + return (devctl("cdrom_stm0:", 0x4393, &devctl_req, sizeof(devctl_req), &buf, 4) >= 0) ? buf : 0; +} + +int sceCdStStat(void) +{ + cdrom_stm_devctl_t devctl_req; + int buf; + + memset(&devctl_req, 0, sizeof(devctl_req)); + devctl_req.m_cmdid = 6; + return (devctl("cdrom_stm0:", 0x4393, &devctl_req, sizeof(devctl_req), &buf, 4) >= 0) ? buf : 0; +} + +static int CdSearchFileInner(cdvdman_filetbl_entry_t *fp, const char *name, int layer) +{ + int parent_level; + int i; + unsigned int j; + char name_buf[32]; + + VERBOSE_PRINTF(1, "CdSearchFile: start name= %s layer= %d\n", name, layer); + if ( g_cdvdman_fs_layer != layer ) + { + g_cdvdman_fs_cache = 0; + } + if ( !cdvdman_mediactl(0) && g_cdvdman_fs_cache ) + { + VERBOSE_KPRINTF(1, "CdSearchFile: cache dir data used\n"); + } + else + { + VERBOSE_PRINTF(1, "CdSearchFile Topen= %s\n", name); + if ( !CD_newmedia(layer) ) + { + g_cdvdman_fs_cache = 0; + return 0; + } + g_cdvdman_fs_cache = 1; + } + if ( *name != '\\' ) + { + return 0; + } + name_buf[0] = 0; + parent_level = 1; + j = 0; + for ( i = 0; i < 8 && name[i]; i += 1 ) + { + for ( j = 0; name[i + j] != '\\'; j += 1 ) + { + name_buf[j] = name[i + j]; + } + name_buf[j] = 0; + parent_level = cdvdman_finddir(parent_level, name_buf); + if ( parent_level == -1 ) + { + name_buf[0] = 0; + break; + } + } + if ( i >= 8 ) + { + VERBOSE_PRINTF(1, "%s: path level (%d) error\n", name, i); + return 0; + } + if ( !name_buf[0] ) + { + VERBOSE_PRINTF(1, "%s: dir was not found\n", name); + return 0; + } + name_buf[j] = 0; + if ( !CD_cachefile(parent_level, layer) ) + { + VERBOSE_PRINTF(1, "CdSearchFile: disc error\n"); + return 0; + } + VERBOSE_PRINTF(2, "CdSearchFile: searching %s...\n", name_buf); + for ( j = 0; + j < (sizeof(g_cdvdman_filetbl) / sizeof(g_cdvdman_filetbl[0])) && g_cdvdman_filetbl[j].m_file_struct.name[0]; + j += 1 ) + { + VERBOSE_PRINTF(1, "%d %s %s\n", (int)j, g_cdvdman_filetbl[j].m_file_struct.name, name_buf); + if ( cdvdman_cmpname(g_cdvdman_filetbl[j].m_file_struct.name, name_buf) ) + { + VERBOSE_PRINTF(2, "%s:\t found\n", name_buf); + // The following memcpy was inlined + memcpy(fp, &g_cdvdman_filetbl[j], sizeof(cdvdman_filetbl_entry_t)); + fp->m_file_struct.lsn += layer ? g_cdvdman_fs_base2 : 0; + return 1; + } + } + VERBOSE_PRINTF(1, "%s: not found\n", name_buf); + return 0; +} + +static int sceCdSearchDir(char *dirname, int layer) +{ + sceCdlFILE fp; + + VERBOSE_PRINTF(1, "_sceCdSearchDir: dir name %s layer %d\n", dirname, layer); + return sceCdLayerSearchFile(&fp, dirname, layer) ? g_cdvdman_fs_cdsec : SCECdErREADCFR; +} + +static int sceCdReadDir(sceCdlFILE *fp, int dsec, int index, int layer) +{ + VERBOSE_PRINTF(1, "_sceCdReadDir: current= %d dsec= %d layer= %d\n", g_cdvdman_fs_cdsec, dsec, layer); + if ( g_cdvdman_fs_cdsec != dsec || g_cdvdman_fs_layer != layer ) + { + if ( g_cdvdman_fs_layer != layer ) + { + if ( !CD_newmedia(layer) ) + { + return -ENOENT; + } + g_cdvdman_fs_cache = 1; + } + if ( !CD_cachefile(dsec, layer) ) + { + return -ENOENT; + } + } + if ( g_cdvdman_filetbl[index].m_file_struct.name[0] ) + { + VERBOSE_PRINTF(1, "%s:\t found dir_point %d\n", g_cdvdman_filetbl[index].m_file_struct.name, index); + // The following memcpy was inlined + memcpy(fp, &g_cdvdman_filetbl[index], sizeof(cdvdman_filetbl_entry_t)); + return 1; + } + return 0; +} + +static int cdvdman_cmpname(const char *p, const char *q) +{ + return !strncmp(p, q, 12); +} + +static int CD_newmedia(int arg) +{ + unsigned int DiskType; + unsigned int i; + iso9660_path_t *path_cur; + int state; + int ptsector; + + ptsector = 0; + DiskType = sceCdGetDiskType(); + switch ( DiskType ) + { + case SCECdPSCD: + case SCECdPSCDDA: + case SCECdPS2CD: + case SCECdPS2CDDA: + case SCECdPS2DVD: + case SCECdDVDVR: + case SCECdDVDV: + case SCECdIllegalMedia: + break; + default: + VERBOSE_PRINTF(1, "CD_newmedia: Illegal disc media type =%d\n", (int)DiskType); + return 0; + } + g_cdvdman_fs_base2 = 0; + if ( DiskType == SCECdPS2DVD ) + { + if ( !DvdDual_infochk() ) + { + VERBOSE_PRINTF(1, "CD_newmedia: Get DvdDual_infochk fail\n"); + return 0; + } + g_cdvdman_fs_base2 = arg ? g_cdvdman_istruct.m_layer_1_lsn : 0; + } + if ( disc_read(1, g_cdvdman_fs_base2 + 0x10, g_cdvdman_fs_rbuf, arg) != 1 ) + { + VERBOSE_PRINTF(1, "CD_newmedia: Read error in disc_read(PVD)\n"); + return 0; + } + CpuSuspendIntr(&state); + for ( i = 0; i < g_cdvdman_pathtblsize; i += 1 ) + { + g_cdvdman_pathtbl[i].m_cache_hit_count = 0; + g_cdvdman_pathtbl[i].m_layer = 0; + g_cdvdman_pathtbl[i].m_nsec = 0; + g_cdvdman_pathtbl[i].m_lsn = 0; + g_cdvdman_pathtbl[i].m_cache_path_sz = 0; + } + g_cache_count = 0; + g_cache_table = 0; + g_cache_path_size = 0; + CpuResumeIntr(state); + if ( strncmp((char *)((iso9660_desc_t *)g_cdvdman_fs_rbuf)->m_id, "CD001", 5) ) + { + VERBOSE_PRINTF(1, "CD_newmedia: Disc format error in cd_read(PVD)\n"); + return 0; + } + switch ( DiskType ) + { + case SCECdPSCD: + case SCECdPSCDDA: + case SCECdPS2CD: + case SCECdPS2CDDA: + VERBOSE_PRINTF(1, "CD_newmedia: CD Read mode\n"); + ptsector = *(u32 *)(((iso9660_desc_t *)g_cdvdman_fs_rbuf)->m_type_l_path_table); + break; + case SCECdPS2DVD: + case SCECdDVDVR: + case SCECdDVDV: + VERBOSE_PRINTF(1, "CD_newmedia: DVD Read mode\n"); + ptsector = 257; + break; + } + if ( disc_read(1, g_cdvdman_fs_base2 + ptsector, g_cdvdman_fs_rbuf, arg) != 1 ) + { + VERBOSE_PRINTF(1, "CD_newmedia: Read error (PT:%08x)\n", ptsector); + return 0; + } + VERBOSE_PRINTF(2, "CD_newmedia: sarching dir..\n"); + for ( i = 0, path_cur = (iso9660_path_t *)g_cdvdman_fs_rbuf; + i < (sizeof(g_cdvdman_dirtbl) / sizeof(g_cdvdman_dirtbl[0])) + && path_cur < (iso9660_path_t *)&g_cdvdman_fs_rbuf[sizeof(g_cdvdman_fs_rbuf)] && path_cur->m_name_len[0]; + i += 1, + path_cur = (iso9660_path_t *)(((char *)path_cur) + path_cur->m_name_len[0] + (path_cur->m_name_len[0] & 1) + + sizeof(iso9660_path_t)) ) + { + memcpy(&g_cdvdman_dirtbl[i].m_extent, path_cur->m_extent, sizeof(path_cur->m_extent)); + g_cdvdman_dirtbl[i].m_number = i; + memcpy(&g_cdvdman_dirtbl[i].m_parent, path_cur->m_parent, sizeof(path_cur->m_parent)); + memcpy(g_cdvdman_dirtbl[i].m_name, path_cur->m_name, path_cur->m_name_len[0]); + g_cdvdman_dirtbl[i].m_name[path_cur->m_name_len[0]] = 0; + VERBOSE_PRINTF( + 2, + "\t%08x,%04x,%04x,%s\n", + g_cdvdman_dirtbl[i].m_extent, + g_cdvdman_dirtbl[i].m_number, + g_cdvdman_dirtbl[i].m_parent, + g_cdvdman_dirtbl[i].m_name); + } + if ( i < (sizeof(g_cdvdman_dirtbl) / sizeof(g_cdvdman_dirtbl[0])) ) + { + g_cdvdman_dirtbl[i].m_parent = 0; + } + g_cdvdman_fs_cdsec = 0; + g_cdvdman_fs_layer = arg; + VERBOSE_PRINTF(2, "CD_newmedia: %d dir entries found\n", (int)i); + return 1; +} + +static int cdvdman_finddir(int target_parent, const char *target_name) +{ + unsigned int i; + + for ( i = 0; i < (sizeof(g_cdvdman_dirtbl) / sizeof(g_cdvdman_dirtbl[0])) && g_cdvdman_dirtbl[i].m_parent; i += 1 ) + { + if ( g_cdvdman_dirtbl[i].m_parent == target_parent && !strcmp(target_name, g_cdvdman_dirtbl[i].m_name) ) + { + return i + 1; + } + } + return -1; +} + +static int CD_cachefile(int dsec, int layer) +{ + iso9660_dirent_t *dirent_cur; + unsigned int i; + + if ( dsec == g_cdvdman_fs_cdsec ) + { + return 1; + } + if ( + disc_read(1, g_cdvdman_dirtbl[dsec - 1].m_extent + (layer ? g_cdvdman_fs_base2 : 0), g_cdvdman_fs_rbuf, layer) + != 1 ) + { + VERBOSE_PRINTF(1, "CD_cachefile: dir not found\n"); + g_cdvdman_fs_cdsec = 0; + return 0; + } + VERBOSE_PRINTF(2, "CD_cachefile: searching...\n"); + for ( i = 0, dirent_cur = (iso9660_dirent_t *)g_cdvdman_fs_rbuf; + i < (sizeof(g_cdvdman_filetbl) / sizeof(g_cdvdman_filetbl[0])) + && dirent_cur < (iso9660_dirent_t *)&g_cdvdman_fs_rbuf[sizeof(g_cdvdman_fs_rbuf)]; + i += 1, dirent_cur = (iso9660_dirent_t *)((char *)dirent_cur + dirent_cur->m_length[0]) ) + { + int file_year; + + if ( !dirent_cur->m_length[0] ) + { + break; + } + memcpy( + &g_cdvdman_filetbl[i].m_file_struct.lsn, dirent_cur->m_extent, sizeof(g_cdvdman_filetbl[i].m_file_struct.lsn)); + memcpy( + &g_cdvdman_filetbl[i].m_file_struct.size, dirent_cur->m_size, sizeof(g_cdvdman_filetbl[i].m_file_struct.size)); + file_year = dirent_cur->m_date[0] + 1900; + g_cdvdman_filetbl[i].m_file_struct.date[7] = file_year >> 8; + g_cdvdman_filetbl[i].m_file_struct.date[6] = file_year; + g_cdvdman_filetbl[i].m_file_struct.date[5] = dirent_cur->m_date[1]; + g_cdvdman_filetbl[i].m_file_struct.date[4] = dirent_cur->m_date[2]; + g_cdvdman_filetbl[i].m_file_struct.date[3] = dirent_cur->m_date[3]; + g_cdvdman_filetbl[i].m_file_struct.date[2] = dirent_cur->m_date[4]; + g_cdvdman_filetbl[i].m_file_struct.date[1] = dirent_cur->m_date[5]; + g_cdvdman_filetbl[i].m_flags = dirent_cur->m_flags[0]; + switch ( i ) + { + case 0: + strcpy(g_cdvdman_filetbl[i].m_file_struct.name, "."); + break; + case 1: + strcpy(g_cdvdman_filetbl[i].m_file_struct.name, ".."); + break; + default: + memcpy(g_cdvdman_filetbl[i].m_file_struct.name, dirent_cur->m_name, dirent_cur->m_name_len[0]); + g_cdvdman_filetbl[i].m_file_struct.name[dirent_cur->m_name_len[0]] = 0; + break; + } + VERBOSE_PRINTF( + 2, + "\t lsn %d size %d name:%d:%s %d/%d/%d %d:%d:%d\n", + (int)(g_cdvdman_filetbl[i].m_file_struct.lsn), + (int)(g_cdvdman_filetbl[i].m_file_struct.size), + dirent_cur->m_name_len[0], + g_cdvdman_filetbl[i].m_file_struct.name, + file_year, + g_cdvdman_filetbl[i].m_file_struct.date[5], + g_cdvdman_filetbl[i].m_file_struct.date[4], + g_cdvdman_filetbl[i].m_file_struct.date[3], + g_cdvdman_filetbl[i].m_file_struct.date[2], + g_cdvdman_filetbl[i].m_file_struct.date[1]); + } + g_cdvdman_fs_cdsec = dsec; + if ( i < (sizeof(g_cdvdman_filetbl) / sizeof(g_cdvdman_filetbl[0])) ) + { + g_cdvdman_filetbl[i].m_file_struct.name[0] = 0; + } + VERBOSE_PRINTF(2, "CD_cachefile: %d files found\n", (int)i); + return 1; +} + +static int disc_read(int size, int loc, void *buffer, int layer) +{ + int f; + int i; + sceCdRMode rmode; + int has_success; + + has_success = 1; + f = 0; + rmode.trycount = 16; + VERBOSE_PRINTF(1, "cd_read:lsn= %d size= %d layer= %d\n", loc, size, layer); + if ( cdvdman_l0check(layer) ) + { + g_cdvdman_srchspd = 0; + } + switch ( g_cdvdman_srchspd ) + { + case SCECdSpinX1: + case SCECdSpinX2: + case SCECdSpinX4: + rmode.spindlctrl = g_cdvdman_srchspd; + break; + case SCECdSpinStm: + case SCECdSpinNom: + rmode.spindlctrl = !!g_cdvdman_srchspd; + break; + default: + rmode.spindlctrl = SCECdSpinNom; + break; + } + rmode.datapattern = SCECdSecS2048; + if ( !g_cdvdman_pathtblflag ) + { + has_success = 1; + } + if ( !has_success ) + { + int pathcachecnt; + + pathcachecnt = (g_cache_count < g_cdvdman_pathtblsize) ? g_cache_count : g_cdvdman_pathtblsize; + for ( i = 0; i < pathcachecnt; i += 1 ) + { + VERBOSE_KPRINTF( + 1, + "Path table Cache Search lsn:%d:%d nsec:%d:%d layer%d:%d\n", + g_cdvdman_pathtbl[i].m_lsn, + loc, + g_cdvdman_pathtbl[i].m_nsec, + size, + g_cdvdman_pathtbl[i].m_layer, + layer); + if ( + g_cdvdman_pathtbl[i].m_lsn == loc && g_cdvdman_pathtbl[i].m_nsec == (unsigned int)size + && g_cdvdman_pathtbl[i].m_layer == layer ) + { + break; + } + } + if ( i != pathcachecnt ) + { + VERBOSE_KPRINTF(1, "Path table Cache ON:%d\n", g_cdvdman_pathtbl[i].m_cache_path_sz); + if ( lseek(g_cache_path_fd, g_cdvdman_pathtbl[i].m_cache_path_sz, 0) >= 0 ) + { + read(g_cache_path_fd, buffer, size << 11); + f = 1; + g_cdvdman_pathtbl[i].m_cache_hit_count += 1; + } + has_success = 1; + } + if ( !has_success ) + { + if ( !sceCdRE(loc, size, buffer, &rmode) ) + { + return 0; + } + sceCdSync(3); + } + } + if ( !has_success && !sceCdGetError() ) + { + int cache_path_sz; + + if ( g_cache_count >= g_cdvdman_pathtblsize ) + { + int cachetblo1; + unsigned int cacheblo2; + + g_cache_table += 1; + if ( g_cache_table >= g_cdvdman_pathtblsize ) + { + g_cache_table = 0; + } + cachetblo1 = g_cache_table; + cacheblo2 = cachetblo1; + for ( i = 0; (unsigned int)i < g_cache_count; i += 1 ) + { + if ( cacheblo2 >= g_cdvdman_pathtblsize ) + { + cacheblo2 = 0; + } + if ( + g_cdvdman_pathtbl[cacheblo2].m_nsec >= (unsigned int)size + && g_cdvdman_pathtbl[cacheblo2].m_cache_hit_count + < (unsigned int)g_cdvdman_pathtbl[cachetblo1].m_cache_hit_count ) + { + cachetblo1 = cacheblo2; + } + cacheblo2 += 1; + } + cache_path_sz = g_cdvdman_pathtbl[cachetblo1].m_cache_path_sz; + g_cache_table = cachetblo1; + } + else + { + cache_path_sz = g_cache_path_size; + g_cache_table = g_cache_count; + g_cache_count += 1; + } + if ( lseek(g_cache_path_fd, cache_path_sz, 0) >= 0 ) + { + int ptbl_wcache_write_res; + + ptbl_wcache_write_res = write(g_cache_path_fd, buffer, size << 11); + if ( ptbl_wcache_write_res == size << 11 ) + { + f = 1; + g_cdvdman_pathtbl[g_cache_table].m_cache_path_sz = cache_path_sz; + g_cdvdman_pathtbl[g_cache_table].m_lsn = loc; + g_cdvdman_pathtbl[g_cache_table].m_nsec = size; + g_cdvdman_pathtbl[g_cache_table].m_layer = layer; + g_cdvdman_pathtbl[g_cache_table].m_cache_hit_count = 0; + g_cache_path_size += (g_cache_count < g_cdvdman_pathtblsize) ? ptbl_wcache_write_res : 0; + } + else + { + VERBOSE_KPRINTF(1, "Ptbl_WCache:write %d", ptbl_wcache_write_res); + g_cdvdman_pathtbl[g_cache_table].m_cache_hit_count = 0; + g_cdvdman_pathtbl[g_cache_table].m_layer = 0; + g_cdvdman_pathtbl[g_cache_table].m_nsec = 0; + g_cdvdman_pathtbl[g_cache_table].m_lsn = 0; + } + } + has_success = 1; + } + if ( has_success ) + { + if ( f ) + { + return size; + } + if ( !sceCdRE(loc, size, buffer, &rmode) ) + { + return 0; + } + sceCdSync(3); + if ( !sceCdGetError() ) + { + return size; + } + } + VERBOSE_KPRINTF(1, "cd_read: error code %x\n", sceCdGetError()); + return 0; +} + +static int path_tbl_init(u32 blocks, char *fname, int action) +{ + int num; + int v; + char cachedir[512]; + int state; + u32 blocksbs; + + num = 0; + v = 0; + if ( action ) + { + CpuSuspendIntr(&state); + g_cdvdman_pathtbl = (cdvdman_pathtbl_t *)AllocSysMemory(ALLOC_LAST, sizeof(cdvdman_pathtbl_t) * blocks, 0); + if ( !g_cdvdman_pathtbl ) + { + CpuResumeIntr(state); + g_cdvdman_pathtblflag = 0; + return -ENOMEM; + } + CpuResumeIntr(state); + sprintf(cachedir, "%sCache_Path", fname); + v = open(cachedir, O_TRUNC | O_CREAT | O_RDWR, 0x1ff /* 0o777 */); + if ( v >= 0 ) + { + u32 i; + + g_cache_path_fd = v; + if ( !strncmp(cachedir, "pfs", 3) ) + { + blocksbs = blocks << 11; + ioctl2(g_cache_path_fd, PIOCALLOC, &blocksbs, 4, 0, 0); + } + for ( i = 0; i < blocks; i += 1 ) + { + v = write(g_cache_path_fd, g_cdvdman_fs_rbuf, sizeof(g_cdvdman_fs_rbuf)); + if ( v < 0 ) + { + break; + } + } + if ( v >= 0 ) + { + CpuSuspendIntr(&state); + g_cdvdman_pathtblsize = blocks; + for ( i = 0; i < blocks; i += 1 ) + { + g_cdvdman_pathtbl[i].m_cache_hit_count = 0; + g_cdvdman_pathtbl[i].m_layer = 0; + g_cdvdman_pathtbl[i].m_nsec = 0; + g_cdvdman_pathtbl[i].m_lsn = 0; + g_cdvdman_pathtbl[i].m_cache_path_sz = 0; + } + g_cache_path_size = 0; + g_cache_count = 0; + g_cache_table = 0; + g_cdvdman_pathtblflag = 1; + CpuResumeIntr(state); + return 0; + } + } + } + if ( g_cache_path_fd != -1 ) + { + num = close(g_cache_path_fd); + if ( num >= 0 ) + { + if ( !strncmp(cachedir, "pfs", 3) ) + { + num = remove(cachedir); + } + else if ( !strncmp(cachedir, "host", 4) ) + { + num = 0; + remove(cachedir); + } + } + } + CpuSuspendIntr(&state); + g_cache_path_fd = -1; + g_cache_count = 0; + g_cache_table = 0; + g_cache_path_size = 0; + g_cdvdman_pathtblflag = 0; + g_cdvdman_pathtblsize = 0; + FreeSysMemory(g_cdvdman_pathtbl); + g_cdvdman_pathtbl = 0; + CpuResumeIntr(state); + if ( v < 0 ) + { + VERBOSE_KPRINTF(1, "path_tbl_init Error %d\n", v); + } + return (!action) ? num : v; +} + +// Unofficial: unused obfuscation code was removed + +// clang-format off +__asm__ ( + "\t" ".set push" "\n" + "\t" ".set noat" "\n" + "\t" ".set noreorder" "\n" + "\t" ".global optimized_memcpy" "\n" + "\t" "optimized_memcpy:" "\n" + "\t" " srl $a3, $a2, 2" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_12" "\n" + "\t" " or $a3, $a0, $a1" "\n" + "\t" " andi $a3, $a3, 0x3" "\n" + "\t" " bnez $a3, .Loptimized_memcpy_3" "\n" + "\t" " nop" "\n" + "\t" " srl $a3, $a2, 2" "\n" + "\t" " addiu $at, $zero, 0xC" "\n" + "\t" " div $zero, $a3, $at" "\n" + "\t" " mflo $a3" "\n" + "\t" " mfhi $v1" "\n" + "\t" " beqz $v1, .Loptimized_memcpy_2" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_1:" "\n" + "\t" " lw $v0, 0x0($a1)" "\n" + "\t" " addiu $v1, $v1, -0x1" "\n" + "\t" " sw $v0, 0x0($a0)" "\n" + "\t" " addiu $a1, $a1, 0x4" "\n" + "\t" " bnez $v1, .Loptimized_memcpy_1" "\n" + "\t" " addiu $a0, $a0, 0x4" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_12" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_2:" "\n" + "\t" " lw $v0, 0x0($a1)" "\n" + "\t" " lw $v1, 0x4($a1)" "\n" + "\t" " lw $t0, 0x8($a1)" "\n" + "\t" " lw $t1, 0xC($a1)" "\n" + "\t" " lw $t2, 0x10($a1)" "\n" + "\t" " lw $t3, 0x14($a1)" "\n" + "\t" " lw $t4, 0x18($a1)" "\n" + "\t" " lw $t5, 0x1C($a1)" "\n" + "\t" " lw $t6, 0x20($a1)" "\n" + "\t" " lw $t7, 0x24($a1)" "\n" + "\t" " lw $t8, 0x28($a1)" "\n" + "\t" " lw $t9, 0x2C($a1)" "\n" + "\t" " addiu $a3, $a3, -0x1" "\n" + "\t" " sw $v0, 0x0($a0)" "\n" + "\t" " sw $v1, 0x4($a0)" "\n" + "\t" " sw $t0, 0x8($a0)" "\n" + "\t" " sw $t1, 0xC($a0)" "\n" + "\t" " sw $t2, 0x10($a0)" "\n" + "\t" " sw $t3, 0x14($a0)" "\n" + "\t" " sw $t4, 0x18($a0)" "\n" + "\t" " sw $t5, 0x1C($a0)" "\n" + "\t" " sw $t6, 0x20($a0)" "\n" + "\t" " sw $t7, 0x24($a0)" "\n" + "\t" " sw $t8, 0x28($a0)" "\n" + "\t" " sw $t9, 0x2C($a0)" "\n" + "\t" " addiu $a1, $a1, 0x30" "\n" + "\t" " bnez $a3, .Loptimized_memcpy_2" "\n" + "\t" " addiu $a0, $a0, 0x30" "\n" + "\t" " j .Loptimized_memcpy_12" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_3:" "\n" + "\t" " andi $a3, $a0, 0x3" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_6" "\n" + "\t" " andi $a3, $a1, 0x3" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_6" "\n" + "\t" " nop" "\n" + "\t" " srl $a3, $a2, 2" "\n" + "\t" " addiu $at, $zero, 0xC" "\n" + "\t" " div $zero, $a3, $at" "\n" + "\t" " mflo $a3" "\n" + "\t" " mfhi $v1" "\n" + "\t" " beqz $v1, .Loptimized_memcpy_5" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_4:" "\n" + "\t" " lwl $v0, 0x3($a1)" "\n" + "\t" " lwr $v0, 0x0($a1)" "\n" + "\t" " addiu $v1, $v1, -0x1" "\n" + "\t" " swl $v0, 0x3($a0)" "\n" + "\t" " swr $v0, 0x0($a0)" "\n" + "\t" " addiu $a1, $a1, 0x4" "\n" + "\t" " bnez $v1, .Loptimized_memcpy_4" "\n" + "\t" " addiu $a0, $a0, 0x4" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_12" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_5:" "\n" + "\t" " lwl $v0, 0x3($a1)" "\n" + "\t" " lwr $v0, 0x0($a1)" "\n" + "\t" " lwl $v1, 0x7($a1)" "\n" + "\t" " lwr $v1, 0x4($a1)" "\n" + "\t" " lwl $t0, 0xB($a1)" "\n" + "\t" " lwr $t0, 0x8($a1)" "\n" + "\t" " lwl $t1, 0xF($a1)" "\n" + "\t" " lwr $t1, 0xC($a1)" "\n" + "\t" " lwl $t2, 0x13($a1)" "\n" + "\t" " lwr $t2, 0x10($a1)" "\n" + "\t" " lwl $t3, 0x17($a1)" "\n" + "\t" " lwr $t3, 0x14($a1)" "\n" + "\t" " lwl $t4, 0x1B($a1)" "\n" + "\t" " lwr $t4, 0x18($a1)" "\n" + "\t" " lwl $t5, 0x1F($a1)" "\n" + "\t" " lwr $t5, 0x1C($a1)" "\n" + "\t" " lwl $t6, 0x23($a1)" "\n" + "\t" " lwr $t6, 0x20($a1)" "\n" + "\t" " lwl $t7, 0x27($a1)" "\n" + "\t" " lwr $t7, 0x24($a1)" "\n" + "\t" " lwl $t8, 0x2B($a1)" "\n" + "\t" " lwr $t8, 0x28($a1)" "\n" + "\t" " lwl $t9, 0x2F($a1)" "\n" + "\t" " lwr $t9, 0x2C($a1)" "\n" + "\t" " addiu $a3, $a3, -0x1" "\n" + "\t" " swl $v0, 0x3($a0)" "\n" + "\t" " swr $v0, 0x0($a0)" "\n" + "\t" " swl $v1, 0x7($a0)" "\n" + "\t" " swr $v1, 0x4($a0)" "\n" + "\t" " swl $t0, 0xB($a0)" "\n" + "\t" " swr $t0, 0x8($a0)" "\n" + "\t" " swl $t1, 0xF($a0)" "\n" + "\t" " swr $t1, 0xC($a0)" "\n" + "\t" " swl $t2, 0x13($a0)" "\n" + "\t" " swr $t2, 0x10($a0)" "\n" + "\t" " swl $t3, 0x17($a0)" "\n" + "\t" " swr $t3, 0x14($a0)" "\n" + "\t" " swl $t4, 0x1B($a0)" "\n" + "\t" " swr $t4, 0x18($a0)" "\n" + "\t" " swl $t5, 0x1F($a0)" "\n" + "\t" " swr $t5, 0x1C($a0)" "\n" + "\t" " swl $t6, 0x23($a0)" "\n" + "\t" " swr $t6, 0x20($a0)" "\n" + "\t" " swl $t7, 0x27($a0)" "\n" + "\t" " swr $t7, 0x24($a0)" "\n" + "\t" " swl $t8, 0x2B($a0)" "\n" + "\t" " swr $t8, 0x28($a0)" "\n" + "\t" " swl $t9, 0x2F($a0)" "\n" + "\t" " swr $t9, 0x2C($a0)" "\n" + "\t" " addiu $a1, $a1, 0x30" "\n" + "\t" " bnez $a3, .Loptimized_memcpy_5" "\n" + "\t" " addiu $a0, $a0, 0x30" "\n" + "\t" " j .Loptimized_memcpy_12" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_6:" "\n" + "\t" " andi $a3, $a0, 0x3" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_9" "\n" + "\t" " nop" "\n" + "\t" " srl $a3, $a2, 2" "\n" + "\t" " addiu $at, $zero, 0xC" "\n" + "\t" " div $zero, $a3, $at" "\n" + "\t" " mflo $a3" "\n" + "\t" " mfhi $v1" "\n" + "\t" " beqz $v1, .Loptimized_memcpy_8" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_7:" "\n" + "\t" " lw $v0, 0x0($a1)" "\n" + "\t" " addiu $v1, $v1, -0x1" "\n" + "\t" " swl $v0, 0x3($a0)" "\n" + "\t" " swr $v0, 0x0($a0)" "\n" + "\t" " addiu $a1, $a1, 0x4" "\n" + "\t" " bnez $v1, .Loptimized_memcpy_7" "\n" + "\t" " addiu $a0, $a0, 0x4" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_12" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_8:" "\n" + "\t" " lw $v0, 0x0($a1)" "\n" + "\t" " lw $v1, 0x4($a1)" "\n" + "\t" " lw $t0, 0x8($a1)" "\n" + "\t" " lw $t1, 0xC($a1)" "\n" + "\t" " lw $t2, 0x10($a1)" "\n" + "\t" " lw $t3, 0x14($a1)" "\n" + "\t" " lw $t4, 0x18($a1)" "\n" + "\t" " lw $t5, 0x1C($a1)" "\n" + "\t" " lw $t6, 0x20($a1)" "\n" + "\t" " lw $t7, 0x24($a1)" "\n" + "\t" " lw $t8, 0x28($a1)" "\n" + "\t" " lw $t9, 0x2C($a1)" "\n" + "\t" " addiu $a3, $a3, -0x1" "\n" + "\t" " swl $v0, 0x3($a0)" "\n" + "\t" " swr $v0, 0x0($a0)" "\n" + "\t" " swl $v1, 0x7($a0)" "\n" + "\t" " swr $v1, 0x4($a0)" "\n" + "\t" " swl $t0, 0xB($a0)" "\n" + "\t" " swr $t0, 0x8($a0)" "\n" + "\t" " swl $t1, 0xF($a0)" "\n" + "\t" " swr $t1, 0xC($a0)" "\n" + "\t" " swl $t2, 0x13($a0)" "\n" + "\t" " swr $t2, 0x10($a0)" "\n" + "\t" " swl $t3, 0x17($a0)" "\n" + "\t" " swr $t3, 0x14($a0)" "\n" + "\t" " swl $t4, 0x1B($a0)" "\n" + "\t" " swr $t4, 0x18($a0)" "\n" + "\t" " swl $t5, 0x1F($a0)" "\n" + "\t" " swr $t5, 0x1C($a0)" "\n" + "\t" " swl $t6, 0x23($a0)" "\n" + "\t" " swr $t6, 0x20($a0)" "\n" + "\t" " swl $t7, 0x27($a0)" "\n" + "\t" " swr $t7, 0x24($a0)" "\n" + "\t" " swl $t8, 0x2B($a0)" "\n" + "\t" " swr $t8, 0x28($a0)" "\n" + "\t" " swl $t9, 0x2F($a0)" "\n" + "\t" " swr $t9, 0x2C($a0)" "\n" + "\t" " addiu $a1, $a1, 0x30" "\n" + "\t" " bnez $a3, .Loptimized_memcpy_8" "\n" + "\t" " addiu $a0, $a0, 0x30" "\n" + "\t" " j .Loptimized_memcpy_12" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_9:" "\n" + "\t" " srl $a3, $a2, 2" "\n" + "\t" " addiu $at, $zero, 0xC" "\n" + "\t" " div $zero, $a3, $at" "\n" + "\t" " mflo $a3" "\n" + "\t" " mfhi $v1" "\n" + "\t" " beqz $v1, .Loptimized_memcpy_11" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_10:" "\n" + "\t" " lwl $v0, 0x3($a1)" "\n" + "\t" " lwr $v0, 0x0($a1)" "\n" + "\t" " addiu $v1, $v1, -0x1" "\n" + "\t" " sw $v0, 0x0($a0)" "\n" + "\t" " addiu $a1, $a1, 0x4" "\n" + "\t" " bnez $v1, .Loptimized_memcpy_10" "\n" + "\t" " addiu $a0, $a0, 0x4" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_12" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_11:" "\n" + "\t" " lwl $v0, 0x3($a1)" "\n" + "\t" " lwr $v0, 0x0($a1)" "\n" + "\t" " lwl $v1, 0x7($a1)" "\n" + "\t" " lwr $v1, 0x4($a1)" "\n" + "\t" " lwl $t0, 0xB($a1)" "\n" + "\t" " lwr $t0, 0x8($a1)" "\n" + "\t" " lwl $t1, 0xF($a1)" "\n" + "\t" " lwr $t1, 0xC($a1)" "\n" + "\t" " lwl $t2, 0x13($a1)" "\n" + "\t" " lwr $t2, 0x10($a1)" "\n" + "\t" " lwl $t3, 0x17($a1)" "\n" + "\t" " lwr $t3, 0x14($a1)" "\n" + "\t" " lwl $t4, 0x1B($a1)" "\n" + "\t" " lwr $t4, 0x18($a1)" "\n" + "\t" " lwl $t5, 0x1F($a1)" "\n" + "\t" " lwr $t5, 0x1C($a1)" "\n" + "\t" " lwl $t6, 0x23($a1)" "\n" + "\t" " lwr $t6, 0x20($a1)" "\n" + "\t" " lwl $t7, 0x27($a1)" "\n" + "\t" " lwr $t7, 0x24($a1)" "\n" + "\t" " lwl $t8, 0x2B($a1)" "\n" + "\t" " lwr $t8, 0x28($a1)" "\n" + "\t" " lwl $t9, 0x2F($a1)" "\n" + "\t" " lwr $t9, 0x2C($a1)" "\n" + "\t" " addiu $a3, $a3, -0x1" "\n" + "\t" " sw $v0, 0x0($a0)" "\n" + "\t" " sw $v1, 0x4($a0)" "\n" + "\t" " sw $t0, 0x8($a0)" "\n" + "\t" " sw $t1, 0xC($a0)" "\n" + "\t" " sw $t2, 0x10($a0)" "\n" + "\t" " sw $t3, 0x14($a0)" "\n" + "\t" " sw $t4, 0x18($a0)" "\n" + "\t" " sw $t5, 0x1C($a0)" "\n" + "\t" " sw $t6, 0x20($a0)" "\n" + "\t" " sw $t7, 0x24($a0)" "\n" + "\t" " sw $t8, 0x28($a0)" "\n" + "\t" " sw $t9, 0x2C($a0)" "\n" + "\t" " addiu $a1, $a1, 0x30" "\n" + "\t" " bnez $a3, .Loptimized_memcpy_11" "\n" + "\t" " addiu $a0, $a0, 0x30" "\n" + "\t" ".Loptimized_memcpy_12:" "\n" + "\t" " andi $v1, $a2, 0x3" "\n" + "\t" " beqz $v1, .Loptimized_memcpy_14" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_13:" "\n" + "\t" " lb $v0, 0x0($a1)" "\n" + "\t" " addiu $v1, $v1, -0x1" "\n" + "\t" " sb $v0, 0x0($a0)" "\n" + "\t" " addiu $a1, $a1, 0x1" "\n" + "\t" " bnez $v1, .Loptimized_memcpy_13" "\n" + "\t" " addiu $a0, $a0, 0x1" "\n" + "\t" ".Loptimized_memcpy_14:" "\n" + "\t" " addu $v0, $a2, $zero" "\n" + "\t" " jr $ra" "\n" + "\t" " nop" "\n" + "\t" ".set pop" "\n" +); +// clang-format on + +#ifdef DEAD_CODE +void hex_dump(u8 *addr_start, int length) +{ + int i; + + KPRINTF("Hex Dump addr %08x\n", addr_start); + for ( i = 0; i < length; i += 1 ) + { + if ( !(i & 0xF) && i ) + { + PRINTF("\n"); + } + KPRINTF(" %02x", addr_start[i]); + } + KPRINTF("\n"); +} +#endif + +static int cdvdman_initcfg() +{ + int i; + u8 m_version[5]; + u32 eflag; + + eflag = 0; + for ( i = 0; i <= 100; i += 1 ) + { + unsigned int mvored; + + if ( !sceCdGetMVersion(m_version, &eflag) && (eflag & 0x80) ) + { + vDelayThread(2000); + VERBOSE_KPRINTF(1, "_sceCdMV error\n"); + } + mvored = m_version[3] | (m_version[2] << 8) | (m_version[1] << 16); + g_cdvdman_emudvd9 = m_version[2] & 1; + VERBOSE_KPRINTF(1, "MV %02x %02x %02x %02x\n", m_version[0], m_version[1], m_version[2], m_version[3]); + g_cdvdman_minver_10700 = mvored >= 0x10700; + g_cdvdman_minver_20200 = mvored >= 0x20200; + g_cdvdman_minver_20400 = mvored >= 0x20400; + g_cdvdman_minver_20800 = mvored >= 0x20800; + g_cdvdman_minver_50000 = mvored >= 0x50000; + g_cdvdman_minver_50200 = mvored >= 0x50200; + g_cdvdman_minver_50400 = mvored >= 0x50400; + g_cdvdman_minver_50600 = mvored >= 0x50600; + g_cdvdman_minver_x_model_15 = (mvored & 0xF) == 1; + g_cdvdman_minver_60000 = mvored >= 0x60000; + g_cdvdman_minver_60200 = mvored >= 0x60200; + return 1; + } + return 0; +} + +static int vSetAlarm(iop_sys_clock_t *sys_clock, unsigned int (*alarm_cb)(void *), void *arg) +{ + return (QueryIntrContext() ? iSetAlarm : SetAlarm)(sys_clock, alarm_cb, arg); +} + +static int vCancelAlarm(unsigned int (*alarm_cb)(void *), void *arg) +{ + return (QueryIntrContext() ? iCancelAlarm : CancelAlarm)(alarm_cb, arg); +} + +#ifdef DEAD_CODE +s32 vSignalSema(s32 sema_id) +{ + return (QueryIntrContext() ? iSignalSema : SignalSema)(sema_id); +} +#endif + +static int vSetEventFlag(int ef, u32 bits) +{ + return (QueryIntrContext() ? iSetEventFlag : SetEventFlag)(ef, bits); +} + +static int vClearEventFlag(int ef, u32 bits) +{ + return (QueryIntrContext() ? iClearEventFlag : ClearEventFlag)(ef, bits); +} + +static int vReferEventFlagStatus(int ef, iop_event_info_t *info) +{ + return (QueryIntrContext() ? iReferEventFlagStatus : ReferEventFlagStatus)(ef, info); +} + +static int vDelayThread(int usec) +{ + int intrval; + int state; + + intrval = CpuSuspendIntr(&state); + CpuResumeIntr(state); + return (!QueryIntrContext() && !intrval) ? DelayThread(usec) : 0; +} + +static int read_timeout_alarm_cb(const iop_sys_clock_t *sys_clock) +{ + int read_timeout; + + read_timeout = sys_clock->lo / 0x9000; + KPRINTF("Read Time Out %d(msec)\n", read_timeout); + sceCdSC(0xFFFFFFEE, &read_timeout); + return !sceCdBreak(); +} + +sceCdCBFunc sceCdCallback(sceCdCBFunc function) +{ + void (*rc)(int); + u32 efbits; + + if ( sceCdSync(1) || PollEventFlag(g_ncmd_evid, 1, WEF_AND | WEF_CLEAR, &efbits) == KE_EVF_COND ) + { + return 0; + } + rc = g_cdvdman_user_cb; + g_cdvdman_user_cb = function; + vSetEventFlag(g_ncmd_evid, 1); + return rc; +} + +void *sceCdPOffCallback(void (*func)(void *), void *addr) +{ + void (*old_cb)(void *); + int state; + + CpuSuspendIntr(&state); + old_cb = g_cdvdman_poff_cb; + g_cdvdman_poff_cb = func; + g_cdvdman_poffarg = addr; + CpuResumeIntr(state); + return old_cb; +} + +int sceCdstm0Cb(void (*p)(int)) +{ + g_cdvdman_cdstm0cb = p; + return 0; +} + +int sceCdstm1Cb(void (*p)(int)) +{ + g_cdvdman_cdstm1cb = p; + return 0; +} + +static int cdvdman_intr_cb(cdvdman_internal_struct_t *s) +{ + sceCdRMode cdrmode; + int oldstate; + int ext_passthrough; + USE_DEV5_MMIO_HWPORT(); + + ext_passthrough = 0; + s->m_wait_flag = s->m_waf_set_test; + iSetEventFlag(g_cdvdman_intr_efid, 0x29); + DisableIntr(IOP_IRQ_DMA_CDVD, &oldstate); + if ( *(u16 *)&s->m_cdvdman_command == 0x3105 ) + { + s->m_last_error = (sceCdStatus() == -1) ? SCECdErTRMOPN : 0; + } + if ( s->m_last_error == SCECdErEOM ) + { + s->m_last_error = 0; + } + VERBOSE_KPRINTF( + 1, "Intr call func_num: %d Err= %02x OnTout= %d\n", g_cdvdman_cmdfunc, (u8)s->m_last_error, s->m_last_read_timeout); + if ( !s->m_scmd_flag ) + { + cdvdman_write_scmd(s); + } + if ( + (((u8)s->m_last_error == SCECdErREAD && g_cdvdman_cmdfunc == SCECdFuncRead) + || ((u8)s->m_last_error == 1 && s->m_last_read_timeout && g_cdvdman_last_cmdfunc == 1)) + && !g_cdvdman_minver_20200 && !s->m_stream_flag && !s->m_dvd_flag && !s->m_recover_status + && s->m_read_mode.trycount != 1 ) + { + s->m_sync_error = 0; + s->m_interupt_read_state = 0; + if ( s->m_dec_mode_set ) + { + s->m_dec_mode_last_set = 1; + } + else + { + VERBOSE_KPRINTF(1, "dec mode 0x00\n"); + s->m_read_chunk_reprocial_32 = 1 + (0x20 / ((!s->m_read_chunk) ? s->m_read_sectors : s->m_read_chunk)); + s->m_dintrlsn = (s->m_read_lsn < 0x61) ? (s->m_read_lsn + s->m_read_sectors + 48) : (s->m_read_lsn - 80); + s->m_read_mode.spindlctrl = 16; + if ( !sceCdRead0_Rty( + s->m_dintrlsn, + (!s->m_read_chunk) ? s->m_read_sectors : s->m_read_chunk, + s->m_read_buf, + &s->m_read_mode, + (u8)s->m_cdvdman_command, + 0, + 0) ) + { + s->m_last_error = SCECdErREAD; + s->m_recover_status = 0; + } + else + { + ext_passthrough = 1; + } + } + } + if ( !ext_passthrough ) + { + char dev5_reg_013_masked; + + VERBOSE_KPRINTF(1, "Recover_Stat:%d\n", s->m_recover_status); + dev5_reg_013_masked = dev5_mmio_hwport->m_dev5_reg_013 & 0xF; + if ( dev5_reg_013_masked ) + { + if ( + ((u8)s->m_last_error == 48 || ((u8)s->m_last_error == 1 && s->m_last_read_timeout)) && !s->m_recover_status + && !s->m_stream_flag && g_cdvdman_cmdfunc != 9 && g_cdvdman_cmdfunc != SCECdFuncReadCDDA + && (unsigned int)s->m_read_mode.trycount - 1 >= 4 ) + { + s->m_sync_error = 0; + s->m_interupt_read_state = 0; + if ( s->m_dec_mode_set ) + { + s->m_dec_mode_last_set = 2; + } + else + { + VERBOSE_KPRINTF(1, "dec mode 0x01\n"); + cdrmode.trycount = s->m_read_mode.trycount; + cdrmode.spindlctrl = dev5_reg_013_masked + 13; + cdrmode.datapattern = s->m_read_mode.datapattern; + if ( sceCdRead0_Rty( + s->m_read_lsn, + s->m_read_sectors, + s->m_read_buf, + &cdrmode, + (u8)s->m_cdvdman_command, + s->m_read_chunk, + s->m_read_callback) ) + { + s->m_last_error = 0; + return 1; + } + s->m_last_error = SCECdErREAD; + } + } + } + s->m_last_read_timeout = 0; + switch ( s->m_recover_status ) + { + case 1: + s->m_sync_error = 0; + s->m_interupt_read_state = 0; + if ( + s->m_last_error + || !sceCdRead0_Rty( + s->m_dintrlsn, + (!s->m_read_chunk) ? s->m_read_sectors : s->m_read_chunk, + s->m_read_buf, + &s->m_read_mode, + (u8)s->m_cdvdman_command, + 0, + 0) ) + { + s->m_last_error = SCECdErREAD; + s->m_recover_status = 0; + } + else + { + ext_passthrough = 1; + } + break; + case 2: + s->m_sync_error = 0; + s->m_interupt_read_state = 0; + if ( sceCdRead0( + s->m_read_lsn, s->m_read_sectors, s->m_read_buf, &s->m_read_mode, s->m_read_chunk, s->m_read_callback) ) + { + s->m_last_error = 0; + s->m_recover_status = 3; + return 1; + } + s->m_last_error = SCECdErREAD; + s->m_recover_status = 0; + break; + case 3: + s->m_recover_status = 0; + break; + default: + break; + } + } + if ( ext_passthrough ) + { + s->m_last_error = 0; + s->m_dintrlsn += s->m_read_sectors; + s->m_read_chunk_reprocial_32 -= 1; + s->m_recover_status = (!s->m_read_chunk_reprocial_32) ? 2 : 1; + return 1; + } + if ( s->m_dec_state ) + { + sceCdDecSet(0, 0, 0); + } + if ( (s->m_read2_flag == 1 || s->m_read2_flag == 3) && !s->m_use_toc ) + { + VERBOSE_KPRINTF(1, "call Read2intrCDVD()\n"); + Read2intrCDVD(s->m_read2_flag); + } + s->m_sync_error = 0; + s->m_interupt_read_state = 0; + if ( s->m_dec_state == 2 ) + { + s->m_dec_state = 0; + } + if ( s->m_stream_flag == 1 && !s->m_use_toc && !s->m_read2_flag ) + { + if ( g_cdvdman_cdstm0cb ) + { + g_cdvdman_cdstm0cb(1); + } + else + { + VERBOSE_KPRINTF(1, "Intr func0 no seting"); + } + } + if ( s->m_stream_flag == 2 && !s->m_use_toc ) + { + if ( !s->m_read2_flag ) + { + if ( g_cdvdman_cdstm1cb ) + { + g_cdvdman_cdstm1cb(1); + } + else + { + VERBOSE_KPRINTF(1, "Intr func1 no seting"); + } + } + } + else + { + if ( !s->m_read2_flag ) + { + g_cdvdman_readptr = 0; + } + } + VERBOSE_KPRINTF( + 1, "Intr call user callback func_addr %08x num %d flg %d\n", g_cdvdman_user_cb, g_cdvdman_cmdfunc, s->m_read2_flag); + if ( g_cdvdman_user_cb && g_cdvdman_cmdfunc && !s->m_read2_flag && !s->m_use_toc ) + { + int cmdfunc_tmp; + + cmdfunc_tmp = g_cdvdman_cmdfunc; + g_cdvdman_cmdfunc = 0; + if ( cmdfunc_tmp == 14 || cmdfunc_tmp == 9 ) + { + cmdfunc_tmp = SCECdFuncRead; + } + g_cdvdman_user_cb(cmdfunc_tmp); + } + if ( !g_cdvdman_user_cb ) + { + g_cdvdman_cmdfunc = 0; + } + return 1; +} + +static int intrh_cdrom(cdvdman_internal_struct_t *s) +{ + int conds1; + iop_event_info_t efinfo; + USE_DEV5_MMIO_HWPORT(); + + conds1 = 0; + s->m_waf_set_test = s->m_wait_flag; + if ( (u8)s->m_last_error != 1 ) + { + s->m_last_error = dev5_mmio_hwport->m_dev5_reg_006; + } + if ( (dev5_mmio_hwport->m_dev5_reg_008 & 1) ) + { + s->m_waf_set_test = (!(dev5_mmio_hwport->m_dev5_reg_005 & 1)) ? 1 : -1; + dev5_mmio_hwport->m_dev5_reg_008 = 1; + conds1 = 1; + } + if ( (dev5_mmio_hwport->m_dev5_reg_008 & 4) ) + { + dev5_mmio_hwport->m_dev5_reg_008 = 4; + iSetEventFlag(g_cdvdman_intr_efid, 4); + iSetEventFlag(g_cdvdman_intr_efid, 0x10); + if ( g_cdvdman_poff_cb ) + { + g_cdvdman_poff_cb(g_cdvdman_poffarg); + } + if ( !conds1 ) + { + return 1; + } + } + else + { + s->m_waf_set_test = 1; + s->m_ncmd_intr_count += 1; + dev5_mmio_hwport->m_dev5_reg_008 = 2; + } + iReferEventFlagStatus(g_cdvdman_intr_efid, &efinfo); + if ( !(efinfo.currBits & 0x20) ) + { + if ( !s->m_last_error ) + { + s->m_drive_interupt_request = 1; + return 1; + } + if ( s->m_last_error == SCECdErEOM ) + { + intrh_dma_3(s); + } + } + return cdvdman_intr_cb(s); +} + +static u32 cdvdman_l1start(const u8 *toc) +{ + return toc[23] + (toc[22] << 8) + (toc[21] << 16) - 0x30000 + 1; +} + +static int DvdDual_infochk() +{ + if ( QueryIntrContext() || !(cdvdman_mediactl(3) || (u8)g_cdvdman_istruct.m_opo_or_para == 0xFF) ) + { + return 1; + } + g_cdvdman_istruct.m_use_toc = 1; + if ( !cdvdman_gettoc(g_cdvdman_ptoc) ) + { + g_cdvdman_istruct.m_use_toc = 0; + g_cdvdman_istruct.m_opo_or_para = -1; + return 0; + } + g_cdvdman_istruct.m_use_toc = 0; + g_cdvdman_istruct.m_layer_1_lsn = cdvdman_l1start(g_cdvdman_ptoc); + g_cdvdman_istruct.m_opo_or_para = ((g_cdvdman_ptoc[14] & 0x60)) ? (((g_cdvdman_ptoc[14] & 0x10)) ? 2 : 1) : 0; + if ( g_cdvdman_istruct.m_dual_layer_emulation ) + { + VERBOSE_KPRINTF(1, "CDVD:DualEmuON\n"); + g_cdvdman_istruct.m_layer_1_lsn = g_cdvdman_istruct.m_current_dvd_lsn; + g_cdvdman_istruct.m_opo_or_para = 0; + } + VERBOSE_KPRINTF( + 1, + "DvdDual_info: %02x\tLayer1_LSN:%d opo_or_para %d\n", + g_cdvdman_ptoc[14], + g_cdvdman_istruct.m_layer_1_lsn, + (u8)g_cdvdman_istruct.m_opo_or_para); + return 1; +} + +static u32 sceCdLsnDualChg(u32 lsn) +{ + int layer_disk_needed; + u32 change_lsn; + sceCdRMode cdrmode; + int has_change_lsn; + + layer_disk_needed = 2; + has_change_lsn = 0; + if ( cdvdman_isdvd() && DvdDual_infochk() ) + { + if ( g_cdvdman_istruct.m_dual_layer_emulation ) + { + if ( !g_cdvdman_istruct.m_current_dvd && lsn >= g_cdvdman_istruct.m_current_dvd_lsn ) + { + layer_disk_needed = 1; + } + if ( g_cdvdman_istruct.m_current_dvd && lsn < g_cdvdman_istruct.m_current_dvd_lsn ) + { + layer_disk_needed = 0; + } + if ( layer_disk_needed == 2 ) + { + change_lsn = lsn - ((g_cdvdman_istruct.m_current_dvd) ? g_cdvdman_istruct.m_current_dvd_lsn : 0); + has_change_lsn = 1; + } + else if ( !QueryIntrContext() ) + { + u32 traychk; + + VERBOSE_KPRINTF(0, "CDVD: Exchange it for the Layer_%d_Disk Please.\n", layer_disk_needed); + while ( g_cdvdman_minver_60200 ? !cdvdman_scmd_sender_3B(0) : !sceCdTrayReq(SCECdTrayOpen, &traychk) ) + { + ; + } + cdrmode.trycount = 0; + cdrmode.spindlctrl = SCECdSpinStm; + cdrmode.datapattern = SCECdSecS2048; + g_cdvdman_istruct.m_use_toc = 1; + while ( layer_disk_needed != 2 ) + { + if ( cdvdman_isdvd() ) + { + int read0_result; + + read0_result = sceCdRead0(0xE, 1, g_cdvdman_ptoc, &cdrmode, 0, 0); + sceCdSync(3); + if ( !g_cdvdman_istruct.m_last_error || read0_result ) + { + int i; + + for ( i = 0; i < 20; i += 1 ) + { + if ( g_cdvdman_ptoc[i + 104] != g_masterdisc_header[i] ) + { + break; + } + } + if ( i == 20 && g_cdvdman_ptoc[131] == 2 && (g_cdvdman_ptoc[132] & 2) ) + { + if ( layer_disk_needed == g_cdvdman_ptoc[133] ) + { + g_cdvdman_istruct.m_current_dvd = layer_disk_needed; + layer_disk_needed = 2; + } + else + { + VERBOSE_KPRINTF(0, "CDVD: Layer_%d Disk not Found\n", layer_disk_needed); + VERBOSE_KPRINTF(0, "CDVD: Exchange it for the Layer_%d_Disk Please.\n", layer_disk_needed); + if ( !g_cdvdman_istruct.m_current_dvd && lsn >= g_cdvdman_istruct.m_current_dvd_lsn ) + { + layer_disk_needed = 1; + } + while ( g_cdvdman_minver_60200 ? !cdvdman_scmd_sender_3B(0) : !sceCdTrayReq(SCECdTrayOpen, &traychk) ) + { + ; + } + } + } + else + { + VERBOSE_KPRINTF(0, "CDVD: Not Master Disk %s\n", (const char *)&g_cdvdman_ptoc[i + 104]); + while ( g_cdvdman_minver_60200 ? !cdvdman_scmd_sender_3B(0) : !sceCdTrayReq(SCECdTrayOpen, &traychk) ) + { + ; + } + } + } + else + { + VERBOSE_KPRINTF(1, "CDVD: LsnDualChg Read Error %02x, %d\n", (u8)g_cdvdman_istruct.m_last_error, 0); + } + } + else + { + vDelayThread(16000); + } + } + change_lsn = lsn - ((g_cdvdman_istruct.m_current_dvd) ? g_cdvdman_istruct.m_current_dvd_lsn : 0); + g_cdvdman_istruct.m_use_toc = 0; + has_change_lsn = 1; + } + } + else + { + change_lsn = + lsn - ((g_cdvdman_istruct.m_opo_or_para && (lsn >= (u32)g_cdvdman_istruct.m_layer_1_lsn)) ? 0x10 : 0); + has_change_lsn = 1; + } + } + if ( has_change_lsn ) + { + VERBOSE_KPRINTF(1, "CDVD: sceCdLsnDualChg lsn %d: change lsn %d\n", lsn, change_lsn); + } + return has_change_lsn ? change_lsn : lsn; +} + +int sceCdReadDvdDualInfo(int *on_dual, unsigned int *layer1_start) +{ + int read0_result; + int i; + sceCdRMode cdrmode; + + *on_dual = 0; + *layer1_start = 0; + g_cdvdman_istruct.m_dual_layer_emulation = 0; + if ( !cdvdman_isdvd() ) + { + return 1; + } + if ( !g_cdvdman_emudvd9 ) + { + if ( !DvdDual_infochk() ) + { + return 0; + } + *on_dual = !!g_cdvdman_istruct.m_opo_or_para; + *layer1_start = g_cdvdman_istruct.m_layer_1_lsn; + return 1; + } + if ( g_cdvdman_mmode != SCECdMmodeDvd && g_cdvdman_mmode != 0xFF ) + { + return 0; + } + cdrmode.trycount = 0; + cdrmode.spindlctrl = SCECdSpinStm; + cdrmode.datapattern = SCECdSecS2048; + read0_result = sceCdRead0(0xE, 1, g_cdvdman_ptoc, &cdrmode, 0, 0); + sceCdSync(3); + if ( g_cdvdman_istruct.m_last_error && !read0_result ) + { + VERBOSE_KPRINTF(1, "CDVD: ReadDvdDualInfo Read Error %02x, %d\n", (u8)g_cdvdman_istruct.m_last_error, 0); + return 0; + } + for ( i = 0; i < 20; i += 1 ) + { + if ( g_cdvdman_ptoc[i + 104] != g_masterdisc_header[i] ) + { + break; + } + } + if ( i != 20 ) + { + if ( !DvdDual_infochk() ) + { + return 0; + } + *on_dual = !!g_cdvdman_istruct.m_opo_or_para; + *layer1_start = g_cdvdman_istruct.m_layer_1_lsn; + return 1; + } + if ( g_cdvdman_ptoc[131] != 2 || !(g_cdvdman_ptoc[132] & 2) ) + { + return 1; + } + g_cdvdman_istruct.m_current_dvd = g_cdvdman_ptoc[133]; + g_cdvdman_istruct.m_current_dvd_lsn = + g_cdvdman_ptoc[134] + (g_cdvdman_ptoc[135] << 8) + (g_cdvdman_ptoc[136] << 16) + (g_cdvdman_ptoc[137] << 24) + 1; + g_cdvdman_istruct.m_opo_or_para = 0; + g_cdvdman_istruct.m_layer_1_lsn = g_cdvdman_istruct.m_current_dvd_lsn; + g_cdvdman_istruct.m_dual_layer_emulation = 1; + *on_dual = 1; + *layer1_start = g_cdvdman_istruct.m_layer_1_lsn; + VERBOSE_KPRINTF( + 1, + "sceCdReadDvdDualInfo():Cur_Disk %d layer1_start %d\n", + (u8)g_cdvdman_istruct.m_current_dvd, + g_cdvdman_istruct.m_current_dvd_lsn); + return 1; +} + +int sceCdSC(int code, int *param) +{ + void *poffarg_tmp; + int *BootMode; + int state; + u32 efbits; + + switch ( code ) + { + case 0xFFFFFFE6: + CpuSuspendIntr(&state); + *param = (int)g_cdvdman_poff_cb; + poffarg_tmp = g_cdvdman_poffarg; + CpuResumeIntr(state); + return (int)poffarg_tmp; + case 0xFFFFFFE7: + return g_scmd_evid; + case 0xFFFFFFE9: + return sceCdLsnDualChg(*param); + case 0xFFFFFFEA: + return DvdDual_infochk(); + case 0xFFFFFFEE: + g_cdvdman_istruct.m_last_read_timeout = *param; + return 0; + case 0xFFFFFFEF: + return g_cdvdman_stream_timeout; + case 0xFFFFFFF0: + *param = (int)&g_verbose_level; + return 0xFF; + case 0xFFFFFFF1: + return g_cdvdman_sync_timeout; + case 0xFFFFFFF2: + *param = (int)&g_cdvdman_istruct; + return 0xFF; + case 0xFFFFFFF3: + BootMode = QueryBootMode(4); + if ( BootMode ) + { + switch ( *(u8 *)BootMode ) + { + case 0: + case 1: + case 2: + g_cdvdman_mmode = 0xFF; + break; + case 3: + g_cdvdman_mmode = SCECdMmodeCd; + break; + } + } + return 1; + case 0xFFFFFFF4: + // The following call to sceCdGetDiskType was inlined + switch ( sceCdGetDiskType() ) + { + case SCECdPSCD: + case SCECdPSCDDA: + case SCECdPS2CD: + case SCECdPS2CDDA: + return g_cdvdman_mmode == SCECdMmodeCd || g_cdvdman_mmode == 0xFF; + case SCECdPS2DVD: + return g_cdvdman_mmode == SCECdMmodeDvd || g_cdvdman_mmode == 0xFF; + case SCECdCDDA: + return g_cdvdman_mmode == 0xFF; + default: + return 0; + } + case 0xFFFFFFF5: + return g_cdvdman_intr_efid; + case 0xFFFFFFF6: + if ( *param ) + { + WaitEventFlag(g_fio_fsv_evid, 1, WEF_AND | WEF_CLEAR, &efbits); + } + else + { + SetEventFlag(g_fio_fsv_evid, 1); + } + g_cdvdman_ee_rpc_fno = *param; + VERBOSE_KPRINTF(1, "EE_ncmd_working code= %d\n", *param); + return g_cdvdman_ee_rpc_fno; + case 0xFFFFFFF7: + return (u16)_irx_id.v; + case 0xFFFFFFF8: + g_cdvdman_spinctl = *param; + return 1; + case 0xFFFFFFFC: + return g_cdvdman_cd36key; + case 0xFFFFFFFD: + return g_cdvdman_istruct.m_read2_flag; + case 0xFFFFFFFE: + g_cdvdman_istruct.m_last_error = *(u8 *)param; + return (u8)g_cdvdman_istruct.m_last_error; + case 0xFFFFFFFF: + case 0: + case 1: + case 2: + *param = (u8)g_cdvdman_istruct.m_last_error; + if ( code != -1 ) + { + g_cdvdman_istruct.m_stream_flag = code; + } + return g_cdvdman_istruct.m_stream_flag; + default: + VERBOSE_KPRINTF(1, "sceCdSC func_num Not found %d\n", code); + return 0; + } +} + +static void cdvdman_init() +{ + int *BootMode; + unsigned int i; + int scres_unused; + u32 argres; + USE_DEV5_MMIO_HWPORT(); + + g_cdvdman_user_cb = 0; + g_cdvdman_poff_cb = 0; + g_cdvdman_cmdfunc = 0; + g_cdvdman_istruct.m_drive_interupt_request = 0; + RegisterIntrHandler(IOP_IRQ_CDVD, 1, (int (*)(void *))intrh_cdrom, &g_cdvdman_istruct); + RegisterIntrHandler(IOP_IRQ_DMA_CDVD, 1, (int (*)(void *))intrh_dma_3, &g_cdvdman_istruct); + EnableIntr(IOP_IRQ_CDVD); + sceCdSC(0xFFFFFFF3, &scres_unused); + dmac_set_dpcr(dmac_get_dpcr() | 0x8000); + dmac_ch_set_chcr(3, 0); + if ( (dev5_mmio_hwport->m_dev5_reg_008 & 4) ) + { + dev5_mmio_hwport->m_dev5_reg_008 = 4; + } + if ( (dev5_mmio_hwport->m_dev5_reg_008 & 1) ) + { + dev5_mmio_hwport->m_dev5_reg_008 = 1; + } + g_cdvdman_clk_flg = sceCdReadClock(&g_cdvdman_clock) ? (!g_cdvdman_clock.stat) : 0; + g_cdvdman_istruct.m_tray_is_open = (dev5_mmio_hwport->m_dev5_reg_00A ^ 1) & 1; + cdvdman_initcfg(); + BootMode = QueryBootMode(6); + g_cdvdman_istruct.m_no_dec_flag = BootMode ? ((*(u16 *)BootMode & 0xFFFC) == 0x60) : 0; + for ( i = 0; i <= 60 && (!sceCdCancelPOffRdy(&argres) || argres); i += 1 ) + { + DelayThread(16000); + } +} + +int sceCdInit(int mode) +{ + USE_DEV5_MMIO_HWPORT(); + + VERBOSE_PRINTF(1, "sceCdInit called mode= %d\n", mode); + if ( mode == SCECdEXIT ) + { + int oldstate; + + g_cdvdman_istruct.m_cd_inited = 0; + sceCdBreak(); + sceCdSync(3); + cdvdman_ncmd_sender_06(); + sceCdSync(0); + VERBOSE_PRINTF(1, "Cdvdman Exit\n"); + DisableIntr(IOP_IRQ_CDVD, &oldstate); + ReleaseIntrHandler(IOP_IRQ_CDVD); + DisableIntr(IOP_IRQ_DMA_CDVD, &oldstate); + ReleaseIntrHandler(IOP_IRQ_DMA_CDVD); + } + else + { + VERBOSE_PRINTF(1, "Cdvdman Init\n"); + g_cdvdman_istruct.m_read2_flag = 0; + g_cdvdman_istruct.m_dec_shift = 0; + g_cdvdman_istruct.m_check_version = 0; + g_cdvdman_istruct.m_dec_state = 0; + sceCdDecSet(0, 0, 0); + cdvdman_init(); + g_cdvdman_istruct.m_cd_inited = 1; + } + if ( mode == SCECdINIT ) + { + u8 ready_status_tmp; + u8 ready_status; + int ready_status_mask_c0h; + + ready_status_tmp = 0; + VERBOSE_PRINTF(1, "sceCdInit Ready check start.\n"); + for ( ready_status_mask_c0h = 0; ready_status_mask_c0h != 0x40; ready_status_mask_c0h = ready_status & 0xC0 ) + { + ready_status = dev5_mmio_hwport->m_dev5_reg_005; + vDelayThread(10000); + if ( ready_status != ready_status_tmp ) + { + ready_status_tmp = ready_status; + VERBOSE_PRINTF(1, "sceCdInit Dev5 Status %x\n", ready_status); + } + } + VERBOSE_PRINTF(1, "sceCdInit Ready check end.\n"); + } + g_cdvdman_istruct.m_wait_flag = 1; + g_cdvdman_istruct.m_scmd_flag = 1; + g_cdvdman_istruct.m_last_error = 0; + g_cdvdman_istruct.m_last_read_timeout = 0; + g_cdvdman_spinctl = -1; + SetEventFlag(g_cdvdman_intr_efid, 0x29); + SetEventFlag(g_ncmd_evid, 1); + SetEventFlag(g_scmd_evid, 1); + SetEventFlag(g_sfile_evid, 1); + return 1; +} + +static int set_prev_command(int cmd, const char *sdata, int sdlen, char *rdata, int rdlen, int check_sef) +{ + int i; + int delaybackoff; + int j; + u32 efbits; + + if ( check_sef == 1 && PollEventFlag(g_scmd_evid, 1, WEF_AND | WEF_CLEAR, &efbits) == KE_EVF_COND ) + { + return 0; + } + g_cdvdman_istruct.m_scmd = cmd; + g_cdvdman_istruct.m_sdlen = sdlen; + g_cdvdman_istruct.m_rdlen = rdlen; + for ( i = 0; i < sdlen; i += 1 ) + { + g_cdvdman_istruct.m_scmd_sd[i] = sdata[i]; + } + if ( g_cdvdman_istruct.m_wait_flag ) + { + g_cdvdman_istruct.m_scmd_flag = 1; + cdvdman_write_scmd(&g_cdvdman_istruct); + } + else if ( QueryIntrContext() ) + { + while ( (dmac_ch_get_chcr(3) & 0x1000000) && !g_cdvdman_istruct.m_wait_flag ) + { + VERBOSE_KPRINTF(1, "set_prev_command: DMA Wait\n"); + } + g_cdvdman_istruct.m_scmd_flag = 1; + cdvdman_write_scmd(&g_cdvdman_istruct); + } + else + { + g_cdvdman_istruct.m_scmd_flag = 0; + } + delaybackoff = 1; + for ( i = 0; i < 500; i += delaybackoff ) + { + if ( g_cdvdman_istruct.m_scmd_flag ) + { + for ( j = 0; j < rdlen; j += 1 ) + { + rdata[j] = g_cdvdman_istruct.m_scmd_rd[j]; + } + if ( check_sef == 1 ) + { + vSetEventFlag(g_scmd_evid, 1); + } + return (u8)g_cdvdman_istruct.m_scmd; + } + vDelayThread(1000 * delaybackoff); + if ( (i & 1) && delaybackoff < 16 ) + { + delaybackoff *= 2; + } + } + g_cdvdman_istruct.m_scmd_flag = 1; + if ( check_sef == 1 ) + { + vSetEventFlag(g_scmd_evid, 1); + } + return 0; +} + +static void cdvdman_write_scmd(cdvdman_internal_struct_t *s) +{ + int i; + unsigned int j; + unsigned int rdcnt; + char rdptr1[64]; + USE_DEV5_MMIO_HWPORT(); + + for ( i = 0; i <= 0; i += 1 ) + { + int overflowcond; + + if ( (dev5_mmio_hwport->m_dev5_reg_017 & 0x80) ) + { + *(u16 *)&s->m_scmd_flag = 1; + return; + } + while ( !(dev5_mmio_hwport->m_dev5_reg_017 & 0x40) ) + { + ; + } + for ( j = 0; j < (u8)s->m_sdlen; j += 1 ) + { + dev5_mmio_hwport->m_dev5_reg_017 = s->m_scmd_sd[j]; + } + dev5_mmio_hwport->m_dev5_reg_016 = s->m_scmd; + if ( QueryIntrContext() ) + { + for ( j = 0; dev5_mmio_hwport->m_dev5_reg_017 & 0x80; j += 1 ) + { + if ( j > 12500000 ) + { + *(u16 *)&s->m_scmd_flag = 1; + return; + } + } + } + else + { + for ( j = 0; dev5_mmio_hwport->m_dev5_reg_017 & 0x80; j += 1 ) + { + DelayThread(100); + if ( j > 50000 ) + { + *(u16 *)&s->m_scmd_flag = 1; + return; + } + } + } + overflowcond = 0; + for ( j = 0; j < (u8)s->m_rdlen; j += 1 ) + { + if ( (dev5_mmio_hwport->m_dev5_reg_017 & 0x40) ) + { + break; + } + rdptr1[j] = dev5_mmio_hwport->m_dev5_reg_018; + } + if ( j >= (u8)s->m_rdlen ) + { + overflowcond = 1; + VERBOSE_KPRINTF(1, "Prev Cmd Result Over Flow\n", rdptr1); + } + rdcnt = j; + if ( (!overflowcond && j >= (u8)s->m_rdlen) || s->m_rdlen == 16 ) + { + break; + } + VERBOSE_KPRINTF(1, "Prev Cmd Result Illegal Size Try count:%d\n", i); + } + if ( i == 1 ) + { + *(u16 *)&s->m_scmd_flag = 1; + } + else + { + for ( j = 0; j < (sizeof(s->m_scmd_rd) / sizeof(s->m_scmd_rd[0])); j += 1 ) + { + s->m_scmd_rd[j] = 0; + } + if ( s->m_rdlen != (sizeof(s->m_scmd_rd) / sizeof(s->m_scmd_rd[0])) ) + { + rdcnt = (u8)s->m_rdlen; + } + for ( j = 0; j < rdcnt; j += 1 ) + { + s->m_scmd_rd[j] = rdptr1[j]; + } + s->m_scmd_flag = 1; + s->m_scmd = 1; + } +} + +static int cdvdman_send_scmd2(int cmd, const void *sdata, int sdlen, void *rdata, int rdlen, int check_sef) +{ + int i; + int j; + char rdstart[64]; + u32 efbits; + USE_DEV5_MMIO_HWPORT(); + + if ( check_sef == 1 && PollEventFlag(g_scmd_evid, 1, WEF_AND | WEF_CLEAR, &efbits) == KE_EVF_COND ) + { + return 0; + } + for ( i = 0; i <= 0; i += 1 ) + { + int cmdresoverflow; + + if ( (dev5_mmio_hwport->m_dev5_reg_017 & 0x80) ) + { + if ( check_sef == 1 ) + { + vSetEventFlag(g_scmd_evid, 1); + } + return 0; + } + while ( !(dev5_mmio_hwport->m_dev5_reg_017 & 0x40) ) + { + ; + } + for ( j = 0; j < sdlen; j += 1 ) + { + dev5_mmio_hwport->m_dev5_reg_017 = ((u8 *)sdata)[j]; + } + dev5_mmio_hwport->m_dev5_reg_016 = cmd; + while ( (dev5_mmio_hwport->m_dev5_reg_017 & 0x80) ) + { + DelayThread(100); + } + cmdresoverflow = 0; + for ( j = 0; !(dev5_mmio_hwport->m_dev5_reg_017 & 0x40); j += 1 ) + { + if ( j >= rdlen ) + { + cmdresoverflow = 1; + VERBOSE_KPRINTF(1, "Prev Cmd Result Over Flow\n"); + break; + } + rdstart[j] = dev5_mmio_hwport->m_dev5_reg_018; + } + if ( (!cmdresoverflow && j >= rdlen) || rdlen == 16 ) + { + break; + } + VERBOSE_KPRINTF(1, "Prev Cmd Result Illegal Size Try count:%d\n", i); + while ( !(dev5_mmio_hwport->m_dev5_reg_017 & 0x20) ) + { + ; + } + for ( j = 0; j < 16 - rdlen; j += 1 ) + ; + } + if ( i == 1 ) + { + if ( check_sef == 1 ) + { + vSetEventFlag(g_scmd_evid, 1); + } + return 0; + } + for ( i = 0; i < rdlen; i += 1 ) + { + ((char *)rdata)[i] = rdstart[i]; + } + if ( check_sef == 1 ) + { + vSetEventFlag(g_scmd_evid, 1); + } + return 1; +} + +int sceCdApplySCmd(u8 cmdNum, const void *inBuff, u16 inBuffSize, void *outBuff) +{ + int i; + + for ( i = 0; i <= 2500; i += 1 ) + { + if ( set_prev_command(cmdNum, (const char *)inBuff, inBuffSize, (char *)outBuff, 16, 1) ) + { + DelayThread(2000); + return 1; + } + DelayThread(2000); + } + KPRINTF("CDVD: set_prev_command TIMEOUT 5(SEC)\n"); + return 0; +} + +int sceCdApplySCmd2(u8 cmdNum, const void *inBuff, unsigned long int inBuffSize, void *outBuff) +{ + int i; + + for ( i = 0; i <= 2500; i += 1 ) + { + if ( cdvdman_send_scmd2(cmdNum, inBuff, inBuffSize, outBuff, 16, 1) ) + { + return 1; + } + DelayThread(2000); + } + KPRINTF("CDVD: set_prev_command TIMEOUT 5(SEC)\n"); + return 0; +} + +#ifdef DEAD_CODE +int sceCdApplySCmd3(u8 cmdNum, const void *inBuff, unsigned long int inBuffSize, void *outBuff) +{ + int i; + + for ( i = 0; i <= 2500; i += 1 ) + { + DelayThread(2000); + if ( set_prev_command((u8)cmdNum, inBuff, inBuffSize, outBuff, 16, 1) ) + { + DelayThread(2000); + return 1; + } + } + KPRINTF("CDVD: set_prev_command TIMEOUT 5(SEC)\n"); + return 0; +} +#endif + +int sceCdBreak(void) +{ + u32 efbits; + int state; + int oldstate; + USE_DEV5_MMIO_HWPORT(); + + if ( PollEventFlag(g_ncmd_evid, 1, WEF_AND | WEF_CLEAR, &efbits) == KE_EVF_COND ) + { + return 0; + } + CpuSuspendIntr(&state); + VERBOSE_KPRINTF( + 1, + "Break call: read2_flg= %d func= %d lsn= %d csec= %d nsec= %d\n", + g_cdvdman_istruct.m_read2_flag, + g_cdvdman_cmdfunc, + g_cdvdman_istruct.m_cdvdman_lsn, + g_cdvdman_istruct.m_cdvdman_csec, + g_cdvdman_istruct.m_cdvdman_nsec); + if ( g_cdvdman_istruct.m_last_read_timeout ) + { + g_cdvdman_istruct.m_read2_flag = 0; + } + g_cdvdman_istruct.m_last_error = SCECdErABRT; + g_cdvdman_istruct.m_thread_id = GetThreadId(); + g_cdvdman_istruct.m_break_cdvdfsv_readchain = 1; + if ( g_cdvdman_istruct.m_dec_state ) + { + g_cdvdman_istruct.m_dec_shift = 0; + g_cdvdman_istruct.m_check_version = 0; + g_cdvdman_istruct.m_dec_state = 0; + sceCdDecSet(0, 0, 0); + } + g_cdvdman_istruct.m_recover_status = 0; + if ( QueryIntrContext() ) + { + iSetEventFlag(g_cdvdman_intr_efid, 0x29); + iCancelAlarm((unsigned int (*)(void *))read_timeout_alarm_cb, &g_cdvdman_read_alarm_cb_timeout); + } + else + { + SetEventFlag(g_cdvdman_intr_efid, 0x29); + CancelAlarm((unsigned int (*)(void *))read_timeout_alarm_cb, &g_cdvdman_read_alarm_cb_timeout); + } + if ( !g_cdvdman_istruct.m_wait_flag || g_cdvdman_istruct.m_last_read_timeout ) + { + if ( (dev5_mmio_hwport->m_dev5_reg_005 & 0xC0) == 0x40 ) + { + VERBOSE_KPRINTF(1, "cdvd: NonInter END\n"); + g_cdvdman_istruct.m_wait_flag = 1; + } + g_cdvdman_last_cmdfunc = g_cdvdman_cmdfunc; + g_cdvdman_cmdfunc = SCECdFuncBreak; + dev5_mmio_hwport->m_dev5_reg_007 = 1; + if ( g_cdvdman_istruct.m_last_read_timeout ) + { + DisableIntr(IOP_IRQ_DMA_CDVD, &oldstate); + } + g_cdvdman_istruct.m_drive_interupt_request = 0; + VERBOSE_KPRINTF(1, "cdvd: Abort command On\n"); + } + vSetEventFlag(g_ncmd_evid, 1); + CpuResumeIntr(state); + return 1; +} + +static int ncmd_timeout_alarm_cb(iop_sys_clock_t *sys_clock) +{ + KPRINTF("Cmd Time Out %d(msec)\n", sys_clock->lo / 0x9000); + sys_clock->lo = 0; + return 0; +} + +static int intrh_dma_3(cdvdman_internal_struct_t *s) +{ + int dmacbres; + int oldstate; + + s->m_dma3_param.m_dma3_msectors -= s->m_dma3_param.m_dma3_csectors; + dmacbres = s->m_dma3_param.m_dma3_callback ? s->m_dma3_param.m_dma3_callback() : 1; + s->m_cdvdman_dma3sec += s->m_dma3_param.m_dma3_csectors; + s->m_dma3_param.m_dma3_csectors = ((u32)s->m_read_chunk > (u32)s->m_dma3_param.m_dma3_msectors) ? + (u32)s->m_dma3_param.m_dma3_msectors : + (u32)s->m_read_chunk; + if ( dmacbres ) + { + if ( s->m_dma3_param.m_dma3_msectors ) + { + dmac_ch_set_chcr(3, 0); + dmac_ch_get_chcr(3); + dmac_ch_set_madr(3, (u32)s->m_dma3_param.m_dma3_maddress); + dmac_ch_set_bcr( + 3, + ((s->m_dma3_param.m_dma3_blkcount * s->m_dma3_param.m_dma3_csectors) << 16) | s->m_dma3_param.m_dma3_blkwords); + dmac_ch_set_chcr(3, 0x41000200); + dmac_ch_get_chcr(3); + iClearEventFlag(g_cdvdman_intr_efid, ~0x20); + } + else + { + DisableIntr(IOP_IRQ_DMA_CDVD, &oldstate); + iSetEventFlag(g_cdvdman_intr_efid, 0x20); + } + } + if ( !s->m_dma3_param.m_dma3_msectors && s->m_drive_interupt_request ) + { + cdvdman_intr_cb(s); + s->m_drive_interupt_request = 0; + } + return 1; +} + +static int cdvdman_setdma3(cdvdman_dma3_parameter_t *dma3_param) +{ + USE_DEV5_MMIO_HWPORT(); + + if ( (dmac_ch_get_chcr(3) & 0x1000000) ) + { + dev5_mmio_hwport->m_dev5_reg_007 = 1; + } + g_cdvdman_istruct.m_drive_interupt_request = 0; + g_cdvdman_istruct.m_dma3_param.m_dma3_blkwords = dma3_param->m_dma3_blkwords; + g_cdvdman_istruct.m_dma3_param.m_dma3_blkcount = dma3_param->m_dma3_blkcount; + g_cdvdman_istruct.m_dma3_param.m_dma3_maddress = dma3_param->m_dma3_maddress; + g_cdvdman_istruct.m_dma3_param.m_dma3_callback = dma3_param->m_dma3_callback; + g_cdvdman_istruct.m_dma3_param.m_dma3_csectors = dma3_param->m_dma3_csectors; + g_cdvdman_istruct.m_dma3_param.m_cdvdreg_howto = dma3_param->m_cdvdreg_howto; + g_cdvdman_istruct.m_dma3_param.m_dma3_msectors = dma3_param->m_dma3_msectors; + g_cdvdman_istruct.m_cdvdman_dma3sec = 0; + dmac_ch_set_chcr(3, 0); + dmac_ch_get_chcr(3); + if ( dma3_param->m_dma3_csectors ) + { + vClearEventFlag(g_cdvdman_intr_efid, ~0x20); + EnableIntr(IOP_IRQ_DMA_CDVD); + } + dev5_mmio_hwport->m_dev5_reg_006 = dma3_param->m_cdvdreg_howto; + dmac_ch_set_madr(3, (u32)dma3_param->m_dma3_maddress); + dmac_ch_set_bcr( + 3, + (dma3_param->m_dma3_blkcount * (dma3_param->m_dma3_csectors ? dma3_param->m_dma3_csectors : 1)) << 16 + | dma3_param->m_dma3_blkwords); + dmac_ch_set_chcr(3, 0x41000200); + return dmac_ch_get_chcr(3); +} + +static int +cdvdman_send_ncmd(int ncmd, const void *ndata, int ndlen, int func, cdvdman_dma3_parameter_t *dma3_param, int check_cb) +{ + int i; + u32 efbits; + USE_DEV5_MMIO_HWPORT(); + + if ( check_cb == 1 && PollEventFlag(g_ncmd_evid, 1, WEF_AND | WEF_CLEAR, &efbits) == KE_EVF_COND ) + { + return -1; + } + if ( + (dev5_mmio_hwport->m_dev5_reg_005 & 0xC0) != 0x40 || !g_cdvdman_istruct.m_wait_flag + || !(g_cdvdman_istruct.m_read2_flag != 1 || ncmd == 8) || !(g_cdvdman_istruct.m_read2_flag != 2 || ncmd == 6) ) + { + if ( check_cb == 1 ) + { + vSetEventFlag(g_ncmd_evid, 1); + } + VERBOSE_KPRINTF(1, "set_cd_commnad Error\tstat %02x\n", (u8)dev5_mmio_hwport->m_dev5_reg_005); + return -1; + } + g_cdvdman_iocache = 0; + if ( dma3_param ) + { + cdvdman_setdma3(dma3_param); + } + g_cdvdman_cmdfunc = func; + // The following call to sceCdGetDiskType was inlined + if ( + !g_cdvdman_minver_10700 && g_cdvdman_ncmd == 6 && ncmd && ncmd != g_cdvdman_ncmd && ncmd != 7 && ncmd != 14 + && ncmd != 8 && (sceCdGetDiskType() != SCECdCDDA || ncmd == 3) ) + { + g_cdvdman_ncmd_timeout.hi = 0; + g_cdvdman_ncmd_timeout.lo = 0x6978000; + vSetAlarm(&g_cdvdman_ncmd_timeout, (unsigned int (*)(void *))ncmd_timeout_alarm_cb, &g_cdvdman_ncmd_timeout); + while ( dev5_mmio_hwport->m_dev5_reg_00A != 10 ) + { + VERBOSE_KPRINTF(1, "Read Pause 1 chk status 0x%02x\n", dev5_mmio_hwport->m_dev5_reg_00A); + if ( !g_cdvdman_ncmd_timeout.lo ) + { + g_cdvdman_ncmd = ncmd; + if ( check_cb == 1 ) + { + vSetEventFlag(g_ncmd_evid, 1); + } + KPRINTF("Time Out Pause WAIT set_cd_commnad\n"); + return -1; + } + vDelayThread(1000); + } + vCancelAlarm((unsigned int (*)(void *))ncmd_timeout_alarm_cb, &g_cdvdman_ncmd_timeout); + } + g_cdvdman_ncmd = ncmd; + if ( g_cdvdman_istruct.m_dec_state ) + { + sceCdDecSet(!!g_cdvdman_istruct.m_dec_shift, 1, g_cdvdman_istruct.m_dec_shift); + } + g_cdvdman_istruct.m_last_read_timeout = 0; + g_cdvdman_istruct.m_cdvdman_command = ncmd; + g_cdvdman_istruct.m_last_error = 0; + g_cdvdman_istruct.m_wait_flag = 0; + g_cdvdman_istruct.m_thread_id = GetThreadId(); + if ( QueryIntrContext() ) + { + iClearEventFlag(g_cdvdman_intr_efid, ~1); + } + else + { + ClearEventFlag(g_cdvdman_intr_efid, ~1); + } + for ( i = 0; i < ndlen; i += 1 ) + { + dev5_mmio_hwport->m_dev5_reg_005 = ((u8 *)ndata)[i]; + } + dev5_mmio_hwport->m_dev5_reg_004 = ncmd; + if ( check_cb == 1 ) + { + vSetEventFlag(g_ncmd_evid, 1); + } + return 0; +} + +int sceCdApplyNCmd(u8 cmdNum, const void *inBuff, u16 inBuffSize) +{ + VERBOSE_KPRINTF(1, "Apply NCmd call cmd= 0x%02x\n", cmdNum); + while ( cdvdman_send_ncmd(cmdNum, inBuff, inBuffSize, 0, 0, 1) < 0 ) + { + vDelayThread(2000); + } + sceCdSync(4); + return 1; +} + +int sceCdCheckCmd(void) +{ + return g_cdvdman_istruct.m_wait_flag; +} + +static int cdvdman_mediactl(int code) +{ + int reg_00B_tmp_1; + int restmp; + u32 efbits; + int rdata; + USE_DEV5_MMIO_HWPORT(); + + rdata = 0; + if ( PollEventFlag(g_scmd_evid, 1, WEF_AND | WEF_CLEAR, &efbits) == KE_EVF_COND ) + { + return 0; + } + reg_00B_tmp_1 = dev5_mmio_hwport->m_dev5_reg_00B & 1; + if ( reg_00B_tmp_1 == g_cdvdman_chmedia ) + { + restmp = 0; + if ( g_cdvdman_chflags[code] ) + { + g_cdvdman_chflags[code] = 0; + restmp = 1; + } + } + else + { + unsigned int i; + + for ( i = 0; i < (sizeof(g_cdvdman_chflags) / sizeof(g_cdvdman_chflags[0])); i += 1 ) + { + g_cdvdman_chflags[i] = i != (unsigned int)code; + } + restmp = 1; + } + if ( ((dev5_mmio_hwport->m_dev5_reg_00A) & 1) != reg_00B_tmp_1 ) + { + while ( !set_prev_command(5, 0, 0, (char *)&rdata, 1, 0) || rdata ) + { + vDelayThread(4000); + } + } + g_cdvdman_chmedia = dev5_mmio_hwport->m_dev5_reg_00B & 1; + vSetEventFlag(g_scmd_evid, 1); + return restmp; +} + +int sceCdGetError(void) +{ + if ( g_cdvdman_istruct.m_last_error ) + { + VERBOSE_KPRINTF(1, "sceCdGetError: 0x%02x\n", (u8)g_cdvdman_istruct.m_last_error); + } + return (u8)g_cdvdman_istruct.m_last_error; +} + +#ifdef DEAD_CODE +int cdvdman_get_last_command() +{ + return (u8)g_cdvdman_istruct.m_cdvdman_command; +} +#endif + +int sceCdNop(void) +{ + return cdvdman_send_ncmd(0, 0, 0, 0, 0, 1) >= 0; +} + +#ifdef DEAD_CODE +int cdvdman_ncmd_sender_01() +{ + return cdvdman_send_ncmd(1, 0, 0, 0, 0, 1) >= 0; +} +#endif + +static int cdvdman_ncmd_sender_06() +{ + int i; + cdvdman_dma3_parameter_t dma3_param; + char ndata[11]; + + // The following call to sceCdGetDiskType was inlined + if ( sceCdGetDiskType() == SCECdNODISC ) + { + return 1; + } + for ( i = 0; i < 48; i += 8 ) + { + KPRINTF("CMD_READP call\n"); + ndata[0] = i + 17; + ndata[3] = 0; + ndata[2] = 0; + ndata[1] = 0; + ndata[4] = 8; + ndata[7] = 0; + ndata[6] = 0; + ndata[5] = 0; + ndata[8] = 0; + ndata[9] = 1; + ndata[10] = 0; + dma3_param.m_cdvdreg_howto = 128; + dma3_param.m_dma3_blkwords = 32; + dma3_param.m_dma3_blkcount = 128; + dma3_param.m_dma3_csectors = 0; + dma3_param.m_dma3_msectors = 0; + dma3_param.m_dma3_callback = 0; + dma3_param.m_dma3_maddress = g_cdvdman_ptoc; + if ( cdvdman_send_ncmd(6, ndata, sizeof(ndata), 5, &dma3_param, 1) < 0 ) + { + return 0; + } + sceCdSync(3); + } + return 1; +} + +int sceCdStandby(void) +{ + cdvdman_dma3_parameter_t dma3_param; + char ndata[11]; + + // The following call to sceCdGetDiskType was inlined + switch ( sceCdGetDiskType() ) + { + case SCECdPSCD: + case SCECdPSCDDA: + case SCECdPS2CD: + case SCECdPS2CDDA: + case SCECdPS2DVD: + ndata[0] = 16; + ndata[4] = 1; + ndata[9] = 1; + dma3_param.m_cdvdreg_howto = 128; + dma3_param.m_dma3_blkwords = 32; + dma3_param.m_dma3_blkcount = 16; + ndata[3] = 0; + ndata[2] = 0; + ndata[1] = 0; + ndata[7] = 0; + ndata[6] = 0; + ndata[5] = 0; + ndata[8] = 0; + ndata[10] = 0; + dma3_param.m_dma3_csectors = 0; + dma3_param.m_dma3_msectors = 0; + dma3_param.m_dma3_callback = 0; + dma3_param.m_dma3_maddress = g_cdvdman_ptoc; + return cdvdman_send_ncmd(6, ndata, sizeof(ndata), 5, &dma3_param, 1) >= 0; + default: + return cdvdman_send_ncmd(2, 0, 0, 5, 0, 1) >= 0; + } +} + +int sceCdStop(void) +{ + return cdvdman_send_ncmd(3, 0, 0, 6, 0, 1) >= 0; +} + +int sceCdPause(void) +{ + return cdvdman_send_ncmd(4, 0, 0, 7, 0, 1) >= 0; +} + +#ifdef DEAD_CODE +int cdvdman_ncmd_sender_0B() +{ + char ndata; + + ndata = 1; + return cdvdman_send_ncmd(11, &ndata, sizeof(ndata), 0, 0, 1) >= 0; +} +#endif + +static int readtoc_timeout_alarm_cb(iop_sys_clock_t *sys_clock) +{ + USE_DEV5_MMIO_HWPORT(); + + KPRINTF("Cmd Time Out %d(msec)\n", sys_clock->lo / 0x9000); + dev5_mmio_hwport->m_dev5_reg_007 = 1; + sys_clock->lo = 0; + return 0; +} + +static int cdvdman_readtoc(u8 *toc, int param, int func) +{ + int errcond; + cdvdman_dma3_parameter_t dma3_param; + iop_sys_clock_t sysclk; + char ndata; + + // The following call to sceCdGetDiskType was inlined + switch ( sceCdGetDiskType() ) + { + case SCECdPS2DVD: + case SCECdDVDVR: + case SCECdDVDV: + dma3_param.m_cdvdreg_howto = 132; + dma3_param.m_dma3_blkwords = 4; + dma3_param.m_dma3_blkcount = 129; + dma3_param.m_dma3_maddress = toc; + dma3_param.m_dma3_msectors = 0; + dma3_param.m_dma3_csectors = 0; + dma3_param.m_dma3_callback = 0; + ndata = param; + break; + case SCECdPSCD: + case SCECdPSCDDA: + case SCECdPS2CD: + case SCECdPS2CDDA: + dma3_param.m_cdvdreg_howto = 128; + dma3_param.m_dma3_blkwords = 32; + dma3_param.m_dma3_blkcount = 8; + dma3_param.m_dma3_maddress = toc; + dma3_param.m_dma3_msectors = 0; + dma3_param.m_dma3_csectors = 0; + dma3_param.m_dma3_callback = 0; + ndata = 0; + break; + case 0xFD: + break; + default: + return 0; + } + if ( cdvdman_send_ncmd(9, &ndata, sizeof(ndata), func, &dma3_param, 1) < 0 ) + { + return 0; + } + sysclk.hi = 0; + sysclk.lo = 0x15F90000; + vSetAlarm(&sysclk, (unsigned int (*)(void *))readtoc_timeout_alarm_cb, &sysclk); + sceCdSync(3); + vCancelAlarm((unsigned int (*)(void *))readtoc_timeout_alarm_cb, &sysclk); + errcond = !sceCdGetError(); + if ( g_cdvdman_minver_10700 && !sceCdPause() ) + { + return 0; + } + sceCdSync(3); + return errcond; +} + +static int cdvdman_gettoc(u8 *toc) +{ + return cdvdman_readtoc(toc, 0, 3); +} + +u32 sceCdGetReadPos(void) +{ + int sector_sizes[4]; + + sector_sizes[0] = 0x800; + sector_sizes[1] = 0x918; + sector_sizes[2] = 0x924; + if ( g_cdvdman_istruct.m_recover_status && g_cdvdman_istruct.m_recover_status != 3 ) + { + return 0; + } + if ( g_cdvdman_cmdfunc == SCECdFuncReadCDDA || g_cdvdman_cmdfunc == 12 ) + { + return dmac_ch_get_madr(3) - (uiptr)g_cdvdman_readbuf; + } + if ( g_cdvdman_istruct.m_read2_flag ) + { + return g_cdvdman_readptr * sector_sizes[g_cdvdman_istruct.m_cdvdman_pattern]; + } + if ( g_cdvdman_cmdfunc == SCECdFuncRead ) + { + return dmac_ch_get_madr(3) - (uiptr)g_cdvdman_readbuf; + } + return 0; +} + +static int cdvdman_speedctl(u32 spindlctrl, int dvdflag, u32 maxlsn) +{ + u32 maxlsn_chk; + + switch ( spindlctrl ) + { + case SCECdSpinStm: + return dvdflag ? 2 : 4; + case SCECdSpinNom: + if ( !dvdflag ) + { + return 133; + } + if ( g_cdvdman_minver_10700 ) + { + return 131; + } + maxlsn_chk = 0x128000; + if ( g_cdvdman_istruct.m_opo_or_para ) + { + maxlsn -= (maxlsn >= (u32)g_cdvdman_istruct.m_layer_1_lsn) ? g_cdvdman_istruct.m_layer_1_lsn : 0; + maxlsn_chk = 0x165000; + } + if ( maxlsn >= maxlsn_chk ) + { + VERBOSE_KPRINTF(1, "Kprob Spd D lsn= %d\n", maxlsn); + return 130; + } + return 133; + case SCECdSpinX1: + case 0xE: + return 1; + case SCECdSpinX2: + return 2; + case SCECdSpinX4: + return dvdflag ? 2 : 131; + case SCECdSpinX12: + return dvdflag ? 3 : 4; + case SCECdSpinNm2: + return 64; + case 0xC: + return dvdflag ? 4 : 2; + case 0xF: + return 130; + case 0x10: + return dvdflag ? 130 : 131; + case 0x11: + return dvdflag ? 130 : 132; + case 0x12: + return dvdflag ? 1 : 131; + case SCECdSpinMx: + return dvdflag ? 3 : 5; + default: + return dvdflag ? 131 : 133; + } +} + +static int cdvdman_isdvd() +{ + // The following call to sceCdGetDiskType was inlined + switch ( sceCdGetDiskType() ) + { + case SCECdPSCD: + case SCECdPSCDDA: + case SCECdPS2CD: + case SCECdPS2CDDA: + g_cdvdman_istruct.m_tray_is_open = 1; + return 0; + case SCECdPS2DVD: + g_cdvdman_istruct.m_tray_is_open = 1; + return 1; + case SCECdDVDVR: + case SCECdDVDV: + g_cdvdman_istruct.m_tray_is_open = 1; + return 1; + case SCECdCDDA: + g_cdvdman_istruct.m_tray_is_open = 1; + return 0; + default: + return 0; + } +} + +static int sceCdRead0_Rty(u32 lsn, u32 nsec, void *buf, const sceCdRMode *mode, int ncmd, int dintrsec, void *func) +{ + cdvdman_dma3_parameter_t dma3_param; + char ndata[11]; + + g_cdvdman_readbuf = buf; + VERBOSE_KPRINTF(1, "sceCdRead0_Rty Lsn:%d nsec:%d dintrnsec %d func %08x\n", lsn, nsec, dintrsec, func); + *(u32 *)ndata = lsn; + *(u32 *)&ndata[4] = nsec; + ndata[8] = mode->trycount; + ndata[9] = cdvdman_speedctl(mode->spindlctrl, cdvdman_isdvd(), lsn + nsec); + dma3_param.m_dma3_csectors = dintrsec; + dma3_param.m_dma3_callback = (int (*)(void))func; + dma3_param.m_dma3_msectors = nsec; + dma3_param.m_dma3_maddress = buf; + dma3_param.m_dma3_blkcount = (!(u16)dintrsec) ? nsec : 1; + if ( ncmd == 6 ) + { + ndata[10] = mode->datapattern; + switch ( mode->datapattern ) + { + case 1: + dma3_param.m_dma3_blkwords = 6; + dma3_param.m_dma3_blkcount *= 97; + dma3_param.m_cdvdreg_howto = 134; + break; + case 2: + dma3_param.m_dma3_blkwords = 15; + dma3_param.m_dma3_blkcount *= 39; + dma3_param.m_cdvdreg_howto = 143; + break; + case 0: + default: + dma3_param.m_dma3_blkwords = 32; + dma3_param.m_dma3_blkcount *= 16; + dma3_param.m_cdvdreg_howto = 128; + break; + } + if ( cdvdman_send_ncmd(ncmd, ndata, sizeof(ndata), 1, &dma3_param, 0) >= 0 ) + { + return 1; + } + } + if ( ncmd == 8 ) + { + dma3_param.m_dma3_blkwords = 12; + dma3_param.m_dma3_blkcount *= 43; + dma3_param.m_cdvdreg_howto = 140; + ndata[10] = 0; + if ( cdvdman_send_ncmd(ncmd, ndata, sizeof(ndata), 14, &dma3_param, 0) >= 0 ) + { + return 1; + } + } + return 0; +} + +int sceCdRead0(u32 lsn, u32 sectors, void *buffer, sceCdRMode *mode, int csec, void *callback) +{ + cdvdman_dma3_parameter_t dma3_param; + char ndata[11]; + u32 efbits; + + if ( PollEventFlag(g_ncmd_evid, 1, WEF_AND | WEF_CLEAR, &efbits) == KE_EVF_COND ) + { + return 0; + } + VERBOSE_KPRINTF( + 1, + "DVD/CD sceCdRead0 sec %d num %d spin %d trycnt %d dptn %d adr %08x\n", + lsn, + sectors, + mode->spindlctrl, + mode->trycount, + mode->datapattern, + buffer); + g_cdvdman_readbuf = buffer; + dma3_param.m_dma3_csectors = (csec && (sectors < (u32)csec)) ? sectors : (u32)csec; + dma3_param.m_dma3_callback = (int (*)(void))callback; + dma3_param.m_dma3_msectors = sectors; + dma3_param.m_dma3_blkcount = (!csec) ? sectors : 1; + switch ( mode->datapattern ) + { + case SCECdSecS2328: + dma3_param.m_dma3_blkwords = 6; + dma3_param.m_dma3_blkcount *= 97; + dma3_param.m_cdvdreg_howto = 134; + break; + case SCECdSecS2340: + dma3_param.m_dma3_blkwords = 15; + dma3_param.m_dma3_blkcount *= 39; + dma3_param.m_cdvdreg_howto = 143; + break; + case SCECdSecS2048: + default: + dma3_param.m_dma3_blkwords = 32; + dma3_param.m_dma3_blkcount *= 16; + dma3_param.m_cdvdreg_howto = 128; + break; + } + // The following call to sceCdGetDiskType was inlined + switch ( sceCdGetDiskType() ) + { + case SCECdPSCD: + case SCECdPSCDDA: + case SCECdPS2CD: + case SCECdPS2CDDA: + if ( g_cdvdman_mmode != SCECdMmodeCd && g_cdvdman_mmode != 0xFF ) + { + vSetEventFlag(g_ncmd_evid, 1); + return 0; + } + g_cdvdman_istruct.m_dvd_flag = 0; + break; + case SCECdPS2DVD: + if ( g_cdvdman_mmode != SCECdMmodeDvd && g_cdvdman_mmode != 0xFF ) + { + vSetEventFlag(g_ncmd_evid, 1); + return 0; + } + g_cdvdman_istruct.m_dvd_flag = 1; + break; + default: + vSetEventFlag(g_ncmd_evid, 1); + return 0; + } + g_cdvdman_istruct.m_read_mode = *mode; + g_cdvdman_istruct.m_read_callback = callback; + g_cdvdman_istruct.m_read_chunk = dma3_param.m_dma3_csectors; + g_cdvdman_istruct.m_read_lsn = lsn; + g_cdvdman_istruct.m_read_sectors = sectors; + *(u32 *)ndata = lsn; + *(u32 *)&ndata[4] = sectors; + ndata[8] = mode->trycount; + ndata[9] = cdvdman_speedctl(mode->spindlctrl, g_cdvdman_istruct.m_dvd_flag, lsn + sectors); + g_cdvdman_istruct.m_read_buf = buffer; + ndata[10] = mode->datapattern; + dma3_param.m_dma3_maddress = buffer; + VERBOSE_KPRINTF(1, "Read Command call\n"); + if ( cdvdman_send_ncmd(6, ndata, sizeof(ndata), 1, &dma3_param, 0) < 0 ) + { + vSetEventFlag(g_ncmd_evid, 1); + return 0; + } + vSetEventFlag(g_ncmd_evid, 1); + return 1; +} + +static int read_cdvd_cb(cdvdman_internal_struct_t *common) +{ + int sblock; + int i; + u32 cdreadlsn; + int syncdec_res_1; + sceCdlLOCCD cdrloc; + + sblock = 0; + for ( i = 0; i < common->m_dma3_param.m_dma3_csectors; i += 1 ) + { + char syncdec_res_4; + int errlsn; + + syncdec_res_4 = 0; + if ( common->m_read2_flag == 3 ) + { + sblock = 0x924; + cdrloc.minute = cdvdman_syncdec( + common->m_dec_state, common->m_check_version, common->m_dec_shift, g_cdvdman_ptoc[(i * sblock)]); + cdrloc.second = cdvdman_syncdec( + common->m_dec_state, common->m_check_version, common->m_dec_shift, g_cdvdman_ptoc[(i * sblock) + 1]); + cdrloc.sector = cdvdman_syncdec( + common->m_dec_state, common->m_check_version, common->m_dec_shift, g_cdvdman_ptoc[(i * sblock) + 2]); + cdreadlsn = sceCdPosToInt(&cdrloc); + } + else + { + sblock = 0x810; + syncdec_res_1 = (u8)cdvdman_syncdec( + common->m_dec_state, common->m_check_version, common->m_dec_shift, g_cdvdman_ptoc[(i * sblock) + 3]); + syncdec_res_1 += + (u8)cdvdman_syncdec( + common->m_dec_state, common->m_check_version, common->m_dec_shift, g_cdvdman_ptoc[(i * sblock) + 2]) + << 8; + syncdec_res_1 += + (u8)cdvdman_syncdec( + common->m_dec_state, common->m_check_version, common->m_dec_shift, g_cdvdman_ptoc[(i * sblock) + 1]) + << 16; + syncdec_res_4 = cdvdman_syncdec( + common->m_dec_state, common->m_check_version, common->m_dec_shift, g_cdvdman_ptoc[(i * sblock)]); + if ( !common->m_cdvdman_dma3sec && !common->m_interupt_read_state ) + { + common->m_interupt_read_state = (syncdec_res_4 & 0xC) | (((syncdec_res_4 & 0xC) && i) ? 0x80 : 0); + } + cdreadlsn = (syncdec_res_1 - 0x30000) + (( common->m_opo_or_para && ((unsigned int)(common->m_cdvdman_lsn + common->m_cdvdman_csec + i) >= common->m_layer_1_lsn && common->m_opo_or_para == 1) ) ? common->m_layer_1_lsn : 0); + } + errlsn = common->m_cdvdman_lsn + common->m_cdvdman_csec + common->m_cdvdman_dma3sec + i; + if ( cdreadlsn != (u32)errlsn ) + { + VERBOSE_KPRINTF( + 1, "Read_IOP Sector_ID error lsn= %d readlsn= %d layer= %d\n", errlsn, cdreadlsn, (syncdec_res_4 & 1)); + break; + } + } + if ( i == common->m_dma3_param.m_dma3_csectors ) + { + unsigned int size; + + size = 0; + switch ( common->m_cdvdman_pattern ) + { + case 0: + size = 0x800; + break; + case 1: + default: + size = 0x918; + break; + case 2: + optimized_memcpy( + &((char *)(common->m_cdvdman_rbuffer))[0x924 * common->m_cdvdman_dma3sec], + (const char *)g_cdvdman_ptoc, + 0x924 * i); + break; + } + if ( size ) + { + for ( i = 0; i < common->m_dma3_param.m_dma3_csectors; i += 1 ) + { + optimized_memcpy( + &((char *)(common->m_cdvdman_rbuffer))[(common->m_cdvdman_dma3sec + i) * size], + (const char *)&g_cdvdman_ptoc[12 + (i * sblock)], + size); + } + } + g_cdvdman_readptr = common->m_cdvdman_csec + common->m_cdvdman_dma3sec; + } + else + { + common->m_sync_error += 1; + } + return 1; +} + +static int cdvdman_read(u32 lsn, u32 sectors, void *buf, sceCdRMode *mode, int decflag, int shift, int ef1, int ef2) +{ + int read_res; + int state; + int scres_unused; + int dvd; + + dvd = cdvdman_isdvd(); + if ( dvd ) + { + if ( !DvdDual_infochk() ) + { + if ( ef1 ) + { + vSetEventFlag(ef1, ef2); + } + return 0; + } + lsn = sceCdLsnDualChg(lsn); + } + else if ( mode->datapattern == SCECdSecS2328 || (g_cdvdman_cd36key && !g_cdvdman_istruct.m_dec_state) ) + { + int read0_res; + + if ( g_cdvdman_cd36key && !g_cdvdman_istruct.m_dec_state && mode->spindlctrl == SCECdSpinNom ) + { + mode->spindlctrl = SCECdSpinStm; + } + CpuSuspendIntr(&state); + read0_res = sceCdRead0(lsn, sectors, buf, mode, 0, 0); + if ( ef1 ) + { + vSetEventFlag(ef1, ef2); + } + CpuResumeIntr(state); + return read0_res; + } + CpuSuspendIntr(&state); + if ( (sceCdDiskReady(8) & 0xC0) != 0x40 || g_cdvdman_istruct.m_read2_flag ) + { + VERBOSE_KPRINTF( + 1, + "sceCdRead: Double Booking error r2f= %d waf= %d\n", + g_cdvdman_istruct.m_read2_flag, + g_cdvdman_istruct.m_wait_flag); + if ( ef1 ) + { + vSetEventFlag(ef1, ef2); + } + CpuResumeIntr(state); + return 0; + } + if ( decflag ) + { + g_cdvdman_istruct.m_dec_shift = shift; + g_cdvdman_istruct.m_dec_state = 1; + } + g_cdvdman_readbuf = buf; + g_cdvdman_readptr = 0; + g_cdvdman_istruct.m_cdvdman_lsn = lsn; + g_cdvdman_istruct.m_cdvdman_csec = 0; + g_cdvdman_istruct.m_cdvdman_nsec = sectors; + g_cdvdman_istruct.m_cdvdman_rbuffer = (int)buf; + g_cdvdman_istruct.m_cdvdman_pattern = dvd ? SCECdSecS2048 : mode->datapattern; + g_cdvdman_istruct.m_cdvdman_cdrmode.trycount = mode->trycount; + g_cdvdman_istruct.m_cdvdman_cdrmode.spindlctrl = mode->spindlctrl; + g_cdvdman_istruct.m_cdvdman_cdrmode.datapattern = dvd ? SCECdSecS2048 : SCECdSecS2340; + g_cdvdman_istruct.m_read2_flag = dvd ? 1 : 3; + g_cdvdman_istruct.m_sync_error = 0; + g_cdvdman_istruct.m_interupt_read_state = 0; + g_cdvdman_istruct.m_cdvdman_rsec = (sectors >= 0x41) ? (((lsn & 0xF)) ? (0x10 - (lsn & 0xF)) : 0x40) : sectors; + g_cdvdman_read_alarm_cb_timeout.hi = 0; + g_cdvdman_read_alarm_cb_timeout.lo = 0x9000 * sceCdSC(0xFFFFFFF1, &scres_unused); + vSetAlarm( + &g_cdvdman_read_alarm_cb_timeout, + (unsigned int (*)(void *))read_timeout_alarm_cb, + &g_cdvdman_read_alarm_cb_timeout); + read_res = (dvd ? sceCdRV : sceCdRead0)( + lsn, + g_cdvdman_istruct.m_cdvdman_rsec, + g_cdvdman_ptoc, + dvd ? mode : &g_cdvdman_istruct.m_cdvdman_cdrmode, + 0x10, + read_cdvd_cb); + if ( !read_res ) + { + g_cdvdman_istruct.m_last_error = SCECdErREADCFR; + g_cdvdman_istruct.m_cdvdman_rsec = 0; + g_cdvdman_istruct.m_read2_flag = 0; + if ( g_cdvdman_istruct.m_dec_state ) + { + g_cdvdman_istruct.m_dec_shift = 0; + g_cdvdman_istruct.m_check_version = 0; + g_cdvdman_istruct.m_dec_state = 0; + sceCdDecSet(0, 0, 0); + } + vCancelAlarm((unsigned int (*)(void *))read_timeout_alarm_cb, &g_cdvdman_read_alarm_cb_timeout); + } + if ( ef1 ) + { + vSetEventFlag(ef1, ef2); + } + CpuResumeIntr(state); + return !!read_res; +} + +int sceCdRE(unsigned int lsn, unsigned int sectors, void *buf, sceCdRMode *mode) +{ + return cdvdman_read(lsn, sectors, buf, mode, 0, 0, 0, 0); +} + +int sceCdRead(u32 lbn, u32 sectors, void *buffer, sceCdRMode *mode) +{ + iop_event_info_t efinfo; + int state; + + // Unofficial: initialize to 0 + memset(&efinfo, 0, sizeof(efinfo)); + CpuSuspendIntr(&state); + vReferEventFlagStatus(g_fio_fsv_evid, &efinfo); + if ( !(efinfo.currBits & 1) ) + { + CpuResumeIntr(state); + return 0; + } + vClearEventFlag(g_fio_fsv_evid, ~1); + CpuResumeIntr(state); + return cdvdman_read(lbn, sectors, buffer, mode, 0, 0, g_fio_fsv_evid, 1); +} + +static int cdvdman_syncdec(int decflag, int decxor, int shift, u32 data) +{ + return decflag ? ((u8)(((u8)data << (shift % 8)) | ((u8)data >> (8 - shift % 8))) ^ (u8)decxor) : (u8)data; +} + +static void Read2intrCDVD(int read2_flag) +{ + iCancelAlarm((unsigned int (*)(void *))read_timeout_alarm_cb, &g_cdvdman_read_alarm_cb_timeout); + if ( g_cdvdman_istruct.m_last_error || g_cdvdman_retries >= 5 ) + { + if ( !g_cdvdman_istruct.m_last_error ) + { + g_cdvdman_istruct.m_last_error = SCECdErREADCF; + } + g_cdvdman_istruct.m_read2_flag = 0; + g_cdvdman_retries = 0; + g_cdvdman_rtindex = 0; + g_cdvdman_readptr = 0; + if ( g_cdvdman_istruct.m_dec_state ) + { + g_cdvdman_istruct.m_dec_shift = 0; + g_cdvdman_istruct.m_check_version = 0; + g_cdvdman_istruct.m_dec_state = 0; + } + g_cdvdman_istruct.m_interupt_read_state = 0; + } + else if ( !g_cdvdman_istruct.m_interupt_read_state || g_cdvdman_istruct.m_cdvdman_csec ) + { + int scres_unused; + + g_cdvdman_istruct.m_interupt_read_state = 0; + if ( g_cdvdman_istruct.m_sync_error ) + { + u32 lsn_tmp; + + if ( !g_cdvdman_rtindex ) + { + g_cdvdman_rtindex = 3; + g_cdvdman_retries += 1; + } + g_cdvdman_istruct.m_sync_error = 0; + lsn_tmp = g_cdvdman_istruct.m_cdvdman_lsn + g_cdvdman_istruct.m_cdvdman_csec; + if ( lsn_tmp >= 0x30 ) + { + lsn_tmp -= 0x10 * (g_cdvdman_rtindex - 1); + } + else + { + lsn_tmp += 0x10 * (g_cdvdman_rtindex - 1); + } + if ( ((read2_flag == 3) ? sceCdRead0 : sceCdRV)( + lsn_tmp, + g_cdvdman_istruct.m_cdvdman_rsec, + g_cdvdman_ptoc, + &g_cdvdman_istruct.m_cdvdman_cdrmode, + 0x10, + read_cdvd_cb) ) + { + g_cdvdman_read_alarm_cb_timeout.hi = 0; + g_cdvdman_read_alarm_cb_timeout.lo = 0x9000 * sceCdSC(0xFFFFFFF1, &scres_unused); + iSetAlarm( + &g_cdvdman_read_alarm_cb_timeout, + (unsigned int (*)(void *))read_timeout_alarm_cb, + &g_cdvdman_read_alarm_cb_timeout); + } + else + { + VERBOSE_KPRINTF(1, "Retry Read Fatal Error\n"); + g_cdvdman_istruct.m_last_error = SCECdErNORDY; + g_cdvdman_istruct.m_read2_flag = 0; + g_cdvdman_retries = 0; + g_cdvdman_rtindex = 0; + g_cdvdman_readptr = 0; + if ( g_cdvdman_istruct.m_dec_state ) + { + g_cdvdman_istruct.m_dec_shift = 0; + g_cdvdman_istruct.m_check_version = 0; + g_cdvdman_istruct.m_dec_state = 0; + } + } + g_cdvdman_rtindex -= !!g_cdvdman_rtindex; + } + else + { + int cdsectorsz; + + g_cdvdman_retries = 0; + switch ( g_cdvdman_istruct.m_cdvdman_pattern ) + { + case 0: + cdsectorsz = 0x800; + break; + case 1: + default: + cdsectorsz = 0x918; + break; + case 2: + cdsectorsz = 0x924; + break; + } + g_cdvdman_istruct.m_cdvdman_rbuffer += cdsectorsz * g_cdvdman_istruct.m_cdvdman_rsec; + g_cdvdman_istruct.m_cdvdman_csec += g_cdvdman_istruct.m_cdvdman_rsec; + if ( (unsigned int)g_cdvdman_istruct.m_cdvdman_csec < (unsigned int)g_cdvdman_istruct.m_cdvdman_nsec ) + { + g_cdvdman_istruct.m_cdvdman_rsec = + ((unsigned int)(g_cdvdman_istruct.m_cdvdman_csec + 0x40) < (unsigned int)g_cdvdman_istruct.m_cdvdman_nsec) ? + 0x40 : + (g_cdvdman_istruct.m_cdvdman_nsec - g_cdvdman_istruct.m_cdvdman_csec); + if ( ((read2_flag == 3) ? sceCdRead0 : sceCdRV)( + g_cdvdman_istruct.m_cdvdman_lsn + g_cdvdman_istruct.m_cdvdman_csec, + g_cdvdman_istruct.m_cdvdman_rsec, + g_cdvdman_ptoc, + &g_cdvdman_istruct.m_cdvdman_cdrmode, + 0x10, + read_cdvd_cb) ) + { + g_cdvdman_read_alarm_cb_timeout.hi = 0; + g_cdvdman_read_alarm_cb_timeout.lo = 0x9000 * sceCdSC(0xFFFFFFF1, &scres_unused); + iSetAlarm( + &g_cdvdman_read_alarm_cb_timeout, + (unsigned int (*)(void *))read_timeout_alarm_cb, + &g_cdvdman_read_alarm_cb_timeout); + } + else + { + g_cdvdman_istruct.m_last_error = SCECdErNORDY; + g_cdvdman_istruct.m_read2_flag = 0; + g_cdvdman_readptr = 0; + if ( g_cdvdman_istruct.m_dec_state ) + { + g_cdvdman_istruct.m_dec_shift = 0; + g_cdvdman_istruct.m_check_version = 0; + g_cdvdman_istruct.m_dec_state = 0; + } + } + } + else + { + g_cdvdman_istruct.m_read2_flag = 0; + g_cdvdman_readptr = 0; + if ( g_cdvdman_istruct.m_dec_state ) + { + g_cdvdman_istruct.m_dec_shift = 0; + g_cdvdman_istruct.m_check_version = 0; + g_cdvdman_istruct.m_dec_state = 0; + } + } + } + } + else + { + g_cdvdman_istruct.m_last_error = ((g_cdvdman_istruct.m_interupt_read_state & 0x80)) ? SCECdErREADCF : SCECdErIPI; + g_cdvdman_istruct.m_interupt_read_state = 0; + VERBOSE_KPRINTF(1, "IPIerr emu Hit Dummy Err %02x\n", (u8)g_cdvdman_istruct.m_last_error); + g_cdvdman_istruct.m_read2_flag = 0; + g_cdvdman_retries = 0; + g_cdvdman_rtindex = 0; + g_cdvdman_readptr = 0; + if ( g_cdvdman_istruct.m_dec_state ) + { + g_cdvdman_istruct.m_dec_shift = 0; + g_cdvdman_istruct.m_check_version = 0; + g_cdvdman_istruct.m_dec_state = 0; + } + } +} + +int sceCdReadChain(sceCdRChain *tag, sceCdRMode *mode) +{ + (void)tag; + (void)mode; + + return 0; +} + +static int cdvdman_readfull(u32 lsn, u32 sectors, void *buf, const sceCdRMode *mode, int flag) +{ + cdvdman_dma3_parameter_t dma3_param; + char ndata[11]; + + VERBOSE_KPRINTF(1, "lsn:%d nsec:%d buf:% cmdmode:%d\n", lsn, sectors, buf, flag); + g_cdvdman_readbuf = buf; + dma3_param.m_dma3_csectors = 0; + dma3_param.m_dma3_msectors = 0; + dma3_param.m_dma3_callback = 0; + dma3_param.m_dma3_blkcount = sectors; + switch ( mode->datapattern ) + { + case SCECdSecS2328: + dma3_param.m_dma3_blkwords = 8; + dma3_param.m_dma3_blkcount *= 74; + dma3_param.m_cdvdreg_howto = 136; + break; + case SCECdSecS2340: + dma3_param.m_dma3_blkwords = 12; + dma3_param.m_dma3_blkcount *= 51; + dma3_param.m_cdvdreg_howto = 140; + break; + case SCECdSecS2048: + default: + dma3_param.m_dma3_blkwords = 12; + dma3_param.m_dma3_blkcount *= 49; + dma3_param.m_cdvdreg_howto = 140; + break; + } + // The following call to sceCdGetDiskType() was inlined + switch ( sceCdGetDiskType() ) + { + case SCECdPSCDDA: + case SCECdPS2CDDA: + case SCECdCDDA: + break; + default: + return 0; + } + if ( g_cdvdman_mmode != SCECdMmodeCd && g_cdvdman_mmode != 0xFF ) + { + return 0; + } + *(u32 *)ndata = lsn; + *(u32 *)&ndata[4] = sectors; + ndata[8] = mode->trycount; + ndata[9] = cdvdman_speedctl(mode->spindlctrl, 0, lsn + sectors); + dma3_param.m_dma3_maddress = buf; + ndata[10] = mode->datapattern; + return cdvdman_send_ncmd((!flag) ? 7 : 14, ndata, sizeof(ndata), (!flag) ? 2 : 12, &dma3_param, 1) >= 0; +} + +int sceCdReadCDDA(u32 lbn, u32 sectors, void *buffer, sceCdRMode *mode) +{ + return cdvdman_readfull(lbn, sectors, buffer, mode, 0); +} + +int sceCdRV(u32 lsn, u32 sectors, void *buf, sceCdRMode *mode, int arg5, void *cb) +{ + cdvdman_dma3_parameter_t dma3_param; + char ndata[11]; + u32 efbits; + + // The following call to sceCdGetDiskType was inlined + if ( + sceCdGetDiskType() != SCECdPS2DVD || (g_cdvdman_mmode != SCECdMmodeDvd && g_cdvdman_mmode != 0xFF) + || (PollEventFlag(g_ncmd_evid, 1, WEF_AND | WEF_CLEAR, &efbits) == KE_EVF_COND) ) + { + return 0; + } + VERBOSE_KPRINTF( + 1, "RV read: sec %d num %d spin %d trycnt %d addr %08x\n", lsn, sectors, mode->spindlctrl, mode->trycount, buf); + g_cdvdman_readbuf = buf; + g_cdvdman_istruct.m_dvd_flag = cdvdman_isdvd(); + g_cdvdman_istruct.m_read_mode = *mode; + g_cdvdman_istruct.m_read_lsn = lsn; + g_cdvdman_istruct.m_read_sectors = sectors; + *(u32 *)ndata = lsn; + *(u32 *)&ndata[4] = sectors; + ndata[8] = mode->trycount; + ndata[9] = cdvdman_speedctl(mode->spindlctrl, 1, lsn + sectors); + ndata[10] = 0; + dma3_param.m_dma3_csectors = (arg5 && (sectors < (u32)arg5)) ? sectors : (u32)arg5; + g_cdvdman_istruct.m_read_chunk = dma3_param.m_dma3_csectors; + dma3_param.m_cdvdreg_howto = 140; + dma3_param.m_dma3_blkwords = 12; + g_cdvdman_istruct.m_read_buf = buf; + dma3_param.m_dma3_blkcount = (!arg5) ? sectors : 1; + dma3_param.m_dma3_blkcount *= 43; + dma3_param.m_dma3_msectors = sectors; + dma3_param.m_dma3_callback = (int (*)(void))cb; + g_cdvdman_istruct.m_read_callback = cb; + dma3_param.m_dma3_maddress = buf; + if ( cdvdman_send_ncmd(8, ndata, sizeof(ndata), 14, &dma3_param, 0) < 0 ) + { + vSetEventFlag(g_ncmd_evid, 1); + return 0; + } + vSetEventFlag(g_ncmd_evid, 1); + return 1; +} + +int sceCdSeek(u32 lbn) +{ + u32 ndata; + + ndata = lbn; + if ( cdvdman_isdvd() ) + { + if ( !DvdDual_infochk() ) + { + return 0; + } + ndata = sceCdLsnDualChg(ndata); + } + return cdvdman_send_ncmd(5, &ndata, 4, 4, 0, 1) >= 0; +} + +int sceCdRI(u8 *buffer, u32 *result) +{ + int command; + u8 rdata[9]; + + command = set_prev_command(18, 0, 0, (char *)rdata, sizeof(rdata), 1); + *result = rdata[0]; + memcpy(buffer, &rdata[1], 8); + return command; +} + +int sceCdRM(char *buffer, u32 *status) +{ + int command; + int cmd_tmp2; + u8 rdata[9]; + char wdata; + u32 efbits; + + *status = 0; + if ( sceCdGetMVersion(rdata, status) != 1 || (unsigned int)(rdata[3] | (rdata[2] << 8) | (rdata[1] << 16)) < 0x10500 ) + { + strcpy(buffer, "M_NAME_UNKNOWN"); + buffer[15] = 0; + *status |= 0x40; + return 1; + } + if ( PollEventFlag(g_scmd_evid, 1, WEF_AND | WEF_CLEAR, &efbits) == KE_EVF_COND ) + { + return 0; + } + DelayThread(2000); + wdata = 0; + command = set_prev_command(0x17, &wdata, sizeof(wdata), (char *)rdata, sizeof(rdata), 0); + *status = rdata[0]; + memcpy(buffer, &rdata[1], 8); + DelayThread(2000); + wdata = 8; + cmd_tmp2 = set_prev_command(0x17, &wdata, sizeof(wdata), (char *)rdata, sizeof(rdata), 0); + *status |= rdata[0]; + memcpy(&buffer[8], &rdata[1], 8); + vSetEventFlag(g_scmd_evid, 1); + return command ? (!!cmd_tmp2) : 0; +} + +static int sceCdGetMVersion(u8 *buffer, u32 *status) +{ + int command; + char rdata[4]; + char wdata[1]; + + wdata[0] = 0; + command = set_prev_command(3, wdata, sizeof(wdata), rdata, sizeof(rdata), 1); + *status = rdata[0] & 0x80; + VERBOSE_KPRINTF(1, "MV 0x%02x,0x%02x,0x%02x,0x%02x\n", (u8)rdata[0], (u8)rdata[1], (u8)rdata[2], (u8)rdata[3]); + rdata[0] &= ~0x80; + memcpy(buffer, rdata, sizeof(rdata)); + return command; +} + +static int cdvdman_scmd_sender_03_48(u8 *buf, u32 *status) +{ + int retval; + char rdata[2]; + char wdata[2]; + + if ( g_cdvdman_minver_50000 ) + { + return 0; + } + wdata[0] = 48; + wdata[1] = 2; + retval = set_prev_command(3, wdata, sizeof(wdata), rdata, sizeof(rdata), 1); + *status = (u8)rdata[0]; + *buf = rdata[1]; + return retval; +} + +int sceCdMmode(int media) +{ + g_cdvdman_mmode = media; + return 1; +} + +int sceCdCancelPOffRdy(u32 *result) +{ + char wdata[8]; + + memset(wdata, 0, sizeof(wdata)); + *result = 0; + return g_cdvdman_minver_20400 ? set_prev_command(27, wdata, 0, (char *)result, 1, 1) : 1; +} + +static unsigned int power_off_alarm_cb(cdvdman_internal_struct_t *s) +{ + s->m_power_flag = 0; + return 0; +} + +int sceCdPowerOff(u32 *result) +{ + int command; + + *result = 0; + VERBOSE_KPRINTF(1, "sceCdPowerOff Call\n"); + if ( !g_cdvdman_minver_x_model_15 ) + { + while ( (sceCdStatus() & SCECdStatShellOpen) ) + { + u32 traychk; + + sceCdTrayReq(SCECdTrayClose, &traychk); + vDelayThread(250000); + } + } + command = set_prev_command(0xF, 0, 0, (char *)result, 1, 1); + if ( !command ) + { + g_cdvdman_istruct.m_power_flag = 0; + return 0; + } + KPRINTF("PowerOff Start...\n"); + g_cdvdman_istruct.m_power_flag = 1; + g_cdvdman_power_off_timeout.hi = 0; + g_cdvdman_power_off_timeout.lo = 0xAFC8000; + vSetAlarm(&g_cdvdman_power_off_timeout, (unsigned int (*)(void *))power_off_alarm_cb, &g_cdvdman_istruct); + return command; +} + +int sceCdCtrlADout(int mode, u32 *status) +{ + char wdata; + + wdata = mode; + *status = 0; + DelayThread(2000); + VERBOSE_KPRINTF(1, "Audio Digital Out: Set param %d\n", wdata); + return set_prev_command(20, &wdata, sizeof(wdata), (char *)status, 1, 1); +} + +int sceCdReadClock(sceCdCLOCK *clock) +{ + int retval; + + retval = set_prev_command(8, 0, 0, (char *)clock, 8, 1); + clock->pad = 0; + clock->month &= 0x7F; + if ( retval && !clock->stat ) + { + memcpy(&g_cdvdman_clock, clock, sizeof(g_cdvdman_clock)); + g_cdvdman_clk_flg = 1; + } + else if ( g_cdvdman_clk_flg ) + { + memcpy(clock, &g_cdvdman_clock, sizeof(g_cdvdman_clock)); + } + else + { + clock->month = 3; + clock->day = 4; + clock->hour = 5; + clock->minute = 6; + clock->year = 0; + clock->second = 7; + } + return retval; +} + +int sceCdRC(sceCdCLOCK *clock) +{ + return set_prev_command(8, 0, 0, (char *)clock, 8, 1); +} + +int sceCdTrayReq(int param, u32 *traychk) +{ + char wdata; + char rdata; + + if ( param == SCECdTrayCheck ) + { + *traychk = cdvdman_mediactl(1); + VERBOSE_KPRINTF(1, "Tray Req test = %d\n", *traychk); + return 1; + } + if ( g_cdvdman_minver_x_model_15 && param == SCECdTrayClose ) + { + return 1; + } + wdata = param; + g_cdvdman_iocache = 0; + if ( set_prev_command(6, &wdata, sizeof(wdata), &rdata, sizeof(rdata), 1) && !rdata ) + { + vDelayThread(11000); + return 1; + } + return 0; +} + +static int cdvdman_scmd_sender_3B(int arg1) +{ + char wdata; + char rdata; + + if ( g_cdvdman_minver_x_model_15 && arg1 == 1 ) + { + return 1; + } + wdata = arg1; + g_cdvdman_iocache = 0; + if ( set_prev_command(59, &wdata, sizeof(wdata), &rdata, sizeof(rdata), 1) && !rdata ) + { + vDelayThread(11000); + return 1; + } + return 0; +} + +#ifdef CDVD_VARIANT_DNAS +int sceCdReadDiskID(unsigned int *id) +{ + sceCdRMode rmode; + char sectbuf[2048]; + u32 efbits; + USE_DEV5_MMIO_HWPORT(); + + *((u8 *)id + 4) = 0; + *((u8 *)id + 3) = 0; + *((u8 *)id + 2) = 0; + *((u8 *)id + 1) = 0; + *(u8 *)id = 0; + switch ( sceCdGetDiskType() ) + { + case SCECdPS2CD: + case SCECdPS2CDDA: + case SCECdPS2DVD: + break; + default: + return 0; + } + rmode.spindlctrl = 18; + rmode.datapattern = SCECdSecS2048; + rmode.trycount = 0; + sceCdRead0(0x4B, 1, sectbuf, &rmode, 0, 0); + sceCdSync(3); + if ( !cdvdman_ncmd_sender_0C(0, 0, 0x4B) ) + { + return 0; + } + sceCdSync(3); + if ( g_cdvdman_istruct.m_last_error ) + { + return 0; + } + WaitEventFlag(g_scmd_evid, 1, WEF_AND, &efbits); + if ( !(dev5_mmio_hwport->m_dev5_reg_038 & 4) ) + { + vSetEventFlag(g_scmd_evid, 1); + return 0; + } + *(u8 *)id = dev5_mmio_hwport->m_dev5_reg_030 ^ dev5_mmio_hwport->m_dev5_reg_039; + *((u8 *)id + 1) = dev5_mmio_hwport->m_dev5_reg_031 ^ dev5_mmio_hwport->m_dev5_reg_039; + *((u8 *)id + 2) = dev5_mmio_hwport->m_dev5_reg_032 ^ dev5_mmio_hwport->m_dev5_reg_039; + *((u8 *)id + 3) = dev5_mmio_hwport->m_dev5_reg_033 ^ dev5_mmio_hwport->m_dev5_reg_039; + *((u8 *)id + 4) = dev5_mmio_hwport->m_dev5_reg_034 ^ dev5_mmio_hwport->m_dev5_reg_039; + vSetEventFlag(g_scmd_evid, 1); + return 1; +} + +int sceCdDoesUniqueKeyExist(u32 *status) +{ + int disktype_tmp; + u8 dev5_reg_038; + sceCdRMode rmode; + char ndata[7]; + int state; + u32 efbits; + USE_DEV5_MMIO_HWPORT(); + + disktype_tmp = 0; + if ( !g_cdvdman_istruct.m_cd_inited ) + { + *status = SCECdErCUD; + return 0; + } + *status = 0; + switch ( sceCdGetDiskType() ) + { + case SCECdPS2CD: + case SCECdPS2CDDA: + disktype_tmp = 1; + break; + case SCECdPS2DVD: + break; + default: + *status = SCECdErCUD; + return 0; + } + CpuSuspendIntr(&state); + if ( g_cdvdman_istruct.m_stream_flag || g_cdvdman_istruct.m_read2_flag ) + { + *status = SCECdErREADCF; + CpuResumeIntr(state); + return 0; + } + if ( (sceCdStatus() & SCECdStatSpin) ) + { + CpuResumeIntr(state); + } + else + { + dev5_mmio_hwport->m_dev5_reg_007 = 1; + CpuResumeIntr(state); + sceCdSync(3); + } + CpuSuspendIntr(&state); + rmode.spindlctrl = 18; + rmode.datapattern = SCECdSecS2048; + rmode.trycount = 0; + if ( disktype_tmp ) + { + unsigned int i; + + for ( i = 0; i < 20; i += 1 ) + { + sceCdRead0(0x4B + (0x10 * i), 0x10, g_cdvdman_ptoc, &rmode, 0, 0); + CpuResumeIntr(state); + sceCdSync(3); + CpuSuspendIntr(&state); + } + CpuResumeIntr(state); + } + else + { + sceCdRead0(0x4B, 1, g_cdvdman_ptoc, &rmode, 0, 0); + CpuResumeIntr(state); + sceCdSync(3); + } + WaitEventFlag(g_scmd_evid, 1, WEF_AND, &efbits); + CpuSuspendIntr(&state); + if ( g_cdvdman_istruct.m_stream_flag || g_cdvdman_istruct.m_read2_flag ) + { + *status = SCECdErREADCF; + CpuResumeIntr(state); + vSetEventFlag(g_scmd_evid, 1); + return 0; + } + strcpy(&ndata[3], "K"); + ndata[6] = 0; + ndata[5] = 0; + ndata[2] = 0; + ndata[1] = 0; + ndata[0] = 0; + if ( cdvdman_send_ncmd(12, ndata, sizeof(ndata), 0, 0, 1) < 0 ) + { + *status = SCECdErREADCF; + CpuResumeIntr(state); + vSetEventFlag(g_scmd_evid, 1); + return 0; + } + CpuResumeIntr(state); + sceCdSync(3); + if ( g_cdvdman_istruct.m_last_error ) + { + *status = (u8)g_cdvdman_istruct.m_last_error; + vSetEventFlag(g_scmd_evid, 1); + return 0; + } + dev5_reg_038 = dev5_mmio_hwport->m_dev5_reg_038; + vSetEventFlag(g_scmd_evid, 1); + return (dev5_reg_038 & 5) == 5; +} + +static int cdvdman_ncmd_sender_0C(int arg1, u32 arg2, u32 arg3) +{ + char ndata[7]; + + ndata[1] = !!arg2; + ndata[0] = arg1; + ndata[2] = !!(arg2 >> 8); + *(u32 *)&ndata[3] = !arg1 ? arg3 : 0; + return cdvdman_send_ncmd(12, ndata, sizeof(ndata), 0, 0, 1) >= 0; +} +#endif + +int sceCdDecSet(u8 enable_xor, u8 enable_shift, u8 shiftval) +{ +#ifdef CDVD_VARIANT_DNAS + USE_DEV5_MMIO_HWPORT(); + + g_cdvdman_cd36key = enable_shift | shiftval; + dev5_mmio_hwport->m_dev5_reg_03A = (16 * (shiftval & 7)) | ((!!enable_xor) << 1) | (!!enable_shift); +#endif + return 1; +} diff --git a/iop/cdvd/cdvdman/src/exports.tab b/iop/cdvd/cdvdman/src/exports.tab new file mode 100644 index 00000000000..5b481a148cc --- /dev/null +++ b/iop/cdvd/cdvdman/src/exports.tab @@ -0,0 +1,210 @@ + +DECLARE_EXPORT_TABLE(cdvdman, 1, 1) +DECLARE_EXPORT(_start) +DECLARE_EXPORT(_retonly) +DECLARE_EXPORT(cdvdman_termcall) +DECLARE_EXPORT(_retonly) +DECLARE_EXPORT(sceCdInit) +DECLARE_EXPORT(sceCdStandby) +DECLARE_EXPORT(sceCdRead) +DECLARE_EXPORT(sceCdSeek) +DECLARE_EXPORT(sceCdGetError) +DECLARE_EXPORT(sceCdGetToc) +DECLARE_EXPORT(sceCdSearchFile) +DECLARE_EXPORT(sceCdSync) +DECLARE_EXPORT(sceCdGetDiskType) +DECLARE_EXPORT(sceCdDiskReady) +DECLARE_EXPORT(sceCdTrayReq) +DECLARE_EXPORT(sceCdStop) +DECLARE_EXPORT(sceCdPosToInt) +DECLARE_EXPORT(sceCdIntToPos) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(sceCdCheckCmd) +DECLARE_EXPORT(sceCdRI) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(sceCdReadClock) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(sceCdStatus) +DECLARE_EXPORT(sceCdApplySCmd) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(sceCdCallback) +DECLARE_EXPORT(sceCdPause) +DECLARE_EXPORT(sceCdBreak) +DECLARE_EXPORT(sceCdReadCDDA) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(sceCdGetReadPos) +DECLARE_EXPORT(sceCdCtrlADout) +DECLARE_EXPORT(sceCdNop) +DECLARE_EXPORT(sceGetFsvRbuf) +DECLARE_EXPORT(sceCdstm0Cb) +DECLARE_EXPORT(sceCdstm1Cb) +DECLARE_EXPORT(sceCdSC) +DECLARE_EXPORT(sceCdRC) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(sceCdApplyNCmd) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(sceCdStInit) +DECLARE_EXPORT(sceCdStRead) +DECLARE_EXPORT(sceCdStSeek) +DECLARE_EXPORT(sceCdStStart) +DECLARE_EXPORT(sceCdStStat) +DECLARE_EXPORT(sceCdStStop) +DECLARE_EXPORT(sceCdRead0) +DECLARE_EXPORT(sceCdRV) +DECLARE_EXPORT(sceCdRM) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(sceCdReadChain) +DECLARE_EXPORT(sceCdStPause) +DECLARE_EXPORT(sceCdStResume) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(sceCdPowerOff) +DECLARE_EXPORT(sceCdMmode) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(sceCdStSeekF) +DECLARE_EXPORT(sceCdPOffCallback) +#ifdef CDVD_VARIANT_DNAS +DECLARE_EXPORT(sceCdReadDiskID) +DECLARE_EXPORT(sceCdReadGUID) +#else +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +#endif +DECLARE_EXPORT(sceCdSetTimeout) +#ifdef CDVD_VARIANT_DNAS +DECLARE_EXPORT(sceCdReadModelID) +#else +DECLARE_EXPORT(_retzero) +#endif +DECLARE_EXPORT(sceCdReadDvdDualInfo) +DECLARE_EXPORT(sceCdLayerSearchFile) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(sceCdApplySCmd2) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(sceCdRE) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +#ifdef CDVD_VARIANT_DNAS +DECLARE_EXPORT(sceCdDoesUniqueKeyExist) +#else +DECLARE_EXPORT(_retzero) +#endif +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +DECLARE_EXPORT(_retzero) +END_EXPORT_TABLE + +void _retonly() {} +int _retzero() {return 0;} diff --git a/iop/cdvd/cdvdman/src/imports.lst b/iop/cdvd/cdvdman/src/imports.lst new file mode 100644 index 00000000000..5757e9f9b25 --- /dev/null +++ b/iop/cdvd/cdvdman/src/imports.lst @@ -0,0 +1,90 @@ + +sysmem_IMPORTS_start +I_AllocSysMemory +I_FreeSysMemory +I_Kprintf +sysmem_IMPORTS_end + +loadcore_IMPORTS_start +I_RegisterLibraryEntries +I_QueryBootMode +// I_SetRebootTimeLibraryHandlingMode +loadcore_IMPORTS_end + +intrman_IMPORTS_start +I_RegisterIntrHandler +I_ReleaseIntrHandler +I_EnableIntr +I_DisableIntr +I_CpuSuspendIntr +I_CpuResumeIntr +I_QueryIntrContext +intrman_IMPORTS_end + +stdio_IMPORTS_start +I_printf +stdio_IMPORTS_end + +dmacman_IMPORTS_start +I_dmac_ch_set_madr +I_dmac_ch_get_madr +I_dmac_ch_set_bcr +I_dmac_ch_set_chcr +I_dmac_ch_get_chcr +I_dmac_set_dpcr +I_dmac_get_dpcr +dmacman_IMPORTS_end + +thbase_IMPORTS_start +I_GetThreadId +I_DelayThread +I_GetSystemTime +I_SetAlarm +I_iSetAlarm +I_CancelAlarm +I_iCancelAlarm +thbase_IMPORTS_end + +thevent_IMPORTS_start +I_CreateEventFlag +I_DeleteEventFlag +I_SetEventFlag +I_iSetEventFlag +I_ClearEventFlag +I_iClearEventFlag +I_WaitEventFlag +I_PollEventFlag +I_ReferEventFlagStatus +I_iReferEventFlagStatus +thevent_IMPORTS_end + +thsemap_IMPORTS_start +I_SignalSema +I_iSignalSema +thsemap_IMPORTS_end + +sysclib_IMPORTS_start +I_memcpy +I_memset +I_sprintf +I_strcat +I_strcmp +I_strcpy +I_strlen +I_strncmp +I_strncpy +I_strtol +sysclib_IMPORTS_end + +iomanX_IMPORTS_start +I_open +I_close +I_read +I_write +I_lseek +I_remove +I_AddDrv +I_DelDrv +I_devctl +I_ioctl2 +iomanX_IMPORTS_end diff --git a/iop/cdvd/cdvdman/src/irx_imports.h b/iop/cdvd/cdvdman/src/irx_imports.h new file mode 100644 index 00000000000..e21b2c61d05 --- /dev/null +++ b/iop/cdvd/cdvdman/src/irx_imports.h @@ -0,0 +1,28 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +*/ + +#ifndef IOP_IRX_IMPORTS_H +#define IOP_IRX_IMPORTS_H + +#include "irx.h" + +/* Please keep these in alphabetical order! */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif /* IOP_IRX_IMPORTS_H */ From 5218286c3b3c18b9106bd18575385188bed33aa1 Mon Sep 17 00:00:00 2001 From: Julian Uy Date: Wed, 23 Oct 2024 09:45:10 -0500 Subject: [PATCH 6/8] add: implementation of cdvdfsv module --- iop/cdvd/cdvdfsv/Makefile | 15 + iop/cdvd/cdvdfsv/src/cdvdfsv.c | 2381 ++++++++++++++++++++++++++++ iop/cdvd/cdvdfsv/src/exports.tab | 11 + iop/cdvd/cdvdfsv/src/imports.lst | 116 ++ iop/cdvd/cdvdfsv/src/irx_imports.h | 30 + 5 files changed, 2553 insertions(+) create mode 100644 iop/cdvd/cdvdfsv/Makefile create mode 100644 iop/cdvd/cdvdfsv/src/cdvdfsv.c create mode 100644 iop/cdvd/cdvdfsv/src/exports.tab create mode 100644 iop/cdvd/cdvdfsv/src/imports.lst create mode 100644 iop/cdvd/cdvdfsv/src/irx_imports.h diff --git a/iop/cdvd/cdvdfsv/Makefile b/iop/cdvd/cdvdfsv/Makefile new file mode 100644 index 00000000000..1ab7933182f --- /dev/null +++ b/iop/cdvd/cdvdfsv/Makefile @@ -0,0 +1,15 @@ +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. + +IOP_CFLAGS += -DBUILDING_CDVD_MODULE +IOP_OBJS = cdvdfsv.o imports.o exports.o + +include $(PS2SDKSRC)/Defs.make +include $(PS2SDKSRC)/iop/Rules.bin.make +include $(PS2SDKSRC)/iop/Rules.make +include $(PS2SDKSRC)/iop/Rules.release diff --git a/iop/cdvd/cdvdfsv/src/cdvdfsv.c b/iop/cdvd/cdvdfsv/src/cdvdfsv.c new file mode 100644 index 00000000000..6572c6a1429 --- /dev/null +++ b/iop/cdvd/cdvdfsv/src/cdvdfsv.c @@ -0,0 +1,2381 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +*/ + +#include "irx_imports.h" + +#include +#include +#include + +IRX_ID("cdvd_ee_driver", 2, 38); +// Based on the module from SCE SDK 3.1.0. + +extern struct irx_export_table _exp_cdvdfsv; + +static int cdvdfsv_init(); +static void cdvdfsv_main_th(void *arg); +int *cdvdfsv_dummyentry(int arg1); +static void cdvdfsv_parseargs(int ac, char **av); +static void cdvdfsv_poffloop(); +static void cdvdfsv_rpc1_th(void *arg); +static void cdvdfsv_rpc3_th(void *arg); +static void cdvdfsv_rpc2_th(void *arg); +unsigned int optimized_memcpy(char *dst, const char *src, unsigned int n); + +static int g_cdvdfsv_def_pri = 81; +static int g_verbose_level = 0; +static int g_cdvdfsv_spinctl = -1; +static int g_cdvdfsv_plbreak = 0; +static int g_cdvdfsv_nopocm = 0; +static int g_cdvdfsv_rpc5flg = 0; +static int g_cdvdfsv_rpc3flg = 0; +#if 0 +static iop_library_t g_modload_libinfo = { NULL, NULL, 256, 0, "modload", { NULL } }; +#endif +static int g_cdvdfsv_r2retry = 0; +static int g_cdvdfsv_r2count = 0; +static int g_cdvdfsv_sid_err_recover_cnt = 0; +static int g_cdvdfsv_err_count = 0; +static void *g_cdvdfsv_fsvrbuf; +static char *g_cdvdfsv_rtocbuf; +static SifDmaTransfer_t g_cdvdfsv_fssdd; +static SifDmaTransfer_t g_cdvdfsv_iomrsdd; +static SifDmaTransfer_t g_cdvdfsv_rdp2sdd; +static SifDmaTransfer_t g_cdvdfsv_multi_dmat[16]; +static sceCdRMode g_cdvdfsv_rmodeee; +static SifDmaTransfer_t g_cdvdfsv_datasdd; +static SifDmaTransfer_t g_cdvdfsv_eerpsdd; +static SifDmaTransfer_t g_cdvdfsv_chrdsdd; +static SifDmaTransfer_t g_cdvdfsv_eereadfull_dma1; +static SifDmaTransfer_t g_cdvdfsv_eereadfull_dma2; +static SifDmaTransfer_t g_cdvdfsv_rtocsdd; +static iop_sys_clock_t g_cdvdfsv_read_timeout; +static int g_cdvdman_intr_efid; +static int g_scmd_evid; +static int g_cdvdfsv_thids[4]; +static cdvdman_internal_struct_t *g_cdvdman_istruct_ptr; +static cdvdfsv_rpc1_outpacket_t g_cdvdfsv_initres; +static cdvdfsv_unaligned_data_outpacket_t g_cdvdfsv_eereadx; +static SifRpcDataQueue_t g_rpc_qdata2; +static SifRpcDataQueue_t g_rpc_qdata1; +static SifRpcDataQueue_t g_rpc_qdata3; +static SifRpcServerData_t g_rpc_sdata1; +static SifRpcServerData_t g_rpc_sdata4; +static SifRpcServerData_t g_rpc_sdata5; +static SifRpcServerData_t g_rpc_sdata2; +static SifRpcServerData_t g_rpc_sdata6; +static SifRpcServerData_t g_rpc_sdata3; +static cdvdfsv_rpc4_outpacket_t g_cdvdfsv_srchres; +static int g_cdvdfsv_readpos; +static int g_cdvdfsv_rderror; +static cdvdfsv_rpc2_outpacket_t g_diskready_res; +static cdvdfsv_rpc5_outpacket_t g_crr; +static cdvdfsv_rpc3_outpacket_t g_outbuf; +static int g_rpc_buffer3[260]; +static int g_rpc_buffer5[256]; +static int g_rpc_buffer1[4]; +static int g_rpc_buffer4[76]; +static int g_rpc_buffer2[4]; + +static int cdvdfsv_checkdmastat(int trid) +{ + int retval; + int state; + + if ( QueryIntrContext() ) + return sceSifDmaStat(trid); + CpuSuspendIntr(&state); + retval = sceSifDmaStat(trid); + CpuResumeIntr(state); + return retval; +} + +static int cdvdfsv_cleanuprpc() +{ + unsigned int i; + + sceSifRemoveRpc(&g_rpc_sdata1, &g_rpc_qdata1); + sceSifRemoveRpc(&g_rpc_sdata2, &g_rpc_qdata1); + sceSifRemoveRpc(&g_rpc_sdata3, &g_rpc_qdata1); + sceSifRemoveRpc(&g_rpc_sdata6, &g_rpc_qdata3); + sceSifRemoveRpc(&g_rpc_sdata4, &g_rpc_qdata2); + sceSifRemoveRpc(&g_rpc_sdata5, &g_rpc_qdata2); + sceSifRemoveRpcQueue(&g_rpc_qdata1); + sceSifRemoveRpcQueue(&g_rpc_qdata2); + sceSifRemoveRpcQueue(&g_rpc_qdata3); + g_cdvdfsv_nopocm = 1; + g_cdvdfsv_plbreak = 1; + for ( i = 0; i < (sizeof(g_cdvdfsv_thids) / sizeof(g_cdvdfsv_thids[0])); i += 1 ) + { + TerminateThread(g_cdvdfsv_thids[i]); + DeleteThread(g_cdvdfsv_thids[i]); + } + return 1; +} + +int _start(int ac, char *av[], void *startaddr, ModuleInfo_t *mi) +{ +#if 0 + const u16 *LibraryEntryTable; +#endif + int state; + + (void)startaddr; + + if ( ac < 0 ) + { + int error_code; + + // cppcheck-suppress knownConditionTrueFalse + if ( g_cdvdfsv_rpc5flg || g_cdvdfsv_rpc3flg || !cdvdfsv_cleanuprpc() ) + { + return MODULE_REMOVABLE_END; + } + CpuSuspendIntr(&state); + error_code = ReleaseLibraryEntries(&_exp_cdvdfsv); + CpuResumeIntr(state); + if ( error_code && error_code != KE_LIBRARY_NOTFOUND ) + { + KPRINTF("ReleaseLibraryEntries Error code %d\n", error_code); + return MODULE_REMOVABLE_END; + } + return MODULE_NO_RESIDENT_END; + } + if ( RegisterLibraryEntries(&_exp_cdvdfsv) ) + { + return MODULE_NO_RESIDENT_END; + } + g_cdvdfsv_fsvrbuf = sceGetFsvRbuf(); + // Unofficial: setting of unused variable removed + g_cdvdfsv_rtocbuf = (char *)g_cdvdfsv_fsvrbuf; + cdvdfsv_parseargs(ac, av); + cdvdfsv_init(); +#if 0 + CpuSuspendIntr(&state); + LibraryEntryTable = (u16 *)QueryLibraryEntryTable(&g_modload_libinfo); + CpuResumeIntr(state); + if ( !LibraryEntryTable || (*(LibraryEntryTable - 6) < 0x104) ) + { + KPRINTF("Warning cdvdfsv.irx: Unload function can't be used.\n"); + return MODULE_RESIDENT_END; + } + return MODULE_REMOVABLE_END; +#else + if ( mi && ((mi->newflags & 2) != 0) ) + mi->newflags |= 0x10; + return MODULE_RESIDENT_END; +#endif +} + +static int cdvdfsv_init() +{ + const int *BootMode; + iop_thread_t thparam; + int scres; + + BootMode = QueryBootMode(3); + if ( BootMode && (BootMode[1] & 2) ) + { + PRINTF(" No cdvd driver \n"); + return 1; + } + sceCdSC(0xFFFFFFF2, (int *)&g_cdvdman_istruct_ptr); + g_scmd_evid = sceCdSC(0xFFFFFFE7, &scres); + thparam.attr = TH_C; + thparam.thread = cdvdfsv_main_th; + thparam.stacksize = 0x800; + thparam.option = 0; + thparam.priority = g_cdvdfsv_def_pri - 1; + g_cdvdfsv_thids[0] = CreateThread(&thparam); + if ( g_cdvdfsv_thids[0] <= 0 ) + { + return 1; + } + StartThread(g_cdvdfsv_thids[0], 0); + return 0; +} + +static void cdvdfsv_main_th(void *arg) +{ + iop_thread_t thparam1; + iop_thread_t thparam2; + + (void)arg; + + if ( !sceSifCheckInit() ) + sceSifInit(); + sceSifInitRpc(0); + PRINTF("cdvd driver module version 0.1.1 (C)SCEI\n"); + thparam2.thread = cdvdfsv_rpc1_th; + thparam2.attr = TH_C; + thparam2.stacksize = 0x1900; + thparam2.option = 0; + thparam2.priority = g_cdvdfsv_def_pri; + g_cdvdfsv_thids[1] = CreateThread(&thparam2); + StartThread(g_cdvdfsv_thids[1], 0); + thparam1.attr = TH_C; + thparam1.thread = cdvdfsv_rpc2_th; + thparam1.stacksize = 0x1900; + thparam1.option = 0; + thparam1.priority = g_cdvdfsv_def_pri; + g_cdvdfsv_thids[2] = CreateThread(&thparam1); + StartThread(g_cdvdfsv_thids[2], 0); + thparam1.thread = cdvdfsv_rpc3_th; + thparam1.attr = TH_C; + thparam1.stacksize = 0x800; + thparam1.option = 0; + thparam1.priority = g_cdvdfsv_def_pri; + g_cdvdfsv_thids[3] = CreateThread(&thparam1); + StartThread(g_cdvdfsv_thids[3], 0); + cdvdfsv_poffloop(); + ExitDeleteThread(); +} + +int *cdvdfsv_dummyentry(int arg1) +{ + VERBOSE_PRINTF(1, "Dummy Entry Called\n"); + if ( arg1 != 128 ) + return 0; + return &g_verbose_level; +} + +static void cdvdfsv_parseargs(int ac, char **av) +{ + int i; + + g_cdvdfsv_def_pri = 81; + for ( i = 1; i < ac; i += 1 ) + { + if ( !strncmp(av[i], "thpri=", 6) ) + { + g_cdvdfsv_def_pri = strtol(av[i] + 6, 0, 10); + if ( (unsigned int)(g_cdvdfsv_def_pri - 9) >= 0x73 ) + { + PRINTF("Cdvdfsv:thpri=%d Illegal priority\n", g_cdvdfsv_def_pri); + g_cdvdfsv_def_pri = 81; + } + if ( g_cdvdfsv_def_pri == 9 ) + g_cdvdfsv_def_pri = 10; + } + } +} + +int sceCdChangeThreadPriority(int priority) +{ + iop_thread_info_t thinfo; + + if ( (unsigned int)(priority - 9) >= 0x73 ) + return -403; + if ( priority == 9 ) + priority = 10; + ReferThreadStatus(0, &thinfo); + ChangeThreadPriority(0, 8); + ChangeThreadPriority(g_cdvdfsv_thids[0], priority - 1); + ChangeThreadPriority(g_cdvdfsv_thids[2], priority); + ChangeThreadPriority(g_cdvdfsv_thids[1], priority); + ChangeThreadPriority(g_cdvdfsv_thids[3], priority); + return 0; +} + +static void *cbrpc_rpc1_cdinit(int fno, void *buffer, int length) +{ + int scres_unused; + + (void)fno; + (void)length; + + VERBOSE_PRINTF(1, "sceCdInit call\n"); + sceCdInit(((const cdvdfsv_rpc1_inpacket_t *)buffer)->m_mode); + g_cdvdfsv_spinctl = -1; + g_cdvdfsv_initres.m_debug_mode = g_verbose_level ? 254 : 0; + g_cdvdfsv_initres.m_cdvdfsv_ver = (u16)_irx_id.v; + g_cdvdfsv_initres.m_cdvdman_ver = sceCdSC(0xFFFFFFF7, &scres_unused); + VERBOSE_PRINTF(1, "sceCdInit end\n"); + g_cdvdfsv_initres.m_retres = 1; + return (void *)&g_cdvdfsv_initres; +} + +static void cdvdfsv_rpc3_16_break(const cdvdfsv_rpc3_inpacket_t *inbuf, int buflen, cdvdfsv_rpc3_outpacket_t *outbuf) +{ + (void)inbuf; + (void)buflen; + + VERBOSE_PRINTF(1, "sceCdAbort call\n"); + sceCdBreak(); + outbuf->m_retres = 1; +} + +static void *cbrpc_rpc4_fscall(int fno, void *buffer, int length) +{ + int scres; + int state; + cdvdfsv_rpc4_inpacket_t *inbuf; + + (void)fno; + + inbuf = buffer; + scres = 255; + sceCdSC(0xFFFFFFF6, &scres); + VERBOSE_PRINTF(1, "search file name %s call struct_siz %d\n", inbuf->m_pkt_sz12c.m_path, length); + switch ( length ) + { + case sizeof(inbuf->m_pkt_sz12c): + g_cdvdfsv_srchres.m_retres = + sceCdLayerSearchFile(&(inbuf->m_pkt_sz12c.m_fp), inbuf->m_pkt_sz12c.m_path, inbuf->m_pkt_sz12c.m_layer); + g_cdvdfsv_fssdd.src = buffer; + g_cdvdfsv_fssdd.dest = (void *)inbuf->m_pkt_sz12c.m_eedest; + g_cdvdfsv_fssdd.size = sizeof(sceCdlFILE) + 4; + break; + case sizeof(inbuf->m_pkt_sz128): + PRINTF("sceCdSearchFile: Called from Not_Dual_layer Version.\n"); + g_cdvdfsv_srchres.m_retres = sceCdSearchFile(&(inbuf->m_pkt_sz128.m_fp), inbuf->m_pkt_sz128.m_path); + g_cdvdfsv_fssdd.src = buffer; + g_cdvdfsv_fssdd.dest = (void *)inbuf->m_pkt_sz128.m_eedest; + g_cdvdfsv_fssdd.size = sizeof(sceCdlFILE) + 4; + break; + default: + PRINTF("Warning sceCdSearchFile: Called from Old liblary.\n"); + g_cdvdfsv_srchres.m_retres = sceCdSearchFile(&(inbuf->m_pkt_sz124.m_fp), inbuf->m_pkt_sz124.m_path); + g_cdvdfsv_fssdd.src = buffer; + g_cdvdfsv_fssdd.dest = (void *)inbuf->m_pkt_sz124.m_eedest; + g_cdvdfsv_fssdd.size = sizeof(sceCdlFILE); + break; + } + g_cdvdfsv_fssdd.attr = 0; + while ( 1 ) + { + int trid; + + CpuSuspendIntr(&state); + trid = sceSifSetDma(&g_cdvdfsv_fssdd, 1); + CpuResumeIntr(state); + if ( trid ) + break; + DelayThread(500); + } + scres = 0; + sceCdSC(0xFFFFFFF6, &scres); + return (void *)&g_cdvdfsv_srchres; +} + +static int read_timeout_alarm_cb(const iop_sys_clock_t *sys_clock) +{ + int read_timeout; + + read_timeout = sys_clock->lo / 0x9000; + KPRINTF("Read Time Out %d(msec)\n", read_timeout); + sceCdSC(0xFFFFFFEE, &read_timeout); + return !sceCdBreak(); +} + +static void cdvdfsv_rpc5_0D_iopmread(const cdvdfsv_rpc5_inpacket_t *inbuf, int buflen, cdvdfsv_rpc5_outpacket_t *outbuf) +{ + int cmd_error; + int trid; + int scres_unused; + int error_code; + int state; + + (void)buflen; + (void)outbuf; + + g_cdvdfsv_rderror = SCECdErREADCFR; + g_cdvdfsv_read_timeout.hi = 0; + g_cdvdfsv_read_timeout.lo = 0x9000 * sceCdSC(0xFFFFFFF1, &scres_unused); + g_cdvdfsv_iomrsdd.src = &g_cdvdfsv_readpos; + g_cdvdfsv_iomrsdd.size = sizeof(g_cdvdfsv_readpos); + g_cdvdfsv_iomrsdd.attr = 0; + g_cdvdfsv_iomrsdd.dest = (void *)inbuf->m_pkt_0D.m_eedest; + VERBOSE_PRINTF( + 1, + "sceCdReadIOPm addr= 0x%08x sector= %d\n", + (unsigned int)(uiptr)(inbuf->m_pkt_0D.m_buf), + (int)(inbuf->m_pkt_0D.m_sectors)); + cmd_error = sceCdRE( + inbuf->m_pkt_0D.m_lbn, inbuf->m_pkt_0D.m_sectors, inbuf->m_pkt_0D.m_buf, (sceCdRMode *)&inbuf->m_pkt_0D.m_mode); + while ( sceCdSync(1) ) + { + g_cdvdfsv_readpos = sceCdGetReadPos(); + while ( 1 ) + { + CpuSuspendIntr(&state); + trid = sceSifSetDma(&g_cdvdfsv_iomrsdd, 1); + CpuResumeIntr(state); + if ( trid ) + break; + DelayThread(500); + } + DelayThread(8000); + while ( cdvdfsv_checkdmastat(trid) >= 0 ) + ; + } + error_code = sceCdGetError(); + if ( error_code || !cmd_error ) + { + if ( !cmd_error ) + sceCdSC(0xFFFFFFFE, &g_cdvdfsv_rderror); + VERBOSE_PRINTF(1, "Read error code %x cmd error %d\n", error_code, cmd_error); + } +} + +static u8 cdvdfsv_syncdec(int flag, int xorkey, int arg2, u8 data) +{ + return flag ? (((data << (arg2 % 8)) | (data >> (8 - arg2 % 8))) ^ xorkey) : data; +} + +static int cdvdfsv_cb_read() +{ + iSetEventFlag(g_cdvdman_intr_efid, 0x20); + return 0; +} + +static int cdvdfsv_checksid(u32 lsn, u32 sectors, u32 ps2dvd, void *buf, int decflag, int decshift, u32 *syncdec_mask) +{ + int scret; + u32 i; + u32 readlsn; + int syncdec; + u8 syncdec_4; + sceCdlLOCCD rpos; + int scres; + int ipi_emu; + + ipi_emu = 0; + *syncdec_mask = 0; + scret = decflag ? sceCdSC(0xFFFFFFE8, &scres) : 0; + syncdec_4 = 0; + for ( i = 0; i < sectors; i += 1 ) + { + if ( ps2dvd ) + { + syncdec = cdvdfsv_syncdec(decflag, scret, decshift, ((u8 *)buf + (i * 0x810))[3]); + syncdec += cdvdfsv_syncdec(decflag, scret, decshift, ((u8 *)buf + (i * 0x810))[2]) << 8; + syncdec += cdvdfsv_syncdec(decflag, scret, decshift, ((u8 *)buf + (i * 0x810))[1]) << 16; + syncdec_4 = cdvdfsv_syncdec(decflag, scret, decshift, ((u8 *)buf + (i * 0x810))[0]); + if ( i && !*syncdec_mask ) + { + ipi_emu = syncdec_4 & 0xC; + } + else if ( !i ) + { + *syncdec_mask = syncdec_4 & 0xC; + } + readlsn = syncdec - 0x30000; + if ( + g_cdvdman_istruct_ptr->m_opo_or_para && (lsn + i) >= g_cdvdman_istruct_ptr->m_layer_1_lsn + && g_cdvdman_istruct_ptr->m_opo_or_para == 1 ) + { + readlsn += g_cdvdman_istruct_ptr->m_layer_1_lsn; + } + } + else + { + rpos.minute = cdvdfsv_syncdec(decflag, scret, decshift, ((u8 *)buf + (i * 0x924))[0]); + rpos.second = cdvdfsv_syncdec(decflag, scret, decshift, ((u8 *)buf + (i * 0x924))[1]); + rpos.sector = cdvdfsv_syncdec(decflag, scret, decshift, ((u8 *)buf + (i * 0x924))[2]); + readlsn = sceCdPosToInt(&rpos); + } + if ( readlsn != (lsn + i) || ipi_emu ) + { + VERBOSE_PRINTF( + 1, + "Read_EE Sector_ID error lsn= %d readlsn= %d layer= %d layer1_start %d\n", + (int)(lsn + i), + (int)readlsn, + (syncdec_4 & 1), + (int)(g_cdvdman_istruct_ptr->m_layer_1_lsn)); + return 0; + } + } + if ( *syncdec_mask ) + { + VERBOSE_PRINTF( + 1, "Read_EE NO_Data_zone error lsn= %d layer= %d SecID %02x\n", (int)lsn, (syncdec_4 & 1), (int)(*syncdec_mask)); + } + return 1; +} + +static int readproc2( + u32 lsn, + u32 nsec, + sceCdRMode *mode, + u32 sector_size_selection, + int do_multi_retries, + int enable_dec_shift, + int dec_shift, + char *ee_addr, + int fssift, + int secsize, + int dmasize, + SifDmaTransfer_t *post_dmat) +{ + unsigned int i; + int csec; + int read_res_tmp; + int trid; + int j; + int size_2; + int sector_sizes[2]; + int error_code; + int scres_unused; + int state; + u32 syncdec_mask; + u32 chcr; + int error_code_tmp; + char *ee_addr_tmp; + int dmasize_tmp; + int csec_comm; + int nsec_div_cdvdfsv_sectors; + int retry_flag1; + int retry_flag2; + int sector_size; + + error_code_tmp = 0; + sector_sizes[0] = 0x924; + sector_sizes[1] = 0x810; + g_cdvdfsv_read_timeout.hi = 0; + g_cdvdfsv_read_timeout.lo = 0x9000 * sceCdSC(0xFFFFFFF1, &scres_unused); + g_cdvdfsv_rderror = SCECdErREADCF; + g_cdvdfsv_r2retry = 0; + g_cdvdfsv_r2count = 0; + if ( secsize != 0x924 && !fssift ) + { + for ( i = 0; i < (sizeof(g_cdvdfsv_multi_dmat) / sizeof(g_cdvdfsv_multi_dmat[0])); i += 1 ) + { + g_cdvdfsv_multi_dmat[i].attr = 0; + g_cdvdfsv_multi_dmat[i].size = secsize; + } + } + sector_size = sector_sizes[sector_size_selection]; + while ( 1 ) + { + while ( 1 ) + { + csec = (nsec <= (sizeof(g_cdvdfsv_multi_dmat) / sizeof(g_cdvdfsv_multi_dmat[0]))) ? + nsec : + (sizeof(g_cdvdfsv_multi_dmat) / sizeof(g_cdvdfsv_multi_dmat[0])); + nsec_div_cdvdfsv_sectors = (nsec >> 4) + (!!((nsec & 0xF))); + retry_flag2 = 0; + ee_addr_tmp = ee_addr; + dmasize_tmp = dmasize; + g_cdvdman_istruct_ptr->m_dec_mode_set = 1; + g_cdvdman_istruct_ptr->m_dec_mode_last_set = 0; + CpuSuspendIntr(&state); + if ( enable_dec_shift ) + { + g_cdvdman_istruct_ptr->m_dec_shift = dec_shift; + g_cdvdman_istruct_ptr->m_dec_state = 2; + } + if ( g_cdvdfsv_r2retry ) + { + VERBOSE_KPRINTF(1, "Rty_Read\n"); + read_res_tmp = (sector_size_selection ? sceCdRV : sceCdRead0)( + (lsn >= 0x60) ? (lsn - 0x10 * g_cdvdfsv_r2retry) : (lsn + 0x10 * g_cdvdfsv_r2retry + 0x60), + 0x10, + &g_cdvdfsv_rtocbuf[0x1248], + mode, + 0, + 0); + CpuResumeIntr(state); + } + else + { + read_res_tmp = (sector_size_selection ? sceCdRV : sceCdRead0)( + lsn, nsec, &g_cdvdfsv_rtocbuf[0x1248], mode, csec, cdvdfsv_cb_read); + CpuResumeIntr(state); + if ( read_res_tmp ) + { + SetAlarm(&g_cdvdfsv_read_timeout, (unsigned int (*)(void *))read_timeout_alarm_cb, &g_cdvdfsv_read_timeout); + csec_comm = 0; + retry_flag1 = 0; + break; + } + } + if ( !read_res_tmp ) + { + g_cdvdman_istruct_ptr->m_dec_state = 0; + g_cdvdman_istruct_ptr->m_dec_mode_set = 0; + sceCdSC(0xFFFFFFFE, &g_cdvdfsv_rderror); + return 0; + } + sceCdSync(3); + g_cdvdfsv_r2retry -= 1; + } + for ( i = 0; (int)i < nsec_div_cdvdfsv_sectors; i += 1 ) + { + sceCdSync(32); + if ( g_cdvdman_istruct_ptr->m_dec_mode_last_set ) + break; + if ( !sceCdGetError() ) + { + if ( cdvdfsv_checksid( + lsn + csec_comm, + csec, + sector_size_selection, + &g_cdvdfsv_rtocbuf[0x1248], + enable_dec_shift, + dec_shift, + &syncdec_mask) ) + { + if ( do_multi_retries && syncdec_mask && !i ) + { + retry_flag1 = 1; + error_code_tmp = SCECdErIPI; + } + } + else if ( do_multi_retries ) + { + retry_flag2 = 1; + retry_flag1 = 1; + } + if ( retry_flag1 || g_cdvdfsv_r2retry ) + { + } + else if ( secsize == 0x924 && !sector_size_selection ) + { + if ( fssift ) + { + if ( i ) + { + optimized_memcpy(&g_cdvdfsv_rtocbuf[secsize], &g_cdvdfsv_rtocbuf[fssift], secsize - fssift); + optimized_memcpy(g_cdvdfsv_rtocbuf, &g_cdvdfsv_rtocbuf[secsize + secsize * csec], secsize); + g_cdvdfsv_rdp2sdd.size = + ((int)i == nsec_div_cdvdfsv_sectors - 1) ? dmasize_tmp : (secsize * (csec - 1) + fssift); + optimized_memcpy( + &g_cdvdfsv_rtocbuf[secsize + secsize - fssift], + &g_cdvdfsv_rtocbuf[secsize * 2], + g_cdvdfsv_rdp2sdd.size); + } + else + { + optimized_memcpy(g_cdvdfsv_rtocbuf, &g_cdvdfsv_rtocbuf[secsize * 2 + secsize * (csec - 1)], secsize); + g_cdvdfsv_rdp2sdd.size = ((int)i == nsec_div_cdvdfsv_sectors - 1) ? dmasize_tmp : (secsize * (csec - 1)); + optimized_memcpy( + &g_cdvdfsv_rtocbuf[secsize], &g_cdvdfsv_rtocbuf[secsize * 2 + fssift], g_cdvdfsv_rdp2sdd.size); + } + g_cdvdfsv_rdp2sdd.src = &g_cdvdfsv_rtocbuf[secsize]; + } + else + { + g_cdvdfsv_rdp2sdd.src = &g_cdvdfsv_rtocbuf[secsize * 2]; + g_cdvdfsv_rdp2sdd.size = secsize * csec; + } + g_cdvdfsv_rdp2sdd.attr = 0; + g_cdvdfsv_rdp2sdd.dest = ee_addr_tmp; + ee_addr_tmp += g_cdvdfsv_rdp2sdd.size; + dmasize_tmp -= g_cdvdfsv_rdp2sdd.size; + while ( 1 ) + { + CpuSuspendIntr(&state); + trid = sceSifSetDma(&g_cdvdfsv_rdp2sdd, 1); + CpuResumeIntr(state); + if ( trid ) + break; + DelayThread(500); + } + while ( cdvdfsv_checkdmastat(trid) >= 0 ) + ; + } + else if ( !fssift ) + { + for ( j = 0; j < csec; j += 1 ) + { + g_cdvdfsv_multi_dmat[j].dest = &ee_addr[(csec_comm + j) * secsize]; + g_cdvdfsv_multi_dmat[j].src = &g_cdvdfsv_rtocbuf[0x1248 + (j * sector_size) + 12]; + } + while ( 1 ) + { + CpuSuspendIntr(&state); + trid = sceSifSetDma(g_cdvdfsv_multi_dmat, csec); + CpuResumeIntr(state); + if ( trid ) + break; + DelayThread(500); + } + while ( cdvdfsv_checkdmastat(trid) >= 0 ) + ; + } + else + { + size_2 = ((int)i != nsec_div_cdvdfsv_sectors - 1) ? fssift : secsize; + g_cdvdfsv_rdp2sdd.size = dmasize_tmp; + if ( i ) + { + optimized_memcpy(&g_cdvdfsv_rtocbuf[0x924], &g_cdvdfsv_rtocbuf[fssift + 12], secsize - fssift); + optimized_memcpy(g_cdvdfsv_rtocbuf, &g_cdvdfsv_rtocbuf[0x1248 + (csec - 1) * sector_size], sector_size); + for ( j = 0; j < csec - 1; j += 1 ) + { + optimized_memcpy( + &g_cdvdfsv_rtocbuf[0x924 + secsize - fssift + (j * secsize)], + &g_cdvdfsv_rtocbuf[0x1248 + 12 + (j * sector_size)], + secsize); + } + optimized_memcpy( + &g_cdvdfsv_rtocbuf[0x924 + secsize - fssift + ((csec - 1) * secsize)], + &g_cdvdfsv_rtocbuf[0x1248 + 12 + ((csec - 1) * sector_size)], + size_2); + if ( (int)i != nsec_div_cdvdfsv_sectors - 1 ) + { + g_cdvdfsv_rdp2sdd.size = secsize * csec; + } + } + else + { + optimized_memcpy(g_cdvdfsv_rtocbuf, &g_cdvdfsv_rtocbuf[0x1248 + (csec - 1) * sector_size], sector_size); + optimized_memcpy(&g_cdvdfsv_rtocbuf[0x924], &g_cdvdfsv_rtocbuf[0x1248 + fssift + 12], secsize - fssift); + for ( j = 0; j < csec - 2; j += 1 ) + { + optimized_memcpy( + &g_cdvdfsv_rtocbuf[0x924 + secsize - fssift + (j * secsize)], + &g_cdvdfsv_rtocbuf[0x1248 + sector_size + 12 + (j * sector_size)], + secsize); + } + optimized_memcpy( + &g_cdvdfsv_rtocbuf[0x924 + secsize - fssift + ((csec - 2) * secsize)], + &g_cdvdfsv_rtocbuf[0x1248 + sector_size + 12 + ((csec - 2) * sector_size)], + size_2); + if ( (int)i != nsec_div_cdvdfsv_sectors - 1 ) + { + g_cdvdfsv_rdp2sdd.size = secsize * (csec - 1); + } + } + g_cdvdfsv_rdp2sdd.src = &g_cdvdfsv_rtocbuf[0x924]; + g_cdvdfsv_rdp2sdd.attr = 0; + g_cdvdfsv_rdp2sdd.dest = ee_addr_tmp; + ee_addr_tmp += g_cdvdfsv_rdp2sdd.size; + dmasize_tmp -= g_cdvdfsv_rdp2sdd.size; + while ( 1 ) + { + CpuSuspendIntr(&state); + trid = sceSifSetDma(&g_cdvdfsv_rdp2sdd, 1); + CpuResumeIntr(state); + if ( trid ) + break; + DelayThread(500); + } + while ( cdvdfsv_checkdmastat(trid) >= 0 ) + ; + } + } + else + { + retry_flag1 = 1; + } + CpuSuspendIntr(&state); + if ( (int)i == nsec_div_cdvdfsv_sectors - 1 ) + { + DisableIntr(IOP_IRQ_DMA_CDVD, (int *)&chcr); + } + else + { + csec_comm = csec_comm + csec; + csec = ((unsigned int)csec > nsec - (unsigned int)csec_comm) ? + (nsec - (unsigned int)csec_comm) : + (sizeof(g_cdvdfsv_multi_dmat) / sizeof(g_cdvdfsv_multi_dmat[0])); + ClearEventFlag(g_cdvdman_intr_efid, ~0x20); + dmac_ch_set_chcr(3, 0); + dmac_ch_get_chcr(3); + g_cdvdman_istruct_ptr->m_dma3_param.m_dma3_maddress = &g_cdvdfsv_rtocbuf[0x1248]; + dmac_ch_set_madr(3, (uiptr)(&g_cdvdfsv_rtocbuf[0x1248])); + dmac_ch_set_bcr( + 3, + g_cdvdman_istruct_ptr->m_dma3_param.m_dma3_blkwords + | ((g_cdvdman_istruct_ptr->m_dma3_param.m_dma3_blkcount * csec) << 16)); + dmac_ch_set_chcr(3, 0x41000200); + chcr = dmac_ch_get_chcr(3); + if ( post_dmat ) + { + g_cdvdfsv_readpos += secsize * csec; + sceSifSetDma(post_dmat, 1); + } + } + CpuResumeIntr(state); + } + sceCdSync(5); + CancelAlarm((unsigned int (*)(void *))read_timeout_alarm_cb, &g_cdvdfsv_read_timeout); + g_cdvdman_istruct_ptr->m_dec_mode_set = 0; + g_cdvdman_istruct_ptr->m_dec_state = 0; + error_code = sceCdGetError(); + if ( (u16)g_cdvdman_istruct_ptr->m_dec_mode_last_set ) + { + retry_flag2 = 1; + error_code = 0; + mode->spindlctrl = 16; + } + if ( error_code || g_cdvdfsv_r2count >= 5 ) + break; + if ( !retry_flag2 ) + { + if ( !error_code_tmp ) + return 1; + sceCdSC(0xFFFFFFFE, &error_code_tmp); + VERBOSE_KPRINTF(1, "secid_chk_ee_trns lsn %d nsec %d IPI Err\n", lsn, nsec); + return 0; + } + if ( !g_cdvdfsv_r2retry ) + { + g_cdvdfsv_r2count += 1; + VERBOSE_PRINTF(1, "Read_CD/DVD-ROM Error Recover Start\n"); + g_cdvdfsv_r2retry = 3; + } + } + if ( g_cdvdfsv_r2count >= 5 && !error_code ) + { + sceCdSC(0xFFFFFFFE, &g_cdvdfsv_rderror); + } + return 0; +} + +static int readproc1( + unsigned int lsn, + u32 nsec, + void *retptr, + sceCdRMode *rmode, + int ps2dvd, + int enable_retries, + int dec_shift_enable, + int dec_shift_value) +{ + int scres_unused; + int state; + u32 syncdec_mask; + int error_code_tmp; + + error_code_tmp = 0; + g_cdvdfsv_read_timeout.hi = 0; + g_cdvdfsv_read_timeout.lo = 0x9000 * sceCdSC(0xFFFFFFF1, &scres_unused); + g_cdvdfsv_rderror = SCECdErREADCF; + g_cdvdfsv_sid_err_recover_cnt = 0; + g_cdvdfsv_err_count = 0; + while ( 1 ) + { + int cmd_error; + int error_code; + + CpuSuspendIntr(&state); + if ( dec_shift_enable ) + { + g_cdvdman_istruct_ptr->m_dec_shift = dec_shift_value; + g_cdvdman_istruct_ptr->m_dec_state = 2; + } + cmd_error = (ps2dvd ? sceCdRV : sceCdRead0)( + (lsn >= 0x30) ? (lsn - 0x10 * g_cdvdfsv_sid_err_recover_cnt) : (lsn + 0x10 * g_cdvdfsv_sid_err_recover_cnt), + nsec, + retptr, + rmode, + 0, + 0); + CpuResumeIntr(state); + if ( cmd_error ) + SetAlarm(&g_cdvdfsv_read_timeout, (unsigned int (*)(void *))read_timeout_alarm_cb, &g_cdvdfsv_read_timeout); + sceCdSync(5); + CancelAlarm((unsigned int (*)(void *))read_timeout_alarm_cb, &g_cdvdfsv_read_timeout); + g_cdvdman_istruct_ptr->m_dec_state = 0; + error_code = sceCdGetError(); + if ( error_code || !cmd_error || g_cdvdfsv_err_count >= 5 ) + { + VERBOSE_KPRINTF(1, "Read error error code %x cmd error %d\n", error_code, cmd_error); + if ( (!cmd_error || g_cdvdfsv_err_count >= 5) && (!error_code) ) + { + sceCdSC(0xFFFFFFFE, &g_cdvdfsv_rderror); + } + return 0; + } + if ( cdvdfsv_checksid(lsn, nsec, ps2dvd, retptr, dec_shift_enable, dec_shift_value, &syncdec_mask) ) + { + if ( enable_retries && syncdec_mask ) + error_code_tmp = SCECdErIPI; + break; + } + if ( !enable_retries ) + break; + if ( !g_cdvdfsv_sid_err_recover_cnt ) + { + g_cdvdfsv_err_count += 1; + VERBOSE_PRINTF(1, "Read_CD/DVD-ROM Sector_ID Error Recover Start\n"); + g_cdvdfsv_sid_err_recover_cnt = 3; + } + g_cdvdfsv_sid_err_recover_cnt -= 1; + } + if ( !error_code_tmp ) + return 1; + sceCdSC(0xFFFFFFFE, &error_code_tmp); + VERBOSE_KPRINTF(1, "secid_chk lsn %d nsec %d IPI Err\n", lsn, nsec); + return 0; +} + +static void cdvdfsv_rpc5_01_readee( + const cdvdfsv_rpc5_inpacket_t *inbuf, int buflen, cdvdfsv_rpc5_outpacket_t *outbuf, u32 ps2dvd, int sync, int decflag) +{ + unsigned int secsize; + unsigned int bsize; + unsigned int bsize_tmp; + unsigned int psize; + unsigned int ssize; + unsigned int i; + int sizestuff; + u32 needed_offset; + int sector_sizes[2]; + int scres_unused; + int lsndualchg_res; + int state; + unsigned int buf_offs_sum; + unsigned int paddr; + int saddr; + int datapattern; + unsigned int len2_plus_sec2; + int trid; + int decval; + int early_break; + + (void)buflen; + + early_break = 0; + trid = 0; + buf_offs_sum = 0; + sector_sizes[0] = 0x924; + sector_sizes[1] = 0x810; + g_cdvdfsv_rmodeee = inbuf->m_pkt_01.m_rmodeee; + lsndualchg_res = inbuf->m_pkt_01.m_lbn; + decval = decflag ? inbuf->m_pkt_01.m_decval : 0; + g_cdvdfsv_eerpsdd.src = &g_cdvdfsv_readpos; + g_cdvdfsv_eerpsdd.size = sizeof(g_cdvdfsv_readpos); + g_cdvdfsv_eerpsdd.attr = 0; + g_cdvdfsv_eerpsdd.dest = (void *)inbuf->m_pkt_01.m_eedest; + if ( ps2dvd ) + { + if ( !sceCdSC(0xFFFFFFEA, &scres_unused) ) + { + g_cdvdfsv_rderror = SCECdErREADCFR; + sceCdSC(0xFFFFFFFE, &g_cdvdfsv_rderror); + bsize = 0; + psize = 0; + ssize = 0; + saddr = 0; + paddr = 0; + early_break = 1; + } + else + { + lsndualchg_res = sceCdSC(0xFFFFFFE9, &lsndualchg_res); + secsize = 0x800; + datapattern = SCECdSecS2048; + g_cdvdfsv_rmodeee.datapattern = SCECdSecS2048; + } + } + else + { + datapattern = g_cdvdfsv_rmodeee.datapattern; + switch ( datapattern ) + { + case SCECdSecS2328: + secsize = 0x918; + break; + case SCECdSecS2340: + secsize = 0x924; + break; + case SCECdSecS2048: + default: + secsize = 0x800; + break; + } + g_cdvdfsv_rmodeee.datapattern = SCECdSecS2340; + } + len2_plus_sec2 = lsndualchg_res + inbuf->m_pkt_01.m_sectors; + if ( !early_break ) + { + int all_sec_bytes; + + all_sec_bytes = secsize * inbuf->m_pkt_01.m_sectors; + if ( g_cdvdfsv_spinctl != -1 ) + g_cdvdfsv_rmodeee.spindlctrl = g_cdvdfsv_spinctl; + paddr = inbuf->m_pkt_01.m_paddr; + saddr = (paddr + all_sec_bytes) & ~0x3F; + psize = ((paddr & 0x3F)) ? ((paddr & ~0x3F) - (paddr - 0x40)) : 0; + bsize = saddr - (paddr + psize); + ssize = paddr + all_sec_bytes - saddr; + VERBOSE_KPRINTF(1, "CD/DVD-ROM lsn= %d sec= %d\n", lsndualchg_res, inbuf->m_pkt_01.m_sectors); + VERBOSE_KPRINTF(1, "f psize= %d bsize= %d ssize= %d\n", psize, bsize, ssize); + } + if ( psize ) + { + u32 sectors; + + sectors = (len2_plus_sec2 < lsndualchg_res + buf_offs_sum / secsize + 2) ? 1 : 2; + VERBOSE_PRINTF( + 1, + "0 CD_READ LBN= %d sectors= %d all= %d\n", + (int)(lsndualchg_res + buf_offs_sum / secsize), + (int)sectors, + (int)inbuf->m_pkt_01.m_sectors); + if ( !readproc1( + lsndualchg_res + buf_offs_sum / secsize, + sectors, + g_cdvdfsv_rtocbuf, + &g_cdvdfsv_rmodeee, + ps2dvd, + sync, + decflag, + decval) ) + { + ssize = 0; + psize = 0; + bsize = 0; + } + else + { + if ( datapattern != SCECdSecS2340 || ps2dvd ) + { + int rtoc_ind; + + rtoc_ind = 12; + for ( i = 0; i < psize; i += 1 ) + { + rtoc_ind += (i && !(i % secsize)) ? (sector_sizes[ps2dvd] - secsize) : 0; + g_cdvdfsv_eereadx.m_pbuf1[i] = g_cdvdfsv_rtocbuf[rtoc_ind + i]; + } + } + else + { + for ( i = 0; i < psize; i += 1 ) + g_cdvdfsv_eereadx.m_pbuf1[i] = g_cdvdfsv_rtocbuf[i]; + } + buf_offs_sum += psize; + } + } + bsize_tmp = bsize; + for ( i = 0; i < bsize; i += sizestuff ) + { + u32 offs_sector_only; + + bsize_tmp = bsize - i; + if ( g_cdvdfsv_spinctl != -1 ) + g_cdvdfsv_rmodeee.spindlctrl = g_cdvdfsv_spinctl; + offs_sector_only = lsndualchg_res + buf_offs_sum / secsize; + if ( (unsigned int)(secsize << 6) >= bsize_tmp ) + { + needed_offset = (bsize_tmp / secsize) + (!!(bsize_tmp % secsize)); + sizestuff = bsize_tmp; + } + else + { + needed_offset = (((offs_sector_only & 0xF)) && (!(secsize & 0xF))) ? (0x10 - (offs_sector_only & 0xF)) : 0x40; + sizestuff = secsize * needed_offset; + } + needed_offset += !!((buf_offs_sum + i) % secsize); + if ( len2_plus_sec2 < offs_sector_only + needed_offset ) + needed_offset = len2_plus_sec2 - (lsndualchg_res + (buf_offs_sum + i) / secsize); + g_cdvdfsv_readpos = buf_offs_sum + i; + if ( !readproc2( + offs_sector_only, + needed_offset, + &g_cdvdfsv_rmodeee, + ps2dvd, + sync, + decflag, + decval, + (char *)(inbuf->m_pkt_01.m_paddr + psize) + i, + (buf_offs_sum + i) % secsize, + secsize, + sizestuff, + &g_cdvdfsv_eerpsdd) ) + { + bsize_tmp = 0; + early_break = 1; + break; + } + while ( cdvdfsv_checkdmastat(trid) >= 0 ) + ; + CpuSuspendIntr(&state); + trid = sceSifSetDma(&g_cdvdfsv_eerpsdd, 1); + CpuResumeIntr(state); + } + buf_offs_sum += i; + bsize = bsize_tmp; + if ( !early_break && ssize ) + { + u32 sectors_1; + unsigned int buf_offs_sum_bytes_in_sector; + + buf_offs_sum_bytes_in_sector = buf_offs_sum % secsize; + sectors_1 = (len2_plus_sec2 < lsndualchg_res + buf_offs_sum / secsize + 2) ? 1 : 2; + VERBOSE_PRINTF( + 1, "2 CD_READ LBN= %d sectors= %d\n", (int)(lsndualchg_res + buf_offs_sum / secsize), (int)sectors_1); + if ( !readproc1( + lsndualchg_res + buf_offs_sum / secsize, + sectors_1, + g_cdvdfsv_rtocbuf, + &g_cdvdfsv_rmodeee, + ps2dvd, + sync, + decflag, + decval) ) + { + bsize = 0; + } + else + { + if ( datapattern != SCECdSecS2340 || ps2dvd ) + { + int i2_offs; + + i2_offs = 12; + for ( i = 0; i < ssize; i += 1 ) + { + i2_offs += + ((i + buf_offs_sum_bytes_in_sector) + && (i % secsize) == (secsize - (buf_offs_sum_bytes_in_sector ? buf_offs_sum_bytes_in_sector : secsize))) ? + (sector_sizes[ps2dvd] - secsize) : + 0; + g_cdvdfsv_eereadx.m_pbuf2[i] = g_cdvdfsv_rtocbuf[buf_offs_sum_bytes_in_sector + i2_offs + i]; + } + } + else + { + for ( i = 0; i < ssize; i += 1 ) + g_cdvdfsv_eereadx.m_pbuf2[i] = g_cdvdfsv_rtocbuf[buf_offs_sum_bytes_in_sector + i]; + } + buf_offs_sum += ssize; + } + } + g_cdvdfsv_eereadx.m_b1len = psize; + g_cdvdfsv_eereadx.m_b2len = ssize; + g_cdvdfsv_eereadx.m_b1dst = paddr; + g_cdvdfsv_eereadx.m_b2dst = saddr; + VERBOSE_PRINTF( + 1, "b psize= %d paddr= %08x bsize= %d ssize= %d saddr %08x\n", (int)psize, paddr, (int)bsize, (int)ssize, saddr); + while ( cdvdfsv_checkdmastat(trid) >= 0 ) + ; + g_cdvdfsv_datasdd.src = &g_cdvdfsv_eereadx; + g_cdvdfsv_datasdd.size = sizeof(g_cdvdfsv_eereadx); + g_cdvdfsv_datasdd.attr = 0; + g_cdvdfsv_readpos = buf_offs_sum; + g_cdvdfsv_datasdd.dest = (void *)inbuf->m_pkt_01.m_eeremaindest; + while ( 1 ) + { + CpuSuspendIntr(&state); + trid = sceSifSetDma(&g_cdvdfsv_datasdd, 1); + sceSifSetDma(&g_cdvdfsv_eerpsdd, 1); + CpuResumeIntr(state); + if ( trid ) + break; + DelayThread(500); + } + while ( cdvdfsv_checkdmastat(trid) >= 0 ) + ; + g_cdvdfsv_spinctl = -1; + VERBOSE_PRINTF(1, "read end\n"); + outbuf->m_retres = buf_offs_sum; +} + +static int +cdvdfsv_chreadee(int secoffs, int seccount, char *ee_addr, const sceCdRMode *in_rmode, u32 disktype_14, int sync) +{ + unsigned int secsize; + unsigned int i; + int readsize_bytes; + sceCdRMode rmode; + int scres_unused; + int lsndualchg_res; + + lsndualchg_res = secoffs; + rmode = *in_rmode; + if ( disktype_14 ) + { + if ( !sceCdSC(0xFFFFFFEA, &scres_unused) ) + { + g_cdvdfsv_rderror = SCECdErREADCFR; + sceCdSC(0xFFFFFFFE, &g_cdvdfsv_rderror); + return 1; + } + secsize = 0x800; + lsndualchg_res = sceCdSC(0xFFFFFFE9, &lsndualchg_res); + rmode.datapattern = SCECdSecS2048; + } + else + { + switch ( rmode.datapattern ) + { + case SCECdSecS2328: + secsize = 0x918; + break; + case SCECdSecS2340: + secsize = 0x924; + break; + case SCECdSecS2048: + default: + secsize = 0x800; + break; + } + rmode.datapattern = SCECdSecS2340; + } + for ( i = 0; i < (unsigned int)(secsize * seccount); i += readsize_bytes ) + { + unsigned int bytescount; + int sectors_partial; + int bytescount_in_sectors; + + bytescount = (unsigned int)(secsize * seccount) - i; + sectors_partial = (lsndualchg_res + i / secsize) & 0xF; + bytescount_in_sectors = 0x10; + readsize_bytes = secsize * bytescount_in_sectors; + if ( (unsigned int)readsize_bytes >= bytescount ) + { + bytescount_in_sectors = (bytescount / secsize) + (!!(bytescount % secsize)); + readsize_bytes = bytescount; + } + else if ( sectors_partial && !(secsize & 0xF) ) + { + bytescount_in_sectors -= sectors_partial; + } + if ( !readproc2( + lsndualchg_res + i / secsize, + bytescount_in_sectors, + &rmode, + disktype_14, + sync, + 0, + 0, + ee_addr + i, + 0, + secsize, + readsize_bytes, + 0) ) + { + break; + } + } + return 1; +} + +void cdvdfsv_rpc5_0F_readchain(const cdvdfsv_rpc5_inpacket_t *inbuf, int buflen, cdvdfsv_rpc5_outpacket_t *outbuf) +{ + int sector_size; + unsigned int i; + const sceCdRChain *chain; + void *buf; + int re_result; + int trid; + int scres_unused; + int state; + + (void)buflen; + (void)outbuf; + + g_cdvdfsv_rderror = SCECdErREADCFR; + g_cdvdfsv_readpos = 0; + g_cdvdman_istruct_ptr->m_break_cdvdfsv_readchain = 0; + g_cdvdfsv_chrdsdd.src = &g_cdvdfsv_readpos; + g_cdvdfsv_chrdsdd.size = sizeof(g_cdvdfsv_readpos); + g_cdvdfsv_chrdsdd.attr = 0; + g_cdvdfsv_chrdsdd.dest = (void *)inbuf->m_pkt_0F.m_eedest; + switch ( inbuf->m_pkt_0F.m_mode.datapattern ) + { + case SCECdSecS2328: + sector_size = 0x918; + break; + case SCECdSecS2340: + sector_size = 0x924; + break; + case SCECdSecS2048: + default: + sector_size = 0x800; + break; + } + chain = inbuf->m_pkt_0F.m_readChain; + for ( i = 0; i < 0x40; i += 1 ) + { + if ( g_cdvdman_istruct_ptr->m_break_cdvdfsv_readchain ) + { + VERBOSE_PRINTF(1, "ReadChain cnt %d on sceCdBreak()\n", (int)i); + return; + } + if ( chain[i].lbn == 0xFFFFFFFF || chain[i].sectors == 0xFFFFFFFF || chain[i].buffer == 0xFFFFFFFF ) + return; + if ( (chain[i].buffer & 1) ) + { + buf = (void *)(chain[i].buffer & ~1); + VERBOSE_PRINTF( + 1, + "ReadChain lsn= %d nsec= %d buf= %08x secsize= %d\n", + (int)(chain[i].lbn), + (int)(chain[i].sectors), + (unsigned int)(uiptr)buf, + inbuf->m_pkt_0F.m_mode.datapattern); + re_result = sceCdRE(chain[i].lbn, chain[i].sectors, buf, (sceCdRMode *)&(inbuf->m_pkt_0F.m_mode)); + if ( re_result == 1 ) + { + sceCdSync(0); + re_result = !sceCdGetError(); + } + else + { + sceCdSC(0xFFFFFFFE, &g_cdvdfsv_rderror); + } + } + else + { + VERBOSE_PRINTF( + 1, "ReadChain EE Memory addr= 0x%08x sector= %d\n", (unsigned int)(chain[i].lbn), (int)(chain[i].sectors)); + // The following call to sceCdGetDiskType was inlined + re_result = cdvdfsv_chreadee( + chain[i].lbn, + chain[i].sectors, + (char *)chain[i].buffer, + &(inbuf->m_pkt_0F.m_mode), + sceCdGetDiskType() == SCECdPS2DVD, + !sceCdSC(0xFFFFFFFC, &scres_unused)); + } + if ( !re_result ) + { + VERBOSE_PRINTF(1, "ReadChain error code= 0x%02x\n", sceCdGetError()); + break; + } + g_cdvdfsv_readpos += chain[i].sectors * sector_size; + while ( 1 ) + { + CpuSuspendIntr(&state); + trid = sceSifSetDma(&g_cdvdfsv_chrdsdd, 1); + CpuResumeIntr(state); + if ( trid ) + break; + DelayThread(500); + } + while ( cdvdfsv_checkdmastat(trid) >= 0 ) + ; + } +} + +void cdvdfsv_rpc5_02_readcdda(const cdvdfsv_rpc5_inpacket_t *inbuf, int buflen, cdvdfsv_rpc5_outpacket_t *outbuf) +{ + int trid1; + unsigned int sector_size; + int all_sec_bytes; + unsigned int buf_1_toalign; + int cmd_error; + int error_code; + unsigned int i; + int trid2; + int state; + int error_code_tmp; + unsigned int buf_offs; + unsigned int buf_toalign; + unsigned int buf_sec_tmp; + unsigned int lbn_1_end; + + trid1 = 0; + g_cdvdfsv_rderror = SCECdErREADCFR; + error_code_tmp = 0; + g_cdvdfsv_eereadfull_dma2.src = &g_cdvdfsv_readpos; + g_cdvdfsv_eereadfull_dma2.size = sizeof(g_cdvdfsv_readpos); + g_cdvdfsv_eereadfull_dma2.attr = 0; + g_cdvdfsv_eereadfull_dma2.dest = (void *)inbuf->m_pkt_02.m_eedest; + switch ( inbuf->m_pkt_02.m_mode.datapattern ) + { + case SCECdSecS2368: + sector_size = 0x940; + break; + case SCECdSecS2352: + case SCECdSecS2448: + default: + sector_size = 0x930; + break; + } + buf_offs = 0; + all_sec_bytes = sector_size * inbuf->m_pkt_02.m_sectors; + lbn_1_end = inbuf->m_pkt_02.m_lbn + inbuf->m_pkt_02.m_sectors; + buf_toalign = + ((inbuf->m_pkt_02.m_buf & 0x3F)) ? ((inbuf->m_pkt_02.m_buf & ~0x3F) - (inbuf->m_pkt_02.m_buf - 0x40)) : 0; + buf_1_toalign = (inbuf->m_pkt_02.m_buf + all_sec_bytes) & ~0x3F; + buf_sec_tmp = all_sec_bytes - (buf_1_toalign - inbuf->m_pkt_02.m_buf); + if ( buf_toalign ) + { + unsigned int buf_offs_sectors; + u32 sectors_1; + + buf_offs_sectors = buf_offs / sector_size; + sectors_1 = (lbn_1_end < inbuf->m_pkt_02.m_lbn + buf_offs / sector_size + 2) ? 1 : 2; + VERBOSE_PRINTF( + 1, + "0 CD_READ LBN= %d sectors= %d all= %d\n", + (int)(inbuf->m_pkt_02.m_lbn + buf_offs_sectors), + (int)sectors_1, + (int)inbuf->m_pkt_02.m_sectors); + cmd_error = sceCdReadCDDA( + inbuf->m_pkt_02.m_lbn + buf_offs_sectors, sectors_1, g_cdvdfsv_rtocbuf, (sceCdRMode *)&inbuf->m_pkt_02.m_mode); + sceCdSync(3); + error_code = sceCdGetError(); + if ( error_code || !cmd_error ) + { + if ( !cmd_error ) + sceCdSC(0xFFFFFFFE, &g_cdvdfsv_rderror); + VERBOSE_PRINTF(1, "Read error code %x cmd error %d\n", error_code, cmd_error); + if ( error_code == SCECdErEOM || error_code == SCECdErSFRMTNG ) + error_code_tmp = error_code; + else + { + buf_toalign = 0; + } + } + if ( error_code_tmp && error_code_tmp != SCECdErEOM && error_code_tmp != SCECdErSFRMTNG ) + { + for ( i = 0; i < buf_toalign; i += 1 ) + { + g_cdvdfsv_eereadx.m_pbuf1[i] = g_cdvdfsv_rtocbuf[i]; + } + buf_offs += buf_toalign; + } + } + if ( error_code_tmp && error_code_tmp != SCECdErEOM && error_code_tmp != SCECdErSFRMTNG ) + { + unsigned int sector_count_in_bytes; + unsigned int buf_aligned; + + for ( buf_aligned = inbuf->m_pkt_02.m_buf + buf_toalign; buf_aligned < buf_1_toalign; + buf_aligned += sector_count_in_bytes ) + { + unsigned int buf_align_remain; + unsigned int buf_offs_mod_sector_size; + u32 lsn_2; + u32 sector_count; + + buf_align_remain = buf_1_toalign - buf_aligned; + buf_offs_mod_sector_size = buf_offs % sector_size; + lsn_2 = inbuf->m_pkt_02.m_lbn + buf_offs / sector_size; + sector_count_in_bytes = 8 * sector_size; + if ( sector_count_in_bytes >= buf_align_remain ) + { + sector_count_in_bytes = buf_align_remain; + sector_count = + (buf_align_remain / sector_size) + (!!(buf_align_remain % sector_size)) + (!!buf_offs_mod_sector_size); + } + else + { + sector_count = 8 + (!!(buf_offs % sector_size)); + } + if ( sector_count > lbn_1_end - lsn_2 ) + sector_count = lbn_1_end - lsn_2; + while ( cdvdfsv_checkdmastat(trid1) >= 0 ) + ; + cmd_error = sceCdReadCDDA(lsn_2, sector_count, g_cdvdfsv_rtocbuf, (sceCdRMode *)&inbuf->m_pkt_02.m_mode); + sceCdSync(3); + error_code = sceCdGetError(); + if ( error_code || !cmd_error ) + { + if ( !cmd_error ) + sceCdSC(0xFFFFFFFE, &g_cdvdfsv_rderror); + VERBOSE_PRINTF(1, "Read error code %x cmd error %d\n", error_code, cmd_error); + if ( error_code == SCECdErEOM || error_code == SCECdErSFRMTNG ) + { + error_code_tmp = error_code; + break; + } + } + if ( buf_offs_mod_sector_size ) + optimized_memcpy(g_cdvdfsv_rtocbuf, &g_cdvdfsv_rtocbuf[buf_offs_mod_sector_size], sector_count_in_bytes); + g_cdvdfsv_eereadfull_dma1.src = g_cdvdfsv_rtocbuf; + g_cdvdfsv_eereadfull_dma1.size = sector_count_in_bytes; + g_cdvdfsv_eereadfull_dma1.attr = 0; + g_cdvdfsv_eereadfull_dma1.dest = (char *)buf_aligned; + g_cdvdfsv_readpos = buf_offs; + while ( 1 ) + { + CpuSuspendIntr(&state); + trid1 = sceSifSetDma(&g_cdvdfsv_eereadfull_dma1, 1); + CpuResumeIntr(state); + if ( trid1 ) + break; + DelayThread(500); + } + if ( (unsigned int)buflen >= 0x19 ) + { + CpuSuspendIntr(&state); + sceSifSetDma(&g_cdvdfsv_eereadfull_dma2, 1); + CpuResumeIntr(state); + } + buf_offs += sector_count_in_bytes; + } + } + if ( (error_code_tmp && error_code_tmp != SCECdErEOM && error_code_tmp != SCECdErSFRMTNG) && buf_sec_tmp ) + { + u32 sectors_3; + u32 lsn_3; + + lsn_3 = inbuf->m_pkt_02.m_lbn + buf_offs / sector_size; + sectors_3 = (lbn_1_end < lsn_3 + 2) ? 1 : 2; + VERBOSE_PRINTF( + 1, + "0 CD_READ LBN= %d sectors= %d all= %d\n", + (int)(inbuf->m_pkt_02.m_lbn + buf_offs / sector_size), + (int)sectors_3, + (int)inbuf->m_pkt_02.m_sectors); + VERBOSE_PRINTF(1, "2 CD_READ LBN= %d sectors= %d\n", (int)lsn_3, (int)sectors_3); + cmd_error = sceCdReadCDDA(lsn_3, sectors_3, g_cdvdfsv_rtocbuf, (sceCdRMode *)&inbuf->m_pkt_02.m_mode); + sceCdSync(3); + error_code = sceCdGetError(); + if ( error_code || !cmd_error ) + { + if ( !cmd_error ) + sceCdSC(0xFFFFFFFE, &g_cdvdfsv_rderror); + VERBOSE_PRINTF(1, "Read error code %x cmd error %d\n", error_code, cmd_error); + if ( error_code == SCECdErEOM || error_code == SCECdErSFRMTNG ) + error_code_tmp = error_code; + else + buf_sec_tmp = 0; + } + for ( i = 0; i < buf_sec_tmp; i += 1 ) + { + g_cdvdfsv_eereadx.m_pbuf2[i] = g_cdvdfsv_rtocbuf[(buf_offs % sector_size) + i]; + } + buf_offs += buf_sec_tmp; + } + g_cdvdfsv_eereadx.m_b1len = buf_toalign; + g_cdvdfsv_eereadx.m_b2len = buf_sec_tmp; + g_cdvdfsv_eereadx.m_b1dst = inbuf->m_pkt_02.m_buf; + g_cdvdfsv_eereadx.m_b2dst = buf_1_toalign; + while ( cdvdfsv_checkdmastat(trid1) >= 0 ) + ; + g_cdvdfsv_eereadfull_dma1.src = &g_cdvdfsv_eereadx; + g_cdvdfsv_eereadfull_dma1.size = sizeof(g_cdvdfsv_eereadx); + g_cdvdfsv_eereadfull_dma1.attr = 0; + g_cdvdfsv_readpos = buf_offs; + g_cdvdfsv_eereadfull_dma1.dest = (void *)inbuf->m_pkt_02.m_eeremaindest; + while ( 1 ) + { + CpuSuspendIntr(&state); + trid2 = sceSifSetDma(&g_cdvdfsv_eereadfull_dma1, 1); + if ( (unsigned int)buflen >= 0x19 ) + sceSifSetDma(&g_cdvdfsv_eereadfull_dma2, 1); + CpuResumeIntr(state); + if ( trid2 ) + break; + DelayThread(500); + } + while ( cdvdfsv_checkdmastat(trid2) >= 0 ) + ; + if ( error_code_tmp ) + sceCdSC(0xFFFFFFFE, &error_code_tmp); + VERBOSE_PRINTF(1, "read end\n"); + outbuf->m_retres = buf_offs; +} + +void *cbrpc_rpc2_diskready(int fno, void *buffer, int length) +{ + (void)fno; + (void)length; + + // The following call to sceCdStatus was inlined + VERBOSE_KPRINTF(1, "DISK READY call 0x%02x\n", sceCdStatus()); + // The following call to sceCdDiskReady was inlined + g_diskready_res.m_retres = sceCdDiskReady(((const cdvdfsv_rpc2_inpacket_t *)buffer)->m_mode); + return (void *)&g_diskready_res; +} + +static void cdvdfsv_rpc5_04_gettoc(const cdvdfsv_rpc5_inpacket_t *inbuf, int buflen, cdvdfsv_rpc5_outpacket_t *outbuf) +{ + int trid; + int state; + + (void)buflen; + + VERBOSE_PRINTF(1, "GET TOC call 0x%08x\n", (int)inbuf); + outbuf->m_retres = sceCdGetToc((u8 *)g_cdvdfsv_rtocbuf); + VERBOSE_PRINTF(1, "GET TOC called\n"); + g_cdvdfsv_rtocsdd.src = g_cdvdfsv_rtocbuf; + g_cdvdfsv_rtocsdd.size = 0x810; + g_cdvdfsv_rtocsdd.attr = 0; + g_cdvdfsv_rtocsdd.dest = (void *)inbuf->m_pkt_04.m_eedest; + while ( 1 ) + { + CpuSuspendIntr(&state); + trid = sceSifSetDma(&g_cdvdfsv_rtocsdd, 1); + CpuResumeIntr(state); + if ( trid ) + break; + DelayThread(500); + } + while ( cdvdfsv_checkdmastat(trid) >= 0 ) + ; + // The following call to sceCdGetDiskType was inlined + switch ( sceCdGetDiskType() ) + { + case SCECdPS2DVD: + case SCECdDVDVR: + case SCECdDVDV: + outbuf->m_pkt_04.m_isdvd = 1; + break; + default: + outbuf->m_pkt_04.m_isdvd = 0; + break; + } +} + +static void cdvdfsv_rpc3_03_disktype(const cdvdfsv_rpc3_inpacket_t *inbuf, int buflen, cdvdfsv_rpc3_outpacket_t *outbuf) +{ + (void)inbuf; + (void)buflen; + + outbuf->m_retres = sceCdGetDiskType(); +} + +static void cdvdfsv_rpc3_0C_cdstatus(const cdvdfsv_rpc3_inpacket_t *inbuf, int buflen, cdvdfsv_rpc3_outpacket_t *outbuf) +{ + (void)inbuf; + (void)buflen; + + outbuf->m_retres = sceCdStatus(); +} + +static void cdvdfsv_rpc3_06_ri(const cdvdfsv_rpc3_inpacket_t *inbuf, int buflen, cdvdfsv_rpc3_outpacket_t *outbuf) +{ + int i; + u32 efbits; + + (void)inbuf; + (void)buflen; + + outbuf->m_retres = 0; + for ( i = 0; i < 3 && !outbuf->m_retres; i += 1 ) + { + WaitEventFlag(g_scmd_evid, 1, WEF_AND, &efbits); + outbuf->m_retres = sceCdRI(outbuf->m_pkt_06.m_buffer, &outbuf->m_pkt_06.m_result); + } +} + +static void cdvdfsv_rpc3_1A_rm(const cdvdfsv_rpc3_inpacket_t *inbuf, int buflen, cdvdfsv_rpc3_outpacket_t *outbuf) +{ + int i; + u32 efbits; + + (void)inbuf; + (void)buflen; + + outbuf->m_retres = 0; + for ( i = 0; i < 3 && !outbuf->m_retres; i += 1 ) + { + WaitEventFlag(g_scmd_evid, 1, WEF_AND, &efbits); + outbuf->m_retres = sceCdRM(outbuf->m_pkt_1A.m_buffer, &outbuf->m_pkt_1A.m_status); + } +} + +#ifdef CDVD_VARIANT_DNAS +static void cdvdfsv_rpc3_24_readguid(const cdvdfsv_rpc3_inpacket_t *inbuf, int buflen, cdvdfsv_rpc3_outpacket_t *outbuf) +{ + int i; + u32 efbits; + + (void)inbuf; + (void)buflen; + + outbuf->m_retres = 0; + for ( i = 0; i < 3 && !outbuf->m_retres; i += 1 ) + { + WaitEventFlag(g_scmd_evid, 1, WEF_AND, &efbits); + outbuf->m_retres = sceCdReadGUID(&outbuf->m_pkt_24.m_guid); + } +} + +static void +cdvdfsv_rpc3_26_readmodelid(const cdvdfsv_rpc3_inpacket_t *inbuf, int buflen, cdvdfsv_rpc3_outpacket_t *outbuf) +{ + int i; + u32 efbits; + + (void)inbuf; + (void)buflen; + + outbuf->m_retres = 0; + for ( i = 0; i < 3 && !outbuf->m_retres; i += 1 ) + { + WaitEventFlag(g_scmd_evid, 1, WEF_AND, &efbits); + outbuf->m_retres = sceCdReadModelID(&outbuf->m_pkt_26.m_id); + } +} +#endif + +static void cdvdfsv_rpc3_22_mmode(const cdvdfsv_rpc3_inpacket_t *inbuf, int buflen, cdvdfsv_rpc3_outpacket_t *outbuf) +{ + if ( buflen == 4 || !inbuf->m_pkt_22.m_char4 ) + { + outbuf->m_retres = sceCdMmode(inbuf->m_pkt_22.m_media); + } +} + +static void +cdvdfsv_rpc3_23_changethreadpriority(const cdvdfsv_rpc3_inpacket_t *inbuf, int buflen, cdvdfsv_rpc3_outpacket_t *outbuf) +{ + (void)buflen; + + outbuf->m_retres = sceCdChangeThreadPriority(inbuf->m_pkt_23.m_priority); +} + +static void cdvdfsv_rpc3_21_poweroff(const cdvdfsv_rpc3_inpacket_t *inbuf, int buflen, cdvdfsv_rpc3_outpacket_t *outbuf) +{ + int i; + u32 efbits; + + (void)inbuf; + (void)buflen; + + outbuf->m_retres = 0; + for ( i = 0; i < 3 && !outbuf->m_retres; i += 1 ) + { + WaitEventFlag(g_scmd_evid, 1, WEF_AND, &efbits); + outbuf->m_retres = sceCdPowerOff(&outbuf->m_pkt_21.m_result); + } +} + +static void +cdvdfsv_rpc3_15_ctrladout(const cdvdfsv_rpc3_inpacket_t *inbuf, int buflen, cdvdfsv_rpc3_outpacket_t *outbuf) +{ + int i; + u32 efbits; + + (void)buflen; + + outbuf->m_retres = 0; + for ( i = 0; i < 3 && !outbuf->m_retres; i += 1 ) + { + WaitEventFlag(g_scmd_evid, 1, WEF_AND, &efbits); + outbuf->m_retres = sceCdCtrlADout(inbuf->m_pkt_15.m_mode, &outbuf->m_pkt_15.m_status); + } +} + +static void +cdvdfsv_rpc3_01_readclock(const cdvdfsv_rpc3_inpacket_t *inbuf, int buflen, cdvdfsv_rpc3_outpacket_t *outbuf) +{ + int i; + u32 efbits; + + (void)inbuf; + (void)buflen; + + outbuf->m_retres = 0; + for ( i = 0; i < 3 && !outbuf->m_retres; i += 1 ) + { + WaitEventFlag(g_scmd_evid, 1, WEF_AND, &efbits); + outbuf->m_retres = sceCdReadClock(&outbuf->m_pkt_01.m_clock); + } +} + +#ifdef CDVD_VARIANT_DNAS +static void +cdvdfsv_rpc5_11_readdiskid(const cdvdfsv_rpc5_inpacket_t *inbuf, int buflen, cdvdfsv_rpc5_outpacket_t *outbuf) +{ + (void)inbuf; + (void)buflen; + + outbuf->m_retres = sceCdReadDiskID((unsigned int *)&(outbuf->m_pkt_11.m_diskid)); +} + +static void +cdvdfsv_rpc5_17_doesuniquekeyexist(const cdvdfsv_rpc5_inpacket_t *inbuf, int buflen, cdvdfsv_rpc5_outpacket_t *outbuf) +{ + (void)inbuf; + (void)buflen; + + outbuf->m_retres = sceCdDoesUniqueKeyExist(&outbuf->m_pkt_17.m_status); +} +#endif + +static void +cdvdfsv_rpc3_0B_applyscmd(const cdvdfsv_rpc3_inpacket_t *inbuf, int buflen, cdvdfsv_rpc3_outpacket_t *outbuf) +{ + (void)buflen; + + sceCdApplySCmd( + inbuf->m_pkt_0B.m_cmdNum, &inbuf->m_pkt_0B.m_inBuff, inbuf->m_pkt_0B.m_inBuffSize, &(outbuf->m_pkt_0B.m_outbuf)); +} + +static void +cdvdfsv_rpc5_0C_applyncmd(const cdvdfsv_rpc5_inpacket_t *inbuf, int buflen, cdvdfsv_rpc5_outpacket_t *outbuf) +{ + (void)buflen; + + outbuf->m_retres = sceCdApplyNCmd(inbuf->m_pkt_0C.m_cmdNum, &inbuf->m_pkt_0C.m_inBuff, inbuf->m_pkt_0C.m_inBuffSize); + sceCdSync(2); +} + +static void cdvdfsv_rpc3_04_geterror(const cdvdfsv_rpc3_inpacket_t *inbuf, int buflen, cdvdfsv_rpc3_outpacket_t *outbuf) +{ + (void)inbuf; + (void)buflen; + + outbuf->m_retres = sceCdGetError(); +} + +static void cdvdfsv_rpc3_05_trayreq(const cdvdfsv_rpc3_inpacket_t *inbuf, int buflen, cdvdfsv_rpc3_outpacket_t *outbuf) +{ + int i; + u32 efbits; + + (void)buflen; + + outbuf->m_retres = 0; + for ( i = 0; i < 3 && !outbuf->m_retres; i += 1 ) + { + WaitEventFlag(g_scmd_evid, 1, WEF_AND, &efbits); + outbuf->m_retres = sceCdTrayReq(inbuf->m_pkt_05.m_param, &outbuf->m_pkt_05.m_traychk); + } +} + +static void +cdvdfsv_rpc3_25_settimeout(const cdvdfsv_rpc3_inpacket_t *inbuf, int buflen, cdvdfsv_rpc3_outpacket_t *outbuf) +{ + (void)buflen; + + outbuf->m_retres = sceCdSetTimeout(inbuf->m_pkt_25.m_param, inbuf->m_pkt_25.m_timeout); +} + +static void +cdvdfsv_rpc3_27_readdvddualinfo(const cdvdfsv_rpc3_inpacket_t *inbuf, int buflen, cdvdfsv_rpc3_outpacket_t *outbuf) +{ + (void)inbuf; + (void)buflen; + + outbuf->m_retres = sceCdReadDvdDualInfo(&outbuf->m_pkt_27.m_on_dual, &outbuf->m_pkt_27.m_layer1_start); +} + +static int cdvdfsv_rpc5_0E_diskready() +{ + int is_detecting; + int scres_unused; + + is_detecting = 0; + // The following call to sceCdGetDiskType was inlined + switch ( sceCdGetDiskType() ) + { + case SCECdDETCT: + case SCECdDETCTCD: + case SCECdDETCTDVDS: + case SCECdDETCTDVDD: + is_detecting = 1; + break; + default: + break; + } + // The following call to sceCdDiskReady was inlined + if ( + (sceCdDiskReady(8) & 0xC0) != 0x40 || sceCdSC(0xFFFFFFFD, &scres_unused) || !sceCdSC(0xFFFFFFF4, &scres_unused) + || is_detecting ) + { + VERBOSE_PRINTF(1, "Drive Not Ready\n"); + return 6; + } + return 2; +} + +static void *cbrpc_rpc5_cdvdncmds(int fno, void *buffer, int length) +{ + int scres_unused; + int fno_1; + + fno_1 = fno; + VERBOSE_PRINTF(1, "sce_cdvd N cmd start %d\n", fno); + g_cdvdfsv_rpc5flg = 1; + sceCdSC(0xFFFFFFF6, &fno_1); + switch ( fno ) + { + case 1: + // The following call to sceCdGetDiskType was inlined + cdvdfsv_rpc5_01_readee( + buffer, length, &g_crr, !(sceCdGetDiskType() ^ SCECdPS2DVD), !sceCdSC(0xFFFFFFFC, &scres_unused), 0); + break; + case 2: + cdvdfsv_rpc5_02_readcdda(buffer, length, &g_crr); + break; + case 4: + cdvdfsv_rpc5_04_gettoc(buffer, length, &g_crr); + break; + case 5: + VERBOSE_PRINTF(1, "Call Seek lsn= %d\n", (int)(((const cdvdfsv_rpc5_inpacket_t *)buffer)->m_pkt_05.m_lbn)); + g_crr.m_retres = sceCdSeek(((const cdvdfsv_rpc5_inpacket_t *)buffer)->m_pkt_05.m_lbn); + VERBOSE_PRINTF(1, "Call Seek end\n"); + sceCdSync(6); + break; + case 6: + VERBOSE_PRINTF(1, "Call Standby\n"); + g_crr.m_retres = sceCdStandby(); + sceCdSync(4); + VERBOSE_PRINTF(1, "Call Standby called\n"); + break; + case 7: + VERBOSE_PRINTF(1, "Call Stop\n"); + g_crr.m_retres = sceCdStop(); + sceCdSync(4); + break; + case 8: + VERBOSE_PRINTF(1, "Call Pause\n"); + g_crr.m_retres = sceCdPause(); + sceCdSync(6); + break; + case 9: + if ( devctl("cdrom_stm0:", 0x4396, buffer, length, &g_crr.m_retres, 4) < 0 ) + g_crr.m_retres = 0; + break; + case 10: + if ( devctl("cdrom_stm0:", 0x4398, buffer, length, &g_crr.m_retres, 4) < 0 ) + g_crr.m_retres = 0; + break; + case 12: + cdvdfsv_rpc5_0C_applyncmd(buffer, length, &g_crr); + break; + case 13: + cdvdfsv_rpc5_0D_iopmread(buffer, length, &g_crr); + break; + case 14: + g_crr.m_retres = cdvdfsv_rpc5_0E_diskready(); + break; + case 15: + cdvdfsv_rpc5_0F_readchain(buffer, length, &g_crr); + break; +#ifdef CDVD_VARIANT_DNAS + case 17: + cdvdfsv_rpc5_11_readdiskid(buffer, length, &g_crr); + break; +#endif + case 19: + // The following call to sceCdGetDiskType was inlined + cdvdfsv_rpc5_01_readee( + buffer, length, &g_crr, !(sceCdGetDiskType() ^ SCECdPS2DVD), 1, !g_cdvdman_istruct_ptr->m_no_dec_flag); + break; +#ifdef CDVD_VARIANT_DNAS + case 23: + cdvdfsv_rpc5_17_doesuniquekeyexist(buffer, length, &g_crr); + break; +#endif + default: + VERBOSE_PRINTF(1, "sce_cdvd no block IO :unrecognized code %x\n", fno); + g_crr.m_retres = 0; + break; + } + fno_1 = 0; + sceCdSC(0xFFFFFFF6, &fno_1); + g_cdvdfsv_rpc5flg = 0; + VERBOSE_PRINTF(1, "sce_cdvd N cmd end\n"); + return (void *)&g_crr; +} + +// cppcheck-suppress constParameterCallback +static void *cbrpc_rpc3_cdvdscmds(int fno, void *buffer, int length) +{ + VERBOSE_PRINTF(1, "sce_cdvd S cmd start %d\n", fno); + g_cdvdfsv_rpc3flg = 1; + switch ( fno ) + { + case 1: + cdvdfsv_rpc3_01_readclock(buffer, length, &g_outbuf); + break; + case 3: + cdvdfsv_rpc3_03_disktype(buffer, length, &g_outbuf); + break; + case 4: + cdvdfsv_rpc3_04_geterror(buffer, length, &g_outbuf); + break; + case 5: + cdvdfsv_rpc3_05_trayreq(buffer, length, &g_outbuf); + break; + case 6: + cdvdfsv_rpc3_06_ri(buffer, length, &g_outbuf); + break; + case 11: + cdvdfsv_rpc3_0B_applyscmd(buffer, length, &g_outbuf); + break; + case 12: + cdvdfsv_rpc3_0C_cdstatus(buffer, length, &g_outbuf); + break; + case 21: + cdvdfsv_rpc3_15_ctrladout(buffer, length, &g_outbuf); + break; + case 22: + cdvdfsv_rpc3_16_break(buffer, length, &g_outbuf); + break; + case 26: + cdvdfsv_rpc3_1A_rm(buffer, length, &g_outbuf); + break; + case 33: + cdvdfsv_rpc3_21_poweroff(buffer, length, &g_outbuf); + break; + case 34: + cdvdfsv_rpc3_22_mmode(buffer, length, &g_outbuf); + break; + case 35: + cdvdfsv_rpc3_23_changethreadpriority(buffer, length, &g_outbuf); + break; +#ifdef CDVD_VARIANT_DNAS + case 36: + cdvdfsv_rpc3_24_readguid(buffer, length, &g_outbuf); + break; +#endif + case 37: + cdvdfsv_rpc3_25_settimeout(buffer, length, &g_outbuf); + break; +#ifdef CDVD_VARIANT_DNAS + case 38: + cdvdfsv_rpc3_26_readmodelid(buffer, length, &g_outbuf); + break; +#endif + case 39: + cdvdfsv_rpc3_27_readdvddualinfo(buffer, length, &g_outbuf); + break; + default: + VERBOSE_PRINTF(1, "sce_cdvd block IO :unrecognized code 0x%02x\n", fno); + g_outbuf.m_retres = 0; + break; + } + VERBOSE_PRINTF(1, "sce_cdvd S cmd end\n"); + g_cdvdfsv_rpc3flg = 0; + return (void *)&g_outbuf; +} + +static void cdvdfsv_poffloop() +{ + int trid; + char cmdpkt[16]; + int scres; + u32 efbits; + + g_cdvdman_intr_efid = sceCdSC(0xFFFFFFF5, &scres); + while ( 1 ) + { + ClearEventFlag(g_cdvdman_intr_efid, ~4); + WaitEventFlag(g_cdvdman_intr_efid, 4, WEF_AND, &efbits); + if ( g_cdvdfsv_nopocm ) + break; + if ( !g_cdvdfsv_plbreak ) + { + while ( 1 ) + { + trid = sceSifSendCmd(0x80000012, cmdpkt, sizeof(cmdpkt), 0, 0, 0); + if ( trid ) + break; + DelayThread(500); + } + while ( cdvdfsv_checkdmastat(trid) >= 0 ) + ; + } + } +} + +static void cdvdfsv_rpc1_th(void *arg) +{ + (void)arg; + + sceSifSetRpcQueue(&g_rpc_qdata1, GetThreadId()); + sceSifRegisterRpc(&g_rpc_sdata1, 0x80000592, cbrpc_rpc1_cdinit, g_rpc_buffer1, 0, 0, &g_rpc_qdata1); + sceSifRegisterRpc(&g_rpc_sdata2, 0x8000059A, cbrpc_rpc2_diskready, g_rpc_buffer2, 0, 0, &g_rpc_qdata1); + sceSifRegisterRpc(&g_rpc_sdata3, 0x80000593, cbrpc_rpc3_cdvdscmds, g_rpc_buffer3, 0, 0, &g_rpc_qdata1); + sceSifRpcLoop(&g_rpc_qdata1); + ExitDeleteThread(); +} + +static void cdvdfsv_rpc3_th(void *arg) +{ + (void)arg; + + sceSifSetRpcQueue(&g_rpc_qdata3, GetThreadId()); + sceSifRegisterRpc(&g_rpc_sdata6, 0x8000059C, cbrpc_rpc2_diskready, g_rpc_buffer2, 0, 0, &g_rpc_qdata3); + sceSifRpcLoop(&g_rpc_qdata3); + ExitDeleteThread(); +} + +static void cdvdfsv_rpc2_th(void *arg) +{ + (void)arg; + + sceSifSetRpcQueue(&g_rpc_qdata2, GetThreadId()); + sceSifRegisterRpc(&g_rpc_sdata4, 0x80000597, cbrpc_rpc4_fscall, g_rpc_buffer4, 0, 0, &g_rpc_qdata2); + sceSifRegisterRpc(&g_rpc_sdata5, 0x80000595, cbrpc_rpc5_cdvdncmds, g_rpc_buffer5, 0, 0, &g_rpc_qdata2); + sceSifRpcLoop(&g_rpc_qdata2); + ExitDeleteThread(); +} + +// Unofficial: unused obfuscation code was removed + +// clang-format off +__asm__ ( + "\t" ".set push" "\n" + "\t" ".set noat" "\n" + "\t" ".set noreorder" "\n" + "\t" ".global optimized_memcpy" "\n" + "\t" "optimized_memcpy:" "\n" + "\t" " srl $a3, $a2, 2" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_12" "\n" + "\t" " or $a3, $a0, $a1" "\n" + "\t" " andi $a3, $a3, 0x3" "\n" + "\t" " bnez $a3, .Loptimized_memcpy_3" "\n" + "\t" " nop" "\n" + "\t" " srl $a3, $a2, 2" "\n" + "\t" " addiu $at, $zero, 0xC" "\n" + "\t" " div $zero, $a3, $at" "\n" + "\t" " mflo $a3" "\n" + "\t" " mfhi $v1" "\n" + "\t" " beqz $v1, .Loptimized_memcpy_2" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_1:" "\n" + "\t" " lw $v0, 0x0($a1)" "\n" + "\t" " addiu $v1, $v1, -0x1" "\n" + "\t" " sw $v0, 0x0($a0)" "\n" + "\t" " addiu $a1, $a1, 0x4" "\n" + "\t" " bnez $v1, .Loptimized_memcpy_1" "\n" + "\t" " addiu $a0, $a0, 0x4" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_12" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_2:" "\n" + "\t" " lw $v0, 0x0($a1)" "\n" + "\t" " lw $v1, 0x4($a1)" "\n" + "\t" " lw $t0, 0x8($a1)" "\n" + "\t" " lw $t1, 0xC($a1)" "\n" + "\t" " lw $t2, 0x10($a1)" "\n" + "\t" " lw $t3, 0x14($a1)" "\n" + "\t" " lw $t4, 0x18($a1)" "\n" + "\t" " lw $t5, 0x1C($a1)" "\n" + "\t" " lw $t6, 0x20($a1)" "\n" + "\t" " lw $t7, 0x24($a1)" "\n" + "\t" " lw $t8, 0x28($a1)" "\n" + "\t" " lw $t9, 0x2C($a1)" "\n" + "\t" " addiu $a3, $a3, -0x1" "\n" + "\t" " sw $v0, 0x0($a0)" "\n" + "\t" " sw $v1, 0x4($a0)" "\n" + "\t" " sw $t0, 0x8($a0)" "\n" + "\t" " sw $t1, 0xC($a0)" "\n" + "\t" " sw $t2, 0x10($a0)" "\n" + "\t" " sw $t3, 0x14($a0)" "\n" + "\t" " sw $t4, 0x18($a0)" "\n" + "\t" " sw $t5, 0x1C($a0)" "\n" + "\t" " sw $t6, 0x20($a0)" "\n" + "\t" " sw $t7, 0x24($a0)" "\n" + "\t" " sw $t8, 0x28($a0)" "\n" + "\t" " sw $t9, 0x2C($a0)" "\n" + "\t" " addiu $a1, $a1, 0x30" "\n" + "\t" " bnez $a3, .Loptimized_memcpy_2" "\n" + "\t" " addiu $a0, $a0, 0x30" "\n" + "\t" " j .Loptimized_memcpy_12" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_3:" "\n" + "\t" " andi $a3, $a0, 0x3" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_6" "\n" + "\t" " andi $a3, $a1, 0x3" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_6" "\n" + "\t" " nop" "\n" + "\t" " srl $a3, $a2, 2" "\n" + "\t" " addiu $at, $zero, 0xC" "\n" + "\t" " div $zero, $a3, $at" "\n" + "\t" " mflo $a3" "\n" + "\t" " mfhi $v1" "\n" + "\t" " beqz $v1, .Loptimized_memcpy_5" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_4:" "\n" + "\t" " lwl $v0, 0x3($a1)" "\n" + "\t" " lwr $v0, 0x0($a1)" "\n" + "\t" " addiu $v1, $v1, -0x1" "\n" + "\t" " swl $v0, 0x3($a0)" "\n" + "\t" " swr $v0, 0x0($a0)" "\n" + "\t" " addiu $a1, $a1, 0x4" "\n" + "\t" " bnez $v1, .Loptimized_memcpy_4" "\n" + "\t" " addiu $a0, $a0, 0x4" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_12" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_5:" "\n" + "\t" " lwl $v0, 0x3($a1)" "\n" + "\t" " lwr $v0, 0x0($a1)" "\n" + "\t" " lwl $v1, 0x7($a1)" "\n" + "\t" " lwr $v1, 0x4($a1)" "\n" + "\t" " lwl $t0, 0xB($a1)" "\n" + "\t" " lwr $t0, 0x8($a1)" "\n" + "\t" " lwl $t1, 0xF($a1)" "\n" + "\t" " lwr $t1, 0xC($a1)" "\n" + "\t" " lwl $t2, 0x13($a1)" "\n" + "\t" " lwr $t2, 0x10($a1)" "\n" + "\t" " lwl $t3, 0x17($a1)" "\n" + "\t" " lwr $t3, 0x14($a1)" "\n" + "\t" " lwl $t4, 0x1B($a1)" "\n" + "\t" " lwr $t4, 0x18($a1)" "\n" + "\t" " lwl $t5, 0x1F($a1)" "\n" + "\t" " lwr $t5, 0x1C($a1)" "\n" + "\t" " lwl $t6, 0x23($a1)" "\n" + "\t" " lwr $t6, 0x20($a1)" "\n" + "\t" " lwl $t7, 0x27($a1)" "\n" + "\t" " lwr $t7, 0x24($a1)" "\n" + "\t" " lwl $t8, 0x2B($a1)" "\n" + "\t" " lwr $t8, 0x28($a1)" "\n" + "\t" " lwl $t9, 0x2F($a1)" "\n" + "\t" " lwr $t9, 0x2C($a1)" "\n" + "\t" " addiu $a3, $a3, -0x1" "\n" + "\t" " swl $v0, 0x3($a0)" "\n" + "\t" " swr $v0, 0x0($a0)" "\n" + "\t" " swl $v1, 0x7($a0)" "\n" + "\t" " swr $v1, 0x4($a0)" "\n" + "\t" " swl $t0, 0xB($a0)" "\n" + "\t" " swr $t0, 0x8($a0)" "\n" + "\t" " swl $t1, 0xF($a0)" "\n" + "\t" " swr $t1, 0xC($a0)" "\n" + "\t" " swl $t2, 0x13($a0)" "\n" + "\t" " swr $t2, 0x10($a0)" "\n" + "\t" " swl $t3, 0x17($a0)" "\n" + "\t" " swr $t3, 0x14($a0)" "\n" + "\t" " swl $t4, 0x1B($a0)" "\n" + "\t" " swr $t4, 0x18($a0)" "\n" + "\t" " swl $t5, 0x1F($a0)" "\n" + "\t" " swr $t5, 0x1C($a0)" "\n" + "\t" " swl $t6, 0x23($a0)" "\n" + "\t" " swr $t6, 0x20($a0)" "\n" + "\t" " swl $t7, 0x27($a0)" "\n" + "\t" " swr $t7, 0x24($a0)" "\n" + "\t" " swl $t8, 0x2B($a0)" "\n" + "\t" " swr $t8, 0x28($a0)" "\n" + "\t" " swl $t9, 0x2F($a0)" "\n" + "\t" " swr $t9, 0x2C($a0)" "\n" + "\t" " addiu $a1, $a1, 0x30" "\n" + "\t" " bnez $a3, .Loptimized_memcpy_5" "\n" + "\t" " addiu $a0, $a0, 0x30" "\n" + "\t" " j .Loptimized_memcpy_12" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_6:" "\n" + "\t" " andi $a3, $a0, 0x3" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_9" "\n" + "\t" " nop" "\n" + "\t" " srl $a3, $a2, 2" "\n" + "\t" " addiu $at, $zero, 0xC" "\n" + "\t" " div $zero, $a3, $at" "\n" + "\t" " mflo $a3" "\n" + "\t" " mfhi $v1" "\n" + "\t" " beqz $v1, .Loptimized_memcpy_8" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_7:" "\n" + "\t" " lw $v0, 0x0($a1)" "\n" + "\t" " addiu $v1, $v1, -0x1" "\n" + "\t" " swl $v0, 0x3($a0)" "\n" + "\t" " swr $v0, 0x0($a0)" "\n" + "\t" " addiu $a1, $a1, 0x4" "\n" + "\t" " bnez $v1, .Loptimized_memcpy_7" "\n" + "\t" " addiu $a0, $a0, 0x4" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_12" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_8:" "\n" + "\t" " lw $v0, 0x0($a1)" "\n" + "\t" " lw $v1, 0x4($a1)" "\n" + "\t" " lw $t0, 0x8($a1)" "\n" + "\t" " lw $t1, 0xC($a1)" "\n" + "\t" " lw $t2, 0x10($a1)" "\n" + "\t" " lw $t3, 0x14($a1)" "\n" + "\t" " lw $t4, 0x18($a1)" "\n" + "\t" " lw $t5, 0x1C($a1)" "\n" + "\t" " lw $t6, 0x20($a1)" "\n" + "\t" " lw $t7, 0x24($a1)" "\n" + "\t" " lw $t8, 0x28($a1)" "\n" + "\t" " lw $t9, 0x2C($a1)" "\n" + "\t" " addiu $a3, $a3, -0x1" "\n" + "\t" " swl $v0, 0x3($a0)" "\n" + "\t" " swr $v0, 0x0($a0)" "\n" + "\t" " swl $v1, 0x7($a0)" "\n" + "\t" " swr $v1, 0x4($a0)" "\n" + "\t" " swl $t0, 0xB($a0)" "\n" + "\t" " swr $t0, 0x8($a0)" "\n" + "\t" " swl $t1, 0xF($a0)" "\n" + "\t" " swr $t1, 0xC($a0)" "\n" + "\t" " swl $t2, 0x13($a0)" "\n" + "\t" " swr $t2, 0x10($a0)" "\n" + "\t" " swl $t3, 0x17($a0)" "\n" + "\t" " swr $t3, 0x14($a0)" "\n" + "\t" " swl $t4, 0x1B($a0)" "\n" + "\t" " swr $t4, 0x18($a0)" "\n" + "\t" " swl $t5, 0x1F($a0)" "\n" + "\t" " swr $t5, 0x1C($a0)" "\n" + "\t" " swl $t6, 0x23($a0)" "\n" + "\t" " swr $t6, 0x20($a0)" "\n" + "\t" " swl $t7, 0x27($a0)" "\n" + "\t" " swr $t7, 0x24($a0)" "\n" + "\t" " swl $t8, 0x2B($a0)" "\n" + "\t" " swr $t8, 0x28($a0)" "\n" + "\t" " swl $t9, 0x2F($a0)" "\n" + "\t" " swr $t9, 0x2C($a0)" "\n" + "\t" " addiu $a1, $a1, 0x30" "\n" + "\t" " bnez $a3, .Loptimized_memcpy_8" "\n" + "\t" " addiu $a0, $a0, 0x30" "\n" + "\t" " j .Loptimized_memcpy_12" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_9:" "\n" + "\t" " srl $a3, $a2, 2" "\n" + "\t" " addiu $at, $zero, 0xC" "\n" + "\t" " div $zero, $a3, $at" "\n" + "\t" " mflo $a3" "\n" + "\t" " mfhi $v1" "\n" + "\t" " beqz $v1, .Loptimized_memcpy_11" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_10:" "\n" + "\t" " lwl $v0, 0x3($a1)" "\n" + "\t" " lwr $v0, 0x0($a1)" "\n" + "\t" " addiu $v1, $v1, -0x1" "\n" + "\t" " sw $v0, 0x0($a0)" "\n" + "\t" " addiu $a1, $a1, 0x4" "\n" + "\t" " bnez $v1, .Loptimized_memcpy_10" "\n" + "\t" " addiu $a0, $a0, 0x4" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_12" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_11:" "\n" + "\t" " lwl $v0, 0x3($a1)" "\n" + "\t" " lwr $v0, 0x0($a1)" "\n" + "\t" " lwl $v1, 0x7($a1)" "\n" + "\t" " lwr $v1, 0x4($a1)" "\n" + "\t" " lwl $t0, 0xB($a1)" "\n" + "\t" " lwr $t0, 0x8($a1)" "\n" + "\t" " lwl $t1, 0xF($a1)" "\n" + "\t" " lwr $t1, 0xC($a1)" "\n" + "\t" " lwl $t2, 0x13($a1)" "\n" + "\t" " lwr $t2, 0x10($a1)" "\n" + "\t" " lwl $t3, 0x17($a1)" "\n" + "\t" " lwr $t3, 0x14($a1)" "\n" + "\t" " lwl $t4, 0x1B($a1)" "\n" + "\t" " lwr $t4, 0x18($a1)" "\n" + "\t" " lwl $t5, 0x1F($a1)" "\n" + "\t" " lwr $t5, 0x1C($a1)" "\n" + "\t" " lwl $t6, 0x23($a1)" "\n" + "\t" " lwr $t6, 0x20($a1)" "\n" + "\t" " lwl $t7, 0x27($a1)" "\n" + "\t" " lwr $t7, 0x24($a1)" "\n" + "\t" " lwl $t8, 0x2B($a1)" "\n" + "\t" " lwr $t8, 0x28($a1)" "\n" + "\t" " lwl $t9, 0x2F($a1)" "\n" + "\t" " lwr $t9, 0x2C($a1)" "\n" + "\t" " addiu $a3, $a3, -0x1" "\n" + "\t" " sw $v0, 0x0($a0)" "\n" + "\t" " sw $v1, 0x4($a0)" "\n" + "\t" " sw $t0, 0x8($a0)" "\n" + "\t" " sw $t1, 0xC($a0)" "\n" + "\t" " sw $t2, 0x10($a0)" "\n" + "\t" " sw $t3, 0x14($a0)" "\n" + "\t" " sw $t4, 0x18($a0)" "\n" + "\t" " sw $t5, 0x1C($a0)" "\n" + "\t" " sw $t6, 0x20($a0)" "\n" + "\t" " sw $t7, 0x24($a0)" "\n" + "\t" " sw $t8, 0x28($a0)" "\n" + "\t" " sw $t9, 0x2C($a0)" "\n" + "\t" " addiu $a1, $a1, 0x30" "\n" + "\t" " bnez $a3, .Loptimized_memcpy_11" "\n" + "\t" " addiu $a0, $a0, 0x30" "\n" + "\t" ".Loptimized_memcpy_12:" "\n" + "\t" " andi $v1, $a2, 0x3" "\n" + "\t" " beqz $v1, .Loptimized_memcpy_14" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_13:" "\n" + "\t" " lb $v0, 0x0($a1)" "\n" + "\t" " addiu $v1, $v1, -0x1" "\n" + "\t" " sb $v0, 0x0($a0)" "\n" + "\t" " addiu $a1, $a1, 0x1" "\n" + "\t" " bnez $v1, .Loptimized_memcpy_13" "\n" + "\t" " addiu $a0, $a0, 0x1" "\n" + "\t" ".Loptimized_memcpy_14:" "\n" + "\t" " addu $v0, $a2, $zero" "\n" + "\t" " jr $ra" "\n" + "\t" " nop" "\n" + "\t" ".set pop" "\n" +); +// clang-format on diff --git a/iop/cdvd/cdvdfsv/src/exports.tab b/iop/cdvd/cdvdfsv/src/exports.tab new file mode 100644 index 00000000000..7d10afb0b2a --- /dev/null +++ b/iop/cdvd/cdvdfsv/src/exports.tab @@ -0,0 +1,11 @@ + +DECLARE_EXPORT_TABLE(cdvdfsv, 1, 1) +DECLARE_EXPORT(_start) +DECLARE_EXPORT(_retonly) +DECLARE_EXPORT(_retonly) +DECLARE_EXPORT(_retonly) +DECLARE_EXPORT(cdvdfsv_dummyentry) +DECLARE_EXPORT(sceCdChangeThreadPriority) +END_EXPORT_TABLE + +void _retonly() {} diff --git a/iop/cdvd/cdvdfsv/src/imports.lst b/iop/cdvd/cdvdfsv/src/imports.lst new file mode 100644 index 00000000000..369b5e4af82 --- /dev/null +++ b/iop/cdvd/cdvdfsv/src/imports.lst @@ -0,0 +1,116 @@ + +sysmem_IMPORTS_start +I_Kprintf +sysmem_IMPORTS_end + +loadcore_IMPORTS_start +I_RegisterLibraryEntries +I_ReleaseLibraryEntries +I_QueryLibraryEntryTable +I_QueryBootMode +loadcore_IMPORTS_end + +intrman_IMPORTS_start +I_DisableIntr +I_CpuSuspendIntr +I_CpuResumeIntr +I_QueryIntrContext +intrman_IMPORTS_end + +stdio_IMPORTS_start +I_printf +stdio_IMPORTS_end + +dmacman_IMPORTS_start +I_dmac_ch_set_madr +I_dmac_ch_set_bcr +I_dmac_ch_set_chcr +I_dmac_ch_get_chcr +dmacman_IMPORTS_end + +thbase_IMPORTS_start +I_CreateThread +I_DeleteThread +I_StartThread +I_ExitDeleteThread +I_TerminateThread +I_ChangeThreadPriority +I_GetThreadId +I_ReferThreadStatus +I_DelayThread +I_SetAlarm +I_CancelAlarm +thbase_IMPORTS_end + +thevent_IMPORTS_start +I_iSetEventFlag +I_ClearEventFlag +I_WaitEventFlag +thevent_IMPORTS_end + +sifcmd_IMPORTS_start +I_sceSifSendCmd +I_sceSifInitRpc +I_sceSifRegisterRpc +I_sceSifSetRpcQueue +I_sceSifRpcLoop +I_sceSifRemoveRpc +I_sceSifRemoveRpcQueue +sifcmd_IMPORTS_end + +sifman_IMPORTS_start +I_sceSifInit +I_sceSifSetDma +I_sceSifDmaStat +I_sceSifCheckInit +sifman_IMPORTS_end + +sysclib_IMPORTS_start +I_memcpy +I_strncmp +I_strtol +sysclib_IMPORTS_end + +iomanX_IMPORTS_start +I_devctl +iomanX_IMPORTS_end + +cdvdman_IMPORTS_start +I_sceCdInit +I_sceCdStandby +I_sceCdSeek +I_sceCdGetError +I_sceCdGetToc +I_sceCdSearchFile +I_sceCdSync +I_sceCdGetDiskType +I_sceCdDiskReady +I_sceCdTrayReq +I_sceCdStop +I_sceCdPosToInt +I_sceCdRI +I_sceCdReadClock +I_sceCdStatus +I_sceCdApplySCmd +I_sceCdPause +I_sceCdBreak +I_sceCdReadCDDA +I_sceCdGetReadPos +I_sceCdCtrlADout +I_sceGetFsvRbuf +I_sceCdSC +I_sceCdApplyNCmd +I_sceCdRead0 +I_sceCdRV +I_sceCdRM +I_sceCdPowerOff +I_sceCdMmode +I_sceCdReadDiskID +I_sceCdReadGUID +I_sceCdSetTimeout +I_sceCdReadModelID +I_sceCdReadDvdDualInfo +I_sceCdLayerSearchFile +I_sceCdRE +I_sceCdDoesUniqueKeyExist +cdvdman_IMPORTS_end diff --git a/iop/cdvd/cdvdfsv/src/irx_imports.h b/iop/cdvd/cdvdfsv/src/irx_imports.h new file mode 100644 index 00000000000..058ea077783 --- /dev/null +++ b/iop/cdvd/cdvdfsv/src/irx_imports.h @@ -0,0 +1,30 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +*/ + +#ifndef IOP_IRX_IMPORTS_H +#define IOP_IRX_IMPORTS_H + +#include "irx.h" + +/* Please keep these in alphabetical order! */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif /* IOP_IRX_IMPORTS_H */ From e405b6d768ff482a1ac148f08cb87f6d0da2de15 Mon Sep 17 00:00:00 2001 From: Julian Uy Date: Wed, 23 Oct 2024 09:45:24 -0500 Subject: [PATCH 7/8] add: implementation of cdvdstm module --- iop/cdvd/cdvdstm/Makefile | 15 + iop/cdvd/cdvdstm/src/cdvdstm.c | 1911 ++++++++++++++++++++++++++++ iop/cdvd/cdvdstm/src/exports.tab | 10 + iop/cdvd/cdvdstm/src/imports.lst | 68 + iop/cdvd/cdvdstm/src/irx_imports.h | 29 + 5 files changed, 2033 insertions(+) create mode 100644 iop/cdvd/cdvdstm/Makefile create mode 100644 iop/cdvd/cdvdstm/src/cdvdstm.c create mode 100644 iop/cdvd/cdvdstm/src/exports.tab create mode 100644 iop/cdvd/cdvdstm/src/imports.lst create mode 100644 iop/cdvd/cdvdstm/src/irx_imports.h diff --git a/iop/cdvd/cdvdstm/Makefile b/iop/cdvd/cdvdstm/Makefile new file mode 100644 index 00000000000..ac576d8852e --- /dev/null +++ b/iop/cdvd/cdvdstm/Makefile @@ -0,0 +1,15 @@ +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. + +IOP_CFLAGS += -DBUILDING_CDVD_MODULE +IOP_OBJS = cdvdstm.o imports.o exports.o + +include $(PS2SDKSRC)/Defs.make +include $(PS2SDKSRC)/iop/Rules.bin.make +include $(PS2SDKSRC)/iop/Rules.make +include $(PS2SDKSRC)/iop/Rules.release diff --git a/iop/cdvd/cdvdstm/src/cdvdstm.c b/iop/cdvd/cdvdstm/src/cdvdstm.c new file mode 100644 index 00000000000..b9d61756a32 --- /dev/null +++ b/iop/cdvd/cdvdstm/src/cdvdstm.c @@ -0,0 +1,1911 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +*/ + +#include "irx_imports.h" + +#include +#include +#include + +IRX_ID("cdvd_st_driver", 2, 2); +// Based on the module from SCE SDK 3.1.0. + +extern struct irx_export_table _exp_cdvdstm; + +int cdvdstm_dummyentry(); +int cdvdstm_termcall(); +static unsigned int iop_stream_handler( + unsigned int posszarg1, unsigned int posszarg2, void *buffer, int cmdid, const sceCdRMode *rmode, int *error_ptr); +static unsigned int iop_stream_intr_cb(void *userdata); +static int cdrom_stm_init(); +static int cdrom_stm_deinit(); +static int cdrom_stm_devctl( + iop_file_t *f, const char *name, int cmd, void *inbuf, unsigned int inbuf_len, void *outbuf, unsigned int outbuf_len); +static int cdrom_stm_nulldev(); +static s64 cdrom_stm_nulldev64(); +static void ee_stream_handler_normal(cdrom_stm_devctl_t *instruct, int inbuf_len, int *outres_ptr); +static unsigned int ee_stream_intr_cb_normal(void *userdata); +static void ee_stream_handler_cdda(cdrom_stm_devctl_t *instruct, int inbuf_len, int *outres_ptr); +static unsigned int ee_stream_intr_cb_cdda(void *userdata); +unsigned int optimized_memcpy(char *dst, const char *src, unsigned int n); + +static void iop_stream_intr_cb_thunk(int userdata) +{ + iop_stream_intr_cb((void *)userdata); +} + +static void ee_stream_intr_cb_normal_thunk(int userdata) +{ + ee_stream_intr_cb_normal((void *)userdata); +} + +static void ee_stream_intr_cb_cdda_thunk(int userdata) +{ + ee_stream_intr_cb_cdda((void *)userdata); +} + +static int g_verbose_level = 0; +static int g_cdvdstm_in_deldrv = 0; +static int g_cdvdstm_bufmax = 0; +static int g_cdvdstm_numbytes = 0; +static int g_cdvdstm_bankmax = 0; +static void *g_cdvdstm_buffer = NULL; +static unsigned int g_cdvdstm_sectorcount = 0; +static int g_cdvdstm_last_error_for_iop = 0; +static int g_cdvdstm_retryerr_iop = 0; +static int g_cdvdstm_retrycnt_iop = 0; +static iop_device_ops_t g_cdrom_stm_dev_ops = { + &cdrom_stm_init, + &cdrom_stm_deinit, + (void *)&cdrom_stm_nulldev, + (void *)&cdrom_stm_nulldev, + (void *)&cdrom_stm_nulldev, + (void *)&cdrom_stm_nulldev, + (void *)&cdrom_stm_nulldev, + (void *)&cdrom_stm_nulldev, + &cdrom_stm_nulldev, + (void *)&cdrom_stm_nulldev, + (void *)&cdrom_stm_nulldev, + (void *)&cdrom_stm_nulldev, + (void *)&cdrom_stm_nulldev, + (void *)&cdrom_stm_nulldev, + (void *)&cdrom_stm_nulldev, + (void *)&cdrom_stm_nulldev, + (void *)&cdrom_stm_nulldev, + (void *)&cdrom_stm_nulldev, + (void *)&cdrom_stm_nulldev, + (void *)&cdrom_stm_nulldev, + (void *)&cdrom_stm_nulldev, + (void *)&cdrom_stm_nulldev, + (void *)&cdrom_stm_nulldev64, + &cdrom_stm_devctl, + (void *)&cdrom_stm_nulldev, + (void *)&cdrom_stm_nulldev, + &cdrom_stm_nulldev, +}; +static iop_device_t g_cdrom_stm_dev = {"cdrom_stm", IOP_DT_FSEXT | IOP_DT_FS, 1, "CD-ROM_STM ", &g_cdrom_stm_dev_ops}; +static int g_cdvdstm_last_error_for_ee = 0; +static int g_cdvdstm_bufsz2 = 0; +static int g_cdvdstm_chunksz2 = 0; +static int g_cdvdstm_bankcnt2 = 0; +static void *g_cdvdstm_buffer2 = NULL; +static u32 g_cdvdstm_sectorcount2 = 0; +static int g_cdvdstm_retryerr_ee = 0; +static int g_cdvdstm_retrycnt_ee_normal = 0; +static int g_cdvdstm_usedchunksize2 = 0x930; +static u32 g_cdvdstm_retrycnt_ee_cdda = 0; +static sceCdRMode g_rmode_for_stream0; +static int g_cdvdstm_tgt; +static int g_cdvdstm_semid; +static int g_cdvdman_intr_efid; +static char g_cdvdstm_usedmap_iop[512]; +static unsigned int g_cdvdstm_lsn_iop; +static int g_cdvdstm_bankgp_iop; +static int g_cdvdstm_bankcur_iop; +static int g_cdvdstm_bankoffs_iop; +static sceCdRMode g_cdvdstm_mode_iop; +static int g_cdvdstm_stmstart_iop; +static iop_sys_clock_t g_cdvdstm_curclk_iop; +static SifDmaTransfer_t g_cdvdstm_dmat; +static int g_cdvdstm_readlbn_ee_normal; +static SifDmaTransfer_t g_cdvdstm_dmat2; +static u32 g_cdvdstm_readlbn_ee_cdda; +static char g_cdvdstm_usedmap_ee[512]; +static u32 g_cdvdstm_lsn_ee; +static int g_cdvdstm_bankgp_ee; +static int g_cdvdstm_bankcur_ee; +static int g_cdvdstm_bankoffs_ee; +static sceCdRMode g_cdvdstm_mode_ee; +static int g_cdvdstm_stmstart_ee; +static iop_sys_clock_t g_cdvdstm_curclk_ee; + +static int vCancelAlarm(unsigned int (*alarm_cb)(void *), void *arg) +{ + return (QueryIntrContext() ? iCancelAlarm : CancelAlarm)(alarm_cb, arg); +} + +static int vSetEventFlag() +{ + return (QueryIntrContext() ? iSetEventFlag : SetEventFlag)(g_cdvdman_intr_efid, 8); +} + +static int vClearEventFlag() +{ + return (QueryIntrContext() ? iClearEventFlag : ClearEventFlag)(g_cdvdman_intr_efid, ~8); +} + +int cdvdstm_dummyentry() +{ + VERBOSE_PRINTF(1, "Dummy Entry Called\n"); + return 0; +} + +int cdvdstm_termcall() +{ + cdrom_stm_devctl_t instruct; + int outres; + + memset(&instruct, 0, sizeof(instruct)); + instruct.m_cmdid = 3; + instruct.m_rmode.datapattern = SCECdSecS2048; + instruct.m_rmode.spindlctrl = SCECdSpinMax; + instruct.m_rmode.trycount = 0; + ee_stream_handler_normal(&instruct, 0x14, &outres); + sceCdStStop(); + return 0; +} + +static int stm_iop_read_timeout_alarm_cb(const iop_sys_clock_t *sys_clock) +{ + KPRINTF("Stm Iop Read Time Out %d(msec)\n", sys_clock->lo / 0x9000); + return !sceCdBreak(); +} + +static int sceCdStream0_inner(unsigned int rdsize, char *addrarg, int modearg, int *error_ptr) +{ + int cur_size; + unsigned int streamres; + int last_error; + u32 efbits; + int err; + + VERBOSE_KPRINTF(1, "sceCdStream0 call read size= %d mode= %d addr= %08x\n", rdsize, modearg, addrarg); + cur_size = 0; + if ( !sceCdSC(0xFFFFFFFF, &last_error) ) + return 0; + *error_ptr = 0; + if ( !modearg ) + return iop_stream_handler(0, rdsize, addrarg, 2, &g_rmode_for_stream0, error_ptr); + vSetEventFlag(); + err = 0; + streamres = 0; + while ( (!err || streamres) ) + { + WaitEventFlag(g_cdvdman_intr_efid, 8, WEF_AND, &efbits); + streamres = iop_stream_handler(0, rdsize - cur_size, &addrarg[cur_size], 2, &g_rmode_for_stream0, &err); + if ( rdsize - cur_size != streamres ) + vClearEventFlag(); + cur_size += streamres; + if ( err ) + *error_ptr = err; + VERBOSE_KPRINTF(1, "sceCdStream0 BLK cur_size= %d req_size= %d err 0x%x\n", cur_size, rdsize, err); + if ( (unsigned int)cur_size == rdsize ) + break; + } + return cur_size; +} + +static int sceCdStream0(int rdsize_sectors, char *addrarg, int modearg, int *error_ptr) +{ + return sceCdStream0_inner(rdsize_sectors << 11, addrarg, modearg, error_ptr) / 0x800; +} + +static unsigned int iop_stream_handler( + unsigned int posszarg1, unsigned int posszarg2, void *buffer, int cmdid, const sceCdRMode *rmode, int *error_ptr) +{ + int retryflag; + int bankcur_tmp; + unsigned int i; + unsigned int written_chunk_size_tmp; + int bankcur_next_tmp1; + int chunk_size; + int bankcur_next_tmp2; + int state; + + retryflag = 0; + VERBOSE_KPRINTF(1, "CD Stream Call mode= %d\n", cmdid); + *error_ptr = 0; + if ( g_cdvdstm_stmstart_iop == 2 && cmdid != 9 && cmdid != 3 ) + { + return 0; + } + switch ( cmdid ) + { + case 8: + sceCdSC(1, &g_cdvdstm_last_error_for_iop); + if ( sceCdNop() ) + return 1; + sceCdSC(0, &g_cdvdstm_last_error_for_iop); + return 0; + case 7: + CpuSuspendIntr(&state); + vCancelAlarm((unsigned int (*)(void *))iop_stream_intr_cb, &g_cdvdstm_curclk_iop); + sceCdSC(0, &g_cdvdstm_last_error_for_iop); + CpuResumeIntr(state); + sceCdSync(0); + vCancelAlarm((unsigned int (*)(void *))stm_iop_read_timeout_alarm_cb, &g_cdvdstm_curclk_iop); + return 1; + case 6: + bankcur_tmp = g_cdvdstm_bankcur_iop; + if ( !g_cdvdstm_usedmap_iop[bankcur_tmp] ) + { + bankcur_tmp += 1; + if ( (unsigned int)bankcur_tmp >= (unsigned int)g_cdvdstm_bankmax ) + bankcur_tmp = 0; + if ( !g_cdvdstm_usedmap_iop[bankcur_tmp] ) + bankcur_tmp = g_cdvdstm_bankcur_iop; + } + for ( i = 0; (i < (unsigned int)g_cdvdstm_bankmax) && g_cdvdstm_usedmap_iop[bankcur_tmp] + && (g_cdvdstm_bankgp_iop != bankcur_tmp); + i += 1 ) + { + bankcur_tmp += 1; + if ( (unsigned int)bankcur_tmp >= (unsigned int)g_cdvdstm_bankmax ) + bankcur_tmp = 0; + } + return i * ((unsigned int)g_cdvdstm_numbytes >> 11); + case 5: + sceCdstm0Cb((void (*)(int))iop_stream_intr_cb_thunk); + g_cdvdstm_bufmax = posszarg1; + g_cdvdstm_sectorcount = posszarg1 / posszarg2; + g_cdvdstm_numbytes = g_cdvdstm_sectorcount << 11; + g_cdvdstm_buffer = buffer; + g_cdvdstm_bankmax = posszarg2; + KPRINTF( + "Stream Buffer 1Bank %dbyte %dbanks addr:%08x %dbyte used.\n", + g_cdvdstm_numbytes, + posszarg2, + buffer, + g_cdvdstm_numbytes * posszarg2); + return 1; + case 3: + CpuSuspendIntr(&state); + g_cdvdstm_stmstart_iop = 0; + vCancelAlarm((unsigned int (*)(void *))iop_stream_intr_cb, &g_cdvdstm_curclk_iop); + sceCdSC(0, &g_cdvdstm_last_error_for_iop); + CpuResumeIntr(state); + sceCdBreak(); + for ( i = 0; i < (unsigned int)g_cdvdstm_bankmax; i += 1 ) + g_cdvdstm_usedmap_iop[i] = 0; + g_cdvdstm_bankoffs_iop = 0; + g_cdvdstm_bankcur_iop = 0; + g_cdvdstm_bankgp_iop = 0; + sceCdSync(0); + g_cdvdstm_last_error_for_iop = 0; + sceCdSC(0xFFFFFFFE, &g_cdvdstm_last_error_for_iop); + vCancelAlarm((unsigned int (*)(void *))stm_iop_read_timeout_alarm_cb, &g_cdvdstm_curclk_iop); + return 1; + case 9: + if ( sceCdSC(0xFFFFFFFF, &g_cdvdstm_last_error_for_iop) ) + { + CpuSuspendIntr(&state); + g_cdvdstm_lsn_iop = posszarg1; + for ( i = 0; i < (unsigned int)g_cdvdstm_bankmax; i += 1 ) + g_cdvdstm_usedmap_iop[i] = 0; + g_cdvdstm_stmstart_iop = 2; + CpuResumeIntr(state); + return 1; + } + return 0; + case 1: + g_cdvdstm_mode_iop.datapattern = rmode->datapattern; + g_cdvdstm_mode_iop.trycount = rmode->trycount; + g_cdvdstm_mode_iop.spindlctrl = rmode->spindlctrl; + g_cdvdstm_retryerr_iop = 0; + break; + case 4: + CpuSuspendIntr(&state); + vCancelAlarm((unsigned int (*)(void *))iop_stream_intr_cb, &g_cdvdstm_curclk_iop); + sceCdSC(0, &g_cdvdstm_last_error_for_iop); + retryflag = 1; + CpuResumeIntr(state); + posszarg2 = 0; + cmdid = 1; + g_cdvdstm_lsn_iop = posszarg1; + g_cdvdstm_bankoffs_iop = 0; + g_cdvdstm_bankcur_iop = 0; + g_cdvdstm_bankgp_iop = 0; + sceCdSync(0); + vCancelAlarm((unsigned int (*)(void *))stm_iop_read_timeout_alarm_cb, &g_cdvdstm_curclk_iop); + break; + } + if ( cmdid == 1 ) + { + CpuSuspendIntr(&state); + retryflag = 1; + vCancelAlarm((unsigned int (*)(void *))iop_stream_intr_cb, &g_cdvdstm_curclk_iop); + sceCdSC(0, &g_cdvdstm_last_error_for_iop); + CpuResumeIntr(state); + for ( i = 0; i < (unsigned int)g_cdvdstm_bankmax; i += 1 ) + g_cdvdstm_usedmap_iop[i] = 0; + g_cdvdstm_lsn_iop = posszarg1; + sceCdSC(0xFFFFFFE9, (int *)&g_cdvdstm_lsn_iop); + g_cdvdstm_bankoffs_iop = 0; + g_cdvdstm_bankcur_iop = 0; + g_cdvdstm_bankgp_iop = 0; + sceCdSync(0); + vCancelAlarm((unsigned int (*)(void *))stm_iop_read_timeout_alarm_cb, &g_cdvdstm_curclk_iop); + g_cdvdstm_stmstart_iop = 1; + sceCdSC(1, &g_cdvdstm_last_error_for_iop); + if ( !sceCdNop() ) + { + sceCdSC(0, &g_cdvdstm_last_error_for_iop); + return 0; + } + } + CpuSuspendIntr(&state); + written_chunk_size_tmp = -1; + for ( i = 0; i < posszarg2; i += chunk_size ) + { + if ( !g_cdvdstm_usedmap_iop[g_cdvdstm_bankcur_iop] ) + { + VERBOSE_KPRINTF( + 1, + "CD read buffer over run %d %d %d %d %d gp %d pp %d\n", + (u8)g_cdvdstm_usedmap_iop[0], + (u8)g_cdvdstm_usedmap_iop[1], + (u8)g_cdvdstm_usedmap_iop[2], + (u8)g_cdvdstm_usedmap_iop[3], + (u8)g_cdvdstm_usedmap_iop[4], + g_cdvdstm_bankgp_iop, + g_cdvdstm_bankcur_iop); + bankcur_next_tmp1 = g_cdvdstm_bankcur_iop; + g_cdvdstm_bankcur_iop += 1; + if ( (unsigned int)g_cdvdstm_bankcur_iop >= (unsigned int)g_cdvdstm_bankmax ) + g_cdvdstm_bankcur_iop = 0; + written_chunk_size_tmp = i; + if ( !g_cdvdstm_usedmap_iop[g_cdvdstm_bankcur_iop] ) + { + g_cdvdstm_bankcur_iop = bankcur_next_tmp1; + } + break; + } + if ( (unsigned int)g_cdvdstm_bankoffs_iop >= (unsigned int)g_cdvdstm_numbytes ) + { + g_cdvdstm_bankoffs_iop = 0; + g_cdvdstm_usedmap_iop[g_cdvdstm_bankcur_iop] = 0; + bankcur_next_tmp2 = g_cdvdstm_bankcur_iop; + g_cdvdstm_bankcur_iop += 1; + if ( (unsigned int)g_cdvdstm_bankcur_iop >= (unsigned int)g_cdvdstm_bankmax ) + g_cdvdstm_bankcur_iop = 0; + if ( !g_cdvdstm_usedmap_iop[g_cdvdstm_bankcur_iop] || g_cdvdstm_bankgp_iop == g_cdvdstm_bankcur_iop ) + { + g_cdvdstm_bankcur_iop = bankcur_next_tmp2; + written_chunk_size_tmp = i; + VERBOSE_KPRINTF( + 1, + "CD read buffer over run %d %d %d %d %d gp %d pp %d\n", + (u8)g_cdvdstm_usedmap_iop[0], + (u8)g_cdvdstm_usedmap_iop[1], + (u8)g_cdvdstm_usedmap_iop[2], + (u8)g_cdvdstm_usedmap_iop[3], + (u8)g_cdvdstm_usedmap_iop[4], + g_cdvdstm_bankgp_iop, + g_cdvdstm_bankcur_iop); + break; + } + } + optimized_memcpy( + &((char *)buffer)[i], + &((char *)g_cdvdstm_buffer)[g_cdvdstm_bankcur_iop * g_cdvdstm_numbytes + g_cdvdstm_bankoffs_iop], + 0x800); + chunk_size = ((unsigned int)0x800 > posszarg2 - i) ? (posszarg2 - i) : 0x800; + g_cdvdstm_bankoffs_iop += chunk_size; + } + if ( written_chunk_size_tmp == 0xFFFFFFFF ) + written_chunk_size_tmp = posszarg2; + CpuResumeIntr(state); + if ( !retryflag ) + { + if ( sceCdSC(0xFFFFFFFF, &g_cdvdstm_last_error_for_iop) != 1 && !written_chunk_size_tmp && !g_cdvdstm_retryerr_iop ) + { + g_cdvdstm_retryerr_iop = 273; + } + *error_ptr = g_cdvdstm_retryerr_iop; + g_cdvdstm_retryerr_iop = 0; + return written_chunk_size_tmp; + } + return 1; +} + +static unsigned int iop_stream_intr_cb(void *userdata) +{ + int last_error; + int scres_unused; + + (void)userdata; + + VERBOSE_KPRINTF(1, "Intr Read call\n"); + iCancelAlarm((unsigned int (*)(void *))stm_iop_read_timeout_alarm_cb, &g_cdvdstm_curclk_iop); + iCancelAlarm((unsigned int (*)(void *))iop_stream_intr_cb, &g_cdvdstm_curclk_iop); + sceCdSC(0xFFFFFFFF, &last_error); + if ( !last_error ) + { + switch ( sceCdGetDiskType() ) + { + case SCECdPSCD: + case SCECdPSCDDA: + case SCECdPS2CD: + case SCECdPS2CDDA: + case SCECdPS2DVD: + break; + default: + last_error = SCECdErREADCF; + break; + } + } + g_cdvdstm_curclk_iop.hi = 0; + if ( g_cdvdstm_stmstart_iop ) + g_cdvdstm_retrycnt_iop = 0; + if ( g_cdvdstm_stmstart_iop || last_error || g_cdvdstm_retrycnt_iop ) + { + VERBOSE_KPRINTF( + 1, "Stm Rtry stmstart:%d err:%02x retry:%d\n", g_cdvdstm_stmstart_iop, last_error, g_cdvdstm_retrycnt_iop); + } + g_cdvdstm_curclk_iop.lo = (g_cdvdstm_stmstart_iop || last_error || g_cdvdstm_retrycnt_iop) ? + 0x20f58000 : + (0x9000 * sceCdSC(0xFFFFFFEF, &scres_unused)); + if ( last_error ) + { + VERBOSE_KPRINTF(1, "IOP Stream read Error code= 0x%02x retry= %d\n", last_error, g_cdvdstm_retrycnt_iop); + if ( last_error == SCECdErREAD || last_error == SCECdErABRT ) + { + VERBOSE_KPRINTF(1, "On err %08x\n", last_error); + if ( g_cdvdstm_retrycnt_iop ) + g_cdvdstm_retryerr_iop = last_error; + g_cdvdstm_retrycnt_iop = 3; + } + else + { + g_cdvdstm_retryerr_iop = last_error; + g_cdvdstm_retrycnt_iop = 1; + } + } + if ( g_cdvdstm_retrycnt_iop ) + { + unsigned int tgttmp; + + g_cdvdstm_retrycnt_iop -= 1; + tgttmp = ((unsigned int)g_cdvdstm_tgt >= (unsigned int)(0x10 * g_cdvdstm_retrycnt_iop)) ? + (g_cdvdstm_tgt - 0x10 * g_cdvdstm_retrycnt_iop) : + (g_cdvdstm_tgt + 0x10 * g_cdvdstm_retrycnt_iop); + VERBOSE_KPRINTF(1, "Stm Rtry Start Tgt=%d Cur= %d\n", g_cdvdstm_tgt, tgttmp); + if ( sceCdRE( + tgttmp, + g_cdvdstm_sectorcount, + (char *)g_cdvdstm_buffer + g_cdvdstm_bankgp_iop * g_cdvdstm_numbytes, + &g_cdvdstm_mode_iop) ) + { + iSetAlarm(&g_cdvdstm_curclk_iop, (unsigned int (*)(void *))stm_iop_read_timeout_alarm_cb, &g_cdvdstm_curclk_iop); + } + else + { + g_cdvdstm_curclk_iop.lo = 0x708000; + if ( + iSetAlarm(&g_cdvdstm_curclk_iop, (unsigned int (*)(void *))iop_stream_intr_cb, &g_cdvdstm_curclk_iop) + && !sceCdNop() ) + { + sceCdSC(0, &last_error); + } + g_cdvdstm_retrycnt_iop += 1; + } + return 0; + } + else + { + int gptmp; + + if ( !g_cdvdstm_stmstart_iop ) + { + g_cdvdstm_usedmap_iop[g_cdvdstm_bankgp_iop] = 1; + gptmp = g_cdvdstm_bankgp_iop; + g_cdvdstm_bankgp_iop += 1; + if ( (unsigned int)g_cdvdstm_bankgp_iop >= (unsigned int)g_cdvdstm_bankmax ) + g_cdvdstm_bankgp_iop = 0; + } + if ( + !g_cdvdstm_stmstart_iop + && (g_cdvdstm_usedmap_iop[g_cdvdstm_bankgp_iop] || g_cdvdstm_bankcur_iop == g_cdvdstm_bankgp_iop) ) + { + g_cdvdstm_bankgp_iop = gptmp; + g_cdvdstm_usedmap_iop[gptmp] = 0; + VERBOSE_KPRINTF( + 1, + "read Full %d %d %d %d %d gp %d pp %d spn %d\n", + (u8)g_cdvdstm_usedmap_iop[0], + (u8)g_cdvdstm_usedmap_iop[1], + (u8)g_cdvdstm_usedmap_iop[2], + (u8)g_cdvdstm_usedmap_iop[3], + (u8)g_cdvdstm_usedmap_iop[4], + g_cdvdstm_bankgp_iop, + g_cdvdstm_bankcur_iop, + g_cdvdstm_mode_iop.spindlctrl); + g_cdvdstm_curclk_iop.lo = 0x48000; + if ( + iSetAlarm(&g_cdvdstm_curclk_iop, (unsigned int (*)(void *))iop_stream_intr_cb, &g_cdvdstm_curclk_iop) + && !sceCdNop() ) + { + sceCdSC(0, &last_error); + } + } + else + { + if ( g_cdvdstm_stmstart_iop == 2 ) + { + unsigned int i; + + g_cdvdstm_bankoffs_iop = 0; + g_cdvdstm_bankcur_iop = 0; + g_cdvdstm_bankgp_iop = 0; + for ( i = 0; i < (unsigned int)g_cdvdstm_bankmax; i += 1 ) + g_cdvdstm_usedmap_iop[i] = 0; + } + g_cdvdstm_stmstart_iop = 0; + g_cdvdstm_tgt = g_cdvdstm_lsn_iop; + if ( sceCdRE( + g_cdvdstm_lsn_iop, + g_cdvdstm_sectorcount, + (char *)g_cdvdstm_buffer + g_cdvdstm_bankgp_iop * g_cdvdstm_numbytes, + &g_cdvdstm_mode_iop) ) + { + iSetAlarm( + &g_cdvdstm_curclk_iop, (unsigned int (*)(void *))stm_iop_read_timeout_alarm_cb, &g_cdvdstm_curclk_iop); + } + else + { + g_cdvdstm_curclk_iop.lo = 0x708000; + if ( + iSetAlarm(&g_cdvdstm_curclk_iop, (unsigned int (*)(void *))iop_stream_intr_cb, &g_cdvdstm_curclk_iop) + && !sceCdNop() ) + { + sceCdSC(0, &last_error); + } + g_cdvdstm_retrycnt_iop = 1; + } + g_cdvdstm_lsn_iop += g_cdvdstm_sectorcount; + } + } + return 0; +} + +static int cdrom_stm_init() +{ + iop_sema_t semaparam; + + semaparam.attr = SA_THPRI; + semaparam.initial = 1; + semaparam.max = 1; + semaparam.option = 0; + g_cdvdstm_semid = CreateSema(&semaparam); + return 0; +} + +static int cdrom_stm_deinit() +{ + SignalSema(g_cdvdstm_semid); + DeleteSema(g_cdvdstm_semid); + return 0; +} + +static int cdrom_stm_devctl( + iop_file_t *f, const char *name, int cmd, void *inbuf, unsigned int inbuf_len, void *outbuf, unsigned int outbuf_len) +{ + int retres; + cdrom_stm_devctl_t *instruct; + int *outres_ptr; + + (void)f; + (void)name; + (void)outbuf_len; + + instruct = inbuf; + outres_ptr = outbuf; + WaitSema(g_cdvdstm_semid); + retres = 0; + if ( g_cdvdstm_in_deldrv ) + { + SignalSema(g_cdvdstm_semid); + return -EIO; + } + switch ( cmd ) + { + case 0x4393: + if ( instruct->m_cmdid == 5 || instruct->m_cmdid == 3 || instruct->m_cmdid - 7 < 2 ) + { + vSetEventFlag(); + } + *outres_ptr = iop_stream_handler( + instruct->m_posszarg1, + instruct->m_posszarg2, + instruct->m_buffer, + instruct->m_cmdid, + &instruct->m_rmode, + (int *)&instruct->m_error); + break; + case 0x4394: + *outres_ptr = + sceCdStream0(instruct->m_posszarg2, (char *)instruct->m_buffer, instruct->m_cmdid, (int *)&instruct->m_error); + break; + case 0x4396: + ee_stream_handler_normal(instruct, inbuf_len, outres_ptr); + break; + case 0x4398: + ee_stream_handler_cdda(instruct, inbuf_len, outres_ptr); + break; + default: + PRINTF("Un-support devctl %08x\n", cmd); + retres = -EIO; + break; + } + SignalSema(g_cdvdstm_semid); + return retres; +} + +static int cdrom_stm_nulldev() +{ + PRINTF("nulldev0 call\n"); + return -EIO; +} + +static s64 cdrom_stm_nulldev64() +{ + PRINTF("nulldev0 call\n"); + return -EIO; +} + +int _start(int ac, char *av[], void *startaddr, ModuleInfo_t *mi) +{ + int last_error; + int scres_unused; + int state; + + (void)av; + (void)startaddr; + + if ( ac < 0 ) + { + int relres; + + if ( !sceCdSC(0xFFFFFFFF, &last_error) ) + { + return MODULE_REMOVABLE_END; + } + g_cdvdstm_in_deldrv = 1; + DelDrv(g_cdrom_stm_dev.name); + CpuSuspendIntr(&state); + relres = ReleaseLibraryEntries(&_exp_cdvdstm); + CpuResumeIntr(state); + g_cdvdstm_in_deldrv = 0; + if ( relres && relres != KE_LIBRARY_NOTFOUND ) + { + g_cdvdstm_in_deldrv = 0; + return MODULE_REMOVABLE_END; + } + return MODULE_NO_RESIDENT_END; + } + if ( RegisterLibraryEntries(&_exp_cdvdstm) ) + return MODULE_NO_RESIDENT_END; + DelDrv(g_cdrom_stm_dev.name); + if ( AddDrv(&g_cdrom_stm_dev) ) + { + cdrom_stm_deinit(); + return MODULE_NO_RESIDENT_END; + } + g_cdvdman_intr_efid = sceCdSC(0xFFFFFFF5, &scres_unused); +#if 0 + return MODULE_REMOVABLE_END; +#else + if ( mi && ((mi->newflags & 2) != 0) ) + mi->newflags |= 0x10; + return MODULE_RESIDENT_END; +#endif +} + +static int stm_ee_read_timeout_alarm_cb(const iop_sys_clock_t *sys_clock) +{ + int read_timeout; + + read_timeout = sys_clock->lo / 0x9000; + KPRINTF("Stm EE Read Time Out %d(msec)\n", read_timeout); + sceCdSC(0xFFFFFFEE, &read_timeout); + return !sceCdBreak(); +} + +static void ee_stream_handler_normal(cdrom_stm_devctl_t *instruct, int inbuf_len, int *outres_ptr) +{ + int retryflag; + u32 cmdid; + u32 posszarg2_bytes; + int bankcur_tmp; + unsigned int chunks_sectors; + int bankcur_next_tmp1; + int posszarg2_bytes_clamped; + int dmat1; + int bankcur_next_tmp2; + int posszarg2_bytes_overrun; + int outres_tmp2; + int state; + unsigned int i; + + (void)inbuf_len; + + retryflag = 0; + cmdid = instruct->m_cmdid; + if ( g_cdvdstm_stmstart_ee == 2 && (cmdid != 9 && cmdid != 3) ) + { + *outres_ptr = 0; + return; + } + switch ( cmdid ) + { + case 8: + sceCdSC(2, &g_cdvdstm_last_error_for_ee); + if ( !sceCdNop() ) + { + sceCdSC(0, &g_cdvdstm_last_error_for_ee); + *outres_ptr = 0; + return; + } + *outres_ptr = 1; + return; + case 7: + CpuSuspendIntr(&state); + CancelAlarm((unsigned int (*)(void *))ee_stream_intr_cb_normal, &g_cdvdstm_curclk_ee); + sceCdSC(0, &g_cdvdstm_last_error_for_ee); + CpuResumeIntr(state); + sceCdSync(0); + *outres_ptr = 1; + CancelAlarm((unsigned int (*)(void *))stm_ee_read_timeout_alarm_cb, &g_cdvdstm_curclk_ee); + return; + case 6: + bankcur_tmp = g_cdvdstm_bankcur_ee; + if ( !g_cdvdstm_usedmap_ee[bankcur_tmp] ) + { + bankcur_tmp += 1; + if ( (unsigned int)bankcur_tmp >= (unsigned int)g_cdvdstm_bankcnt2 ) + bankcur_tmp = 0; + if ( !g_cdvdstm_usedmap_ee[bankcur_tmp] ) + bankcur_tmp = g_cdvdstm_bankcur_ee; + } + for ( i = 0; (i < (unsigned int)g_cdvdstm_bankcnt2) && g_cdvdstm_usedmap_ee[bankcur_tmp] + && (g_cdvdstm_bankgp_ee != bankcur_tmp); + i += 1 ) + { + bankcur_tmp += 1; + if ( (unsigned int)bankcur_tmp >= (unsigned int)g_cdvdstm_bankcnt2 ) + bankcur_tmp = 0; + } + *outres_ptr = i * ((unsigned int)g_cdvdstm_chunksz2 >> 11); + return; + case 5: + sceCdstm1Cb((void (*)(int))ee_stream_intr_cb_normal_thunk); + if ( !instruct->m_posszarg2 ) + __builtin_trap(); + chunks_sectors = instruct->m_posszarg1 / instruct->m_posszarg2; + g_cdvdstm_bufsz2 = instruct->m_posszarg1; + g_cdvdstm_sectorcount2 = chunks_sectors; + g_cdvdstm_chunksz2 = chunks_sectors << 11; + g_cdvdstm_buffer2 = (char *)instruct->m_buffer; + g_cdvdstm_bankcnt2 = instruct->m_posszarg2; + PRINTF( + "Stream Buffer 1Bank %dbyte %dbanks %dbyte used\n", + (int)(chunks_sectors << 11), + (int)(instruct->m_posszarg2), + (int)((chunks_sectors << 11) * (instruct->m_posszarg2))); + *outres_ptr = 1; + return; + case 3: + CpuSuspendIntr(&state); + g_cdvdstm_stmstart_ee = 0; + CancelAlarm((unsigned int (*)(void *))ee_stream_intr_cb_normal, &g_cdvdstm_curclk_ee); + sceCdSC(0, &g_cdvdstm_last_error_for_ee); + CpuResumeIntr(state); + sceCdBreak(); + for ( i = 0; i < (unsigned int)g_cdvdstm_bankcnt2; i += 1 ) + { + g_cdvdstm_usedmap_ee[i] = 0; + } + g_cdvdstm_bankoffs_ee = 0; + g_cdvdstm_bankcur_ee = 0; + g_cdvdstm_bankgp_ee = 0; + *outres_ptr = 1; + sceCdSync(0); + g_cdvdstm_last_error_for_ee = 0; + sceCdSC(0xFFFFFFFE, &g_cdvdstm_last_error_for_ee); + CancelAlarm((unsigned int (*)(void *))stm_ee_read_timeout_alarm_cb, &g_cdvdstm_curclk_ee); + return; + case 1: + g_cdvdstm_mode_ee.datapattern = instruct->m_rmode.datapattern; + g_cdvdstm_mode_ee.trycount = instruct->m_rmode.trycount; + g_cdvdstm_mode_ee.spindlctrl = instruct->m_rmode.spindlctrl; + g_cdvdstm_retryerr_ee = 0; + break; + } + posszarg2_bytes = instruct->m_posszarg2 << 11; + if ( cmdid == 9 ) + { + if ( sceCdSC(0xFFFFFFFF, &g_cdvdstm_last_error_for_ee) ) + { + CpuSuspendIntr(&state); + g_cdvdstm_lsn_ee = instruct->m_posszarg1; + for ( i = 0; i < (unsigned int)g_cdvdstm_bankcnt2; i += 1 ) + { + g_cdvdstm_usedmap_ee[i] = 0; + } + g_cdvdstm_stmstart_ee = 2; + CpuResumeIntr(state); + *outres_ptr = 1; + return; + } + *outres_ptr = 0; + return; + } + if ( cmdid == 4 ) + { + retryflag = 1; + CpuSuspendIntr(&state); + CancelAlarm((unsigned int (*)(void *))ee_stream_intr_cb_normal, &g_cdvdstm_curclk_ee); + sceCdSC(0, &g_cdvdstm_last_error_for_ee); + posszarg2_bytes = 0; + cmdid = 1; + CpuResumeIntr(state); + g_cdvdstm_lsn_ee = instruct->m_posszarg1; + g_cdvdstm_bankoffs_ee = 0; + g_cdvdstm_bankcur_ee = 0; + g_cdvdstm_bankgp_ee = 0; + sceCdSync(0); + CancelAlarm((unsigned int (*)(void *))stm_ee_read_timeout_alarm_cb, &g_cdvdstm_curclk_ee); + } + if ( cmdid == 1 ) + { + CpuSuspendIntr(&state); + CancelAlarm((unsigned int (*)(void *))ee_stream_intr_cb_normal, &g_cdvdstm_curclk_ee); + sceCdSC(0, &g_cdvdstm_last_error_for_ee); + CpuResumeIntr(state); + retryflag = 1; + for ( i = 0; i < (unsigned int)g_cdvdstm_bankcnt2; i += 1 ) + { + g_cdvdstm_usedmap_ee[i] = 0; + } + g_cdvdstm_lsn_ee = instruct->m_posszarg1; + sceCdSC(0xFFFFFFE9, (int *)&g_cdvdstm_lsn_ee); + g_cdvdstm_bankoffs_ee = 0; + g_cdvdstm_bankcur_ee = 0; + sceCdSync(0); + CancelAlarm((unsigned int (*)(void *))stm_ee_read_timeout_alarm_cb, &g_cdvdstm_curclk_ee); + g_cdvdstm_stmstart_ee = 1; + sceCdSC(2, &g_cdvdstm_last_error_for_ee); + if ( !sceCdNop() ) + { + sceCdSC(0, &g_cdvdstm_last_error_for_ee); + *outres_ptr = 0; + return; + } + } + posszarg2_bytes_overrun = -1; + for ( i = 0; i < posszarg2_bytes; i += posszarg2_bytes_clamped ) + { + unsigned int posszarg2_bytes_remain; + + posszarg2_bytes_remain = posszarg2_bytes - i; + if ( !g_cdvdstm_usedmap_ee[g_cdvdstm_bankcur_ee] ) + { + VERBOSE_KPRINTF( + 1, + "CD read buffer over run %d %d %d %d %d gp %d pp %d\n", + (u8)g_cdvdstm_usedmap_ee[0], + (u8)g_cdvdstm_usedmap_ee[1], + (u8)g_cdvdstm_usedmap_ee[2], + (u8)g_cdvdstm_usedmap_ee[3], + (u8)g_cdvdstm_usedmap_ee[4], + g_cdvdstm_bankgp_ee, + g_cdvdstm_bankcur_ee); + CpuSuspendIntr(&state); + bankcur_next_tmp1 = g_cdvdstm_bankcur_ee; + g_cdvdstm_bankcur_ee += 1; + if ( (unsigned int)g_cdvdstm_bankcur_ee >= (unsigned int)g_cdvdstm_bankcnt2 ) + g_cdvdstm_bankcur_ee = 0; + if ( !g_cdvdstm_usedmap_ee[g_cdvdstm_bankcur_ee] ) + g_cdvdstm_bankcur_ee = bankcur_next_tmp1; + posszarg2_bytes_overrun = posszarg2_bytes - posszarg2_bytes_remain; + CpuResumeIntr(state); + break; + } + posszarg2_bytes_clamped = ((unsigned int)(g_cdvdstm_chunksz2 - g_cdvdstm_bankoffs_ee) < posszarg2_bytes_remain) ? + (unsigned int)(g_cdvdstm_chunksz2 - g_cdvdstm_bankoffs_ee) : + posszarg2_bytes_remain; + g_cdvdstm_dmat.dest = ((char *)instruct->m_buffer) + i; + g_cdvdstm_dmat.size = posszarg2_bytes_clamped; + g_cdvdstm_dmat.attr = 0; + g_cdvdstm_dmat.src = (char *)g_cdvdstm_buffer2 + g_cdvdstm_bankcur_ee * g_cdvdstm_chunksz2 + g_cdvdstm_bankoffs_ee; + if ( posszarg2_bytes_clamped ) + { + while ( 1 ) + { + CpuSuspendIntr(&state); + dmat1 = sceSifSetDma(&g_cdvdstm_dmat, 1); + CpuResumeIntr(state); + if ( dmat1 ) + break; + DelayThread(500); + } + g_cdvdstm_bankoffs_ee += posszarg2_bytes_clamped; + while ( sceSifDmaStat(dmat1) >= 0 ) + ; + } + if ( (unsigned int)g_cdvdstm_bankoffs_ee >= (unsigned int)g_cdvdstm_chunksz2 ) + { + CpuSuspendIntr(&state); + g_cdvdstm_bankoffs_ee = 0; + g_cdvdstm_usedmap_ee[g_cdvdstm_bankcur_ee] = 0; + bankcur_next_tmp2 = g_cdvdstm_bankcur_ee; + g_cdvdstm_bankcur_ee += 1; + if ( (unsigned int)g_cdvdstm_bankcur_ee >= (unsigned int)g_cdvdstm_bankcnt2 ) + g_cdvdstm_bankcur_ee = 0; + if ( g_cdvdstm_usedmap_ee[g_cdvdstm_bankcur_ee] && g_cdvdstm_bankgp_ee != g_cdvdstm_bankcur_ee ) + { + CpuResumeIntr(state); + } + else + { + g_cdvdstm_bankcur_ee = bankcur_next_tmp2; + CpuResumeIntr(state); + VERBOSE_KPRINTF( + 1, + "CD read buffer over run %d %d %d %d %d gp %d pp %d\n", + (u8)g_cdvdstm_usedmap_ee[0], + (u8)g_cdvdstm_usedmap_ee[1], + (u8)g_cdvdstm_usedmap_ee[2], + (u8)g_cdvdstm_usedmap_ee[3], + (u8)g_cdvdstm_usedmap_ee[4], + g_cdvdstm_bankgp_ee, + g_cdvdstm_bankcur_ee); + posszarg2_bytes_overrun = posszarg2_bytes - (posszarg2_bytes_remain - posszarg2_bytes_clamped); + break; + } + } + } + if ( posszarg2_bytes_overrun == -1 ) + posszarg2_bytes_overrun = posszarg2_bytes; + outres_tmp2 = (retryflag) ? 1 : (posszarg2_bytes_overrun / 0x800); + if ( !retryflag ) + { + if ( sceCdSC(0xFFFFFFFF, &g_cdvdstm_last_error_for_ee) != 2 && !outres_tmp2 && !g_cdvdstm_retryerr_ee ) + g_cdvdstm_retryerr_ee = 273; + if ( g_cdvdstm_retryerr_ee ) + { + outres_tmp2 = (u16)outres_tmp2 | (g_cdvdstm_retryerr_ee << 16); + g_cdvdstm_retryerr_ee = 0; + } + } + *outres_ptr = outres_tmp2; + return; +} + +static unsigned int ee_stream_intr_cb_normal(void *userdata) +{ + int scres_unused; + + (void)userdata; + + VERBOSE_KPRINTF(1, "Intr EE Stm Read call\n"); + iCancelAlarm((unsigned int (*)(void *))stm_ee_read_timeout_alarm_cb, &g_cdvdstm_curclk_ee); + iCancelAlarm((unsigned int (*)(void *))ee_stream_intr_cb_normal, &g_cdvdstm_curclk_ee); + sceCdSC(0xFFFFFFFF, &g_cdvdstm_last_error_for_ee); + if ( !g_cdvdstm_last_error_for_ee ) + { + switch ( sceCdGetDiskType() ) + { + case SCECdPSCD: + case SCECdPSCDDA: + case SCECdPS2CD: + case SCECdPS2CDDA: + case SCECdPS2DVD: + break; + default: + g_cdvdstm_last_error_for_ee = SCECdErREADCF; + break; + } + } + g_cdvdstm_curclk_ee.hi = 0; + if ( g_cdvdstm_stmstart_ee ) + g_cdvdstm_retrycnt_ee_normal = 0; + g_cdvdstm_curclk_ee.lo = (g_cdvdstm_stmstart_ee || g_cdvdstm_last_error_for_ee || g_cdvdstm_retrycnt_ee_normal) ? + 0x20f58000 : + (0x9000 * sceCdSC(0xFFFFFFEF, &scres_unused)); + if ( g_cdvdstm_last_error_for_ee ) + { + VERBOSE_KPRINTF( + 1, + "EE Stream read LBN= %d Error code= 0x%02x retry= %d\n", + g_cdvdstm_readlbn_ee_normal, + g_cdvdstm_last_error_for_ee, + g_cdvdstm_retrycnt_ee_normal); + if ( g_cdvdstm_last_error_for_ee == SCECdErREAD || g_cdvdstm_last_error_for_ee == SCECdErABRT ) + { + if ( g_cdvdstm_retrycnt_ee_normal ) + { + VERBOSE_KPRINTF(1, "On Retry retry %d err %08x\n", g_cdvdstm_retrycnt_ee_normal, g_cdvdstm_last_error_for_ee); + } + g_cdvdstm_retrycnt_ee_normal = 3; + } + else + { + g_cdvdstm_retrycnt_ee_normal = 1; + } + g_cdvdstm_retryerr_ee = g_cdvdstm_last_error_for_ee; + } + if ( g_cdvdstm_retrycnt_ee_normal ) + { + g_cdvdstm_retrycnt_ee_normal -= 1; + if ( sceCdRE( + ((unsigned int)g_cdvdstm_readlbn_ee_normal >= (unsigned int)(0x10 * g_cdvdstm_retrycnt_ee_normal)) ? + (g_cdvdstm_readlbn_ee_normal - 0x10 * g_cdvdstm_retrycnt_ee_normal) : + (g_cdvdstm_readlbn_ee_normal + 0x10 * g_cdvdstm_retrycnt_ee_normal), + g_cdvdstm_sectorcount2, + (char *)g_cdvdstm_buffer2 + g_cdvdstm_bankgp_ee * g_cdvdstm_chunksz2, + &g_cdvdstm_mode_ee) ) + { + iSetAlarm(&g_cdvdstm_curclk_ee, (unsigned int (*)(void *))stm_ee_read_timeout_alarm_cb, &g_cdvdstm_curclk_ee); + } + else + { + VERBOSE_KPRINTF(1, "Stm Read Call fail\n"); + g_cdvdstm_curclk_ee.lo = 0x708000; + if ( + iSetAlarm(&g_cdvdstm_curclk_ee, (unsigned int (*)(void *))ee_stream_intr_cb_normal, &g_cdvdstm_curclk_ee) + && !sceCdNop() ) + { + sceCdSC(0, &g_cdvdstm_last_error_for_ee); + } + g_cdvdstm_retrycnt_ee_normal += 1; + } + } + else + { + int gptmp; + + if ( !g_cdvdstm_stmstart_ee ) + { + g_cdvdstm_usedmap_ee[g_cdvdstm_bankgp_ee] = 1; + gptmp = g_cdvdstm_bankgp_ee; + g_cdvdstm_bankgp_ee += 1; + if ( (unsigned int)g_cdvdstm_bankgp_ee >= (unsigned int)g_cdvdstm_bankcnt2 ) + g_cdvdstm_bankgp_ee = 0; + } + if ( + !g_cdvdstm_stmstart_ee + && (g_cdvdstm_usedmap_ee[g_cdvdstm_bankgp_ee] || g_cdvdstm_bankcur_ee == g_cdvdstm_bankgp_ee) ) + { + g_cdvdstm_bankgp_ee = gptmp; + g_cdvdstm_usedmap_ee[gptmp] = 0; + VERBOSE_KPRINTF( + 1, + "read Full %d %d %d %d %d gp %d pp %d spn %d\n", + (u8)g_cdvdstm_usedmap_ee[0], + (u8)g_cdvdstm_usedmap_ee[1], + (u8)g_cdvdstm_usedmap_ee[2], + (u8)g_cdvdstm_usedmap_ee[3], + (u8)g_cdvdstm_usedmap_ee[4], + g_cdvdstm_bankgp_ee, + g_cdvdstm_bankcur_ee, + g_cdvdstm_mode_ee.spindlctrl); + g_cdvdstm_curclk_ee.lo = 0x48000; + if ( + iSetAlarm(&g_cdvdstm_curclk_ee, (unsigned int (*)(void *))ee_stream_intr_cb_normal, &g_cdvdstm_curclk_ee) + && !sceCdNop() ) + { + sceCdSC(0, &g_cdvdstm_last_error_for_ee); + } + } + else + { + if ( g_cdvdstm_stmstart_ee == 2 ) + { + unsigned int i; + + g_cdvdstm_bankoffs_ee = 0; + g_cdvdstm_bankcur_ee = 0; + g_cdvdstm_bankgp_ee = 0; + for ( i = 0; i < (unsigned int)g_cdvdstm_bankcnt2; i += 1 ) + g_cdvdstm_usedmap_ee[i] = 0; + } + g_cdvdstm_stmstart_ee = 0; + g_cdvdstm_readlbn_ee_normal = g_cdvdstm_lsn_ee; + if ( sceCdRE( + g_cdvdstm_lsn_ee, + g_cdvdstm_sectorcount2, + (char *)g_cdvdstm_buffer2 + g_cdvdstm_bankgp_ee * g_cdvdstm_chunksz2, + &g_cdvdstm_mode_ee) ) + { + iSetAlarm(&g_cdvdstm_curclk_ee, (unsigned int (*)(void *))stm_ee_read_timeout_alarm_cb, &g_cdvdstm_curclk_ee); + } + else + { + VERBOSE_KPRINTF(1, "Stm Read Call1 fail\n"); + g_cdvdstm_curclk_ee.lo = 0x708000; + if ( + iSetAlarm(&g_cdvdstm_curclk_ee, (unsigned int (*)(void *))ee_stream_intr_cb_normal, &g_cdvdstm_curclk_ee) + && !sceCdNop() ) + { + sceCdSC(0, &g_cdvdstm_last_error_for_ee); + } + g_cdvdstm_retrycnt_ee_normal = 1; + } + g_cdvdstm_lsn_ee += g_cdvdstm_sectorcount2; + } + } + return 0; +} + +static void ee_stream_handler_cdda(cdrom_stm_devctl_t *instruct, int inbuf_len, int *outres_ptr) +{ + u32 cmdid; + u32 posszarg2_bytes; + int retryflag; + int bankcur_tmp; + u32 chunks_sectors; + int bankcur_next_tmp1; + int posszarg2_bytes_clamped; + int dmat2; + int bankcur_next_tmp2; + int posszarg2_overrun_chunks2; + unsigned int posszarg2_bytes_overrun; + int state; + unsigned int i; + + (void)inbuf_len; + + cmdid = instruct->m_cmdid; + posszarg2_bytes = instruct->m_posszarg2 * g_cdvdstm_usedchunksize2; + retryflag = 0; + if ( g_cdvdstm_stmstart_ee == 2 && (cmdid != 9 && cmdid != 3) ) + { + *outres_ptr = 0; + return; + } + switch ( cmdid ) + { + case 8: + sceCdSC(2, &g_cdvdstm_last_error_for_ee); + if ( sceCdNop() ) + { + *outres_ptr = 1; + return; + } + sceCdSC(0, &g_cdvdstm_last_error_for_ee); + *outres_ptr = 0; + return; + case 7: + CpuSuspendIntr(&state); + CancelAlarm((unsigned int (*)(void *))ee_stream_intr_cb_cdda, &g_cdvdstm_curclk_ee); + sceCdSC(0, &g_cdvdstm_last_error_for_ee); + CpuResumeIntr(state); + sceCdSync(0); + *outres_ptr = 1; + CancelAlarm((unsigned int (*)(void *))stm_ee_read_timeout_alarm_cb, &g_cdvdstm_curclk_ee); + return; + case 6: + bankcur_tmp = g_cdvdstm_bankcur_ee; + if ( !g_cdvdstm_usedmap_ee[bankcur_tmp] ) + { + bankcur_tmp += 1; + if ( (unsigned int)bankcur_tmp >= (unsigned int)g_cdvdstm_bankcnt2 ) + bankcur_tmp = 0; + if ( !g_cdvdstm_usedmap_ee[bankcur_tmp] ) + bankcur_tmp = g_cdvdstm_bankcur_ee; + } + for ( i = 0; (i < (unsigned int)g_cdvdstm_bankcnt2) && g_cdvdstm_usedmap_ee[bankcur_tmp] + && (g_cdvdstm_bankgp_ee != bankcur_tmp); + i += 1 ) + { + bankcur_tmp += 1; + if ( (unsigned int)(bankcur_tmp) >= (unsigned int)g_cdvdstm_bankcnt2 ) + bankcur_tmp = 0; + } + if ( !g_cdvdstm_usedchunksize2 ) + __builtin_trap(); + *outres_ptr = i * (g_cdvdstm_chunksz2 / (unsigned int)g_cdvdstm_usedchunksize2); + return; + case 5: + sceCdstm1Cb((void (*)(int))ee_stream_intr_cb_cdda_thunk); + switch ( instruct->m_rmode.datapattern ) + { + case SCECdSecS2368: + g_cdvdstm_usedchunksize2 = 2368; + break; + case SCECdSecS2448: + g_cdvdstm_usedchunksize2 = 2448; + break; + case SCECdSecS2352: + default: + g_cdvdstm_usedchunksize2 = 0x930; + break; + } + if ( !instruct->m_posszarg2 ) + __builtin_trap(); + chunks_sectors = instruct->m_posszarg1 / instruct->m_posszarg2; + g_cdvdstm_bufsz2 = instruct->m_posszarg1; + g_cdvdstm_sectorcount2 = chunks_sectors; + g_cdvdstm_chunksz2 = chunks_sectors * g_cdvdstm_usedchunksize2; + g_cdvdstm_buffer2 = (char *)instruct->m_buffer; + g_cdvdstm_bankcnt2 = instruct->m_posszarg2; + PRINTF( + "DA Stream Buffer 1Bank %dbyte %dbanks %dbyte used\n", + (int)(chunks_sectors * g_cdvdstm_usedchunksize2), + (int)instruct->m_posszarg2, + (int)(chunks_sectors * g_cdvdstm_usedchunksize2 * instruct->m_posszarg2)); + *outres_ptr = 1; + return; + case 3: + CpuSuspendIntr(&state); + g_cdvdstm_stmstart_ee = 0; + CancelAlarm((unsigned int (*)(void *))ee_stream_intr_cb_cdda, &g_cdvdstm_curclk_ee); + sceCdSC(0, &g_cdvdstm_last_error_for_ee); + CpuResumeIntr(state); + sceCdBreak(); + for ( i = 0; i < (unsigned int)g_cdvdstm_bankcnt2; i += 1 ) + { + g_cdvdstm_usedmap_ee[i] = 0; + } + g_cdvdstm_bankoffs_ee = 0; + g_cdvdstm_bankcur_ee = 0; + g_cdvdstm_bankgp_ee = 0; + *outres_ptr = 1; + sceCdSync(0); + g_cdvdstm_last_error_for_ee = 0; + sceCdSC(0xFFFFFFFE, &g_cdvdstm_last_error_for_ee); + CancelAlarm((unsigned int (*)(void *))stm_ee_read_timeout_alarm_cb, &g_cdvdstm_curclk_ee); + return; + case 1: + g_cdvdstm_mode_ee.datapattern = instruct->m_rmode.datapattern; + g_cdvdstm_mode_ee.trycount = instruct->m_rmode.trycount; + g_cdvdstm_mode_ee.spindlctrl = instruct->m_rmode.spindlctrl; + g_cdvdstm_retryerr_ee = 0; + break; + } + if ( cmdid == 9 ) + { + if ( sceCdSC(0xFFFFFFFF, &g_cdvdstm_last_error_for_ee) ) + { + CpuSuspendIntr(&state); + g_cdvdstm_lsn_ee = instruct->m_posszarg1; + for ( i = 0; i < (unsigned int)g_cdvdstm_bankcnt2; i += 1 ) + { + g_cdvdstm_usedmap_ee[i] = 0; + } + g_cdvdstm_stmstart_ee = 2; + CpuResumeIntr(state); + *outres_ptr = 1; + return; + } + *outres_ptr = 0; + return; + } + if ( cmdid == 4 ) + { + retryflag = 1; + CpuSuspendIntr(&state); + CancelAlarm((unsigned int (*)(void *))ee_stream_intr_cb_cdda, &g_cdvdstm_curclk_ee); + sceCdSC(0, &g_cdvdstm_last_error_for_ee); + posszarg2_bytes = 0; + cmdid = 1; + CpuResumeIntr(state); + g_cdvdstm_lsn_ee = instruct->m_posszarg1; + g_cdvdstm_bankoffs_ee = 0; + g_cdvdstm_bankcur_ee = 0; + g_cdvdstm_bankgp_ee = 0; + sceCdSync(0); + CancelAlarm((unsigned int (*)(void *))stm_ee_read_timeout_alarm_cb, &g_cdvdstm_curclk_ee); + } + if ( cmdid == 1 ) + { + signed int posszarg2_chunks; + + CpuSuspendIntr(&state); + CancelAlarm((unsigned int (*)(void *))ee_stream_intr_cb_cdda, &g_cdvdstm_curclk_ee); + sceCdSC(0, &g_cdvdstm_last_error_for_ee); + CpuResumeIntr(state); + retryflag = 1; + for ( i = 0; i < (unsigned int)g_cdvdstm_bankcnt2; i += 1 ) + { + g_cdvdstm_usedmap_ee[i] = 0; + } + g_cdvdstm_lsn_ee = instruct->m_posszarg1; + g_cdvdstm_bankoffs_ee = 0; + g_cdvdstm_bankcur_ee = 0; + sceCdSync(0); + CancelAlarm((unsigned int (*)(void *))stm_ee_read_timeout_alarm_cb, &g_cdvdstm_curclk_ee); + if ( !g_cdvdstm_chunksz2 ) + __builtin_trap(); + posszarg2_chunks = (posszarg2_bytes / g_cdvdstm_chunksz2) + (!!(posszarg2_bytes % g_cdvdstm_chunksz2)); + for ( g_cdvdstm_bankgp_ee = 0; g_cdvdstm_bankgp_ee < posszarg2_chunks; g_cdvdstm_bankgp_ee += 1 ) + { + int outres_tmp2; + + outres_tmp2 = sceCdReadCDDA(g_cdvdstm_lsn_ee, g_cdvdstm_sectorcount2, g_cdvdstm_buffer2, &g_cdvdstm_mode_ee); + sceCdSync(3); + sceCdSC(0xFFFFFFFF, &g_cdvdstm_last_error_for_ee); + if ( g_cdvdstm_last_error_for_ee || !outres_tmp2 ) + { + sceCdSC(0, &g_cdvdstm_last_error_for_ee); + *outres_ptr = 0; + return; + } + g_cdvdstm_lsn_ee += g_cdvdstm_sectorcount2; + g_cdvdstm_usedmap_ee[g_cdvdstm_bankgp_ee] = 1; + } + g_cdvdstm_stmstart_ee = 1; + sceCdSC(2, &g_cdvdstm_last_error_for_ee); + if ( !sceCdNop() ) + { + sceCdSC(0, &g_cdvdstm_last_error_for_ee); + *outres_ptr = 0; + return; + } + } + posszarg2_bytes_overrun = -1; + for ( i = 0; i < posszarg2_bytes; i += posszarg2_bytes_clamped ) + { + unsigned int posszarg2_bytes_remain; + + posszarg2_bytes_remain = posszarg2_bytes - i; + if ( !g_cdvdstm_usedmap_ee[g_cdvdstm_bankcur_ee] ) + { + VERBOSE_KPRINTF( + 1, + "CD read buffer over run %d %d %d %d %d gp %d pp %d\n", + (u8)g_cdvdstm_usedmap_ee[0], + (u8)g_cdvdstm_usedmap_ee[1], + (u8)g_cdvdstm_usedmap_ee[2], + (u8)g_cdvdstm_usedmap_ee[3], + (u8)g_cdvdstm_usedmap_ee[4], + g_cdvdstm_bankgp_ee, + g_cdvdstm_bankcur_ee); + CpuSuspendIntr(&state); + bankcur_next_tmp1 = g_cdvdstm_bankcur_ee; + g_cdvdstm_bankcur_ee += 1; + if ( (unsigned int)g_cdvdstm_bankcur_ee >= (unsigned int)g_cdvdstm_bankcnt2 ) + g_cdvdstm_bankcur_ee = 0; + if ( !g_cdvdstm_usedmap_ee[g_cdvdstm_bankcur_ee] ) + g_cdvdstm_bankcur_ee = bankcur_next_tmp1; + posszarg2_bytes_overrun = posszarg2_bytes - posszarg2_bytes_remain; + CpuResumeIntr(state); + break; + } + posszarg2_bytes_clamped = ((unsigned int)(g_cdvdstm_chunksz2 - g_cdvdstm_bankoffs_ee) < posszarg2_bytes_remain) ? + (unsigned int)(g_cdvdstm_chunksz2 - g_cdvdstm_bankoffs_ee) : + posszarg2_bytes_remain; + g_cdvdstm_dmat2.dest = ((char *)instruct->m_buffer) + i; + g_cdvdstm_dmat2.size = posszarg2_bytes_clamped; + g_cdvdstm_dmat2.attr = 0; + g_cdvdstm_dmat2.src = (char *)g_cdvdstm_buffer2 + g_cdvdstm_bankcur_ee * g_cdvdstm_chunksz2 + g_cdvdstm_bankoffs_ee; + if ( posszarg2_bytes_clamped ) + { + while ( 1 ) + { + CpuSuspendIntr(&state); + dmat2 = sceSifSetDma(&g_cdvdstm_dmat2, 1); + CpuResumeIntr(state); + if ( dmat2 ) + break; + DelayThread(500); + } + g_cdvdstm_bankoffs_ee += posszarg2_bytes_clamped; + while ( sceSifDmaStat(dmat2) >= 0 ) + ; + } + if ( (unsigned int)g_cdvdstm_bankoffs_ee >= (unsigned int)g_cdvdstm_chunksz2 ) + { + CpuSuspendIntr(&state); + g_cdvdstm_bankoffs_ee = 0; + g_cdvdstm_usedmap_ee[g_cdvdstm_bankcur_ee] = 0; + bankcur_next_tmp2 = g_cdvdstm_bankcur_ee; + g_cdvdstm_bankcur_ee += 1; + if ( (unsigned int)g_cdvdstm_bankcur_ee >= (unsigned int)g_cdvdstm_bankcnt2 ) + g_cdvdstm_bankcur_ee = 0; + if ( g_cdvdstm_usedmap_ee[g_cdvdstm_bankcur_ee] && g_cdvdstm_bankgp_ee != g_cdvdstm_bankcur_ee ) + { + CpuResumeIntr(state); + } + else + { + g_cdvdstm_bankcur_ee = bankcur_next_tmp2; + CpuResumeIntr(state); + VERBOSE_KPRINTF( + 1, + "CD read buffer over run %d %d %d %d %d gp %d pp %d\n", + (u8)g_cdvdstm_usedmap_ee[0], + (u8)g_cdvdstm_usedmap_ee[1], + (u8)g_cdvdstm_usedmap_ee[2], + (u8)g_cdvdstm_usedmap_ee[3], + (u8)g_cdvdstm_usedmap_ee[4], + g_cdvdstm_bankgp_ee, + g_cdvdstm_bankcur_ee); + posszarg2_bytes_overrun = posszarg2_bytes - (posszarg2_bytes_remain - posszarg2_bytes_clamped); + break; + } + } + } + if ( posszarg2_bytes_overrun == 0xFFFFFFFF ) + posszarg2_bytes_overrun = posszarg2_bytes; + if ( !g_cdvdstm_usedchunksize2 ) + __builtin_trap(); + posszarg2_overrun_chunks2 = posszarg2_bytes_overrun / g_cdvdstm_usedchunksize2; + if ( retryflag ) + { + *outres_ptr = 1; + return; + } + if ( sceCdSC(0xFFFFFFFF, &g_cdvdstm_last_error_for_ee) != 2 && !posszarg2_overrun_chunks2 && !g_cdvdstm_retryerr_ee ) + g_cdvdstm_retryerr_ee = 273; + if ( g_cdvdstm_retryerr_ee ) + { + posszarg2_overrun_chunks2 = (u16)posszarg2_overrun_chunks2 | (g_cdvdstm_retryerr_ee << 16); + g_cdvdstm_retryerr_ee = 0; + } + *outres_ptr = posszarg2_overrun_chunks2; +} + +static unsigned int ee_stream_intr_cb_cdda(void *userdata) +{ + int scres_unused; + + (void)userdata; + + VERBOSE_KPRINTF(1, "Intr EE DA Stm Read call\n"); + iCancelAlarm((unsigned int (*)(void *))stm_ee_read_timeout_alarm_cb, &g_cdvdstm_curclk_ee); + iCancelAlarm((unsigned int (*)(void *))ee_stream_intr_cb_cdda, &g_cdvdstm_curclk_ee); + sceCdSC(0xFFFFFFFF, &g_cdvdstm_last_error_for_ee); + if ( !g_cdvdstm_last_error_for_ee ) + { + switch ( sceCdGetDiskType() ) + { + case SCECdPSCDDA: + case SCECdPS2CDDA: + case 0x21: + case SCECdCDDA: + break; + default: + g_cdvdstm_last_error_for_ee = SCECdErREADCF; + break; + } + } + g_cdvdstm_curclk_ee.hi = 0; + if ( g_cdvdstm_stmstart_ee ) + g_cdvdstm_retrycnt_ee_cdda = 0; + g_cdvdstm_curclk_ee.lo = (g_cdvdstm_stmstart_ee || g_cdvdstm_last_error_for_ee || g_cdvdstm_retrycnt_ee_cdda) ? + 0x20f58000 : + (0x9000 * sceCdSC(0xFFFFFFEF, &scres_unused)); + if ( g_cdvdstm_last_error_for_ee ) + { + VERBOSE_KPRINTF( + 1, + "EE Stream read LBN= %d Error code= 0x%02x retry= %d\n", + g_cdvdstm_readlbn_ee_cdda, + g_cdvdstm_last_error_for_ee, + g_cdvdstm_retrycnt_ee_cdda); + if ( g_cdvdstm_last_error_for_ee == SCECdErREAD || g_cdvdstm_last_error_for_ee == SCECdErABRT ) + { + if ( g_cdvdstm_retrycnt_ee_cdda ) + { + VERBOSE_KPRINTF(1, "On Retry retry %d err %08x\n", g_cdvdstm_retrycnt_ee_cdda, g_cdvdstm_last_error_for_ee); + } + g_cdvdstm_retrycnt_ee_cdda = 4; + } + else + { + g_cdvdstm_retrycnt_ee_cdda = 1; + } + g_cdvdstm_retryerr_ee = g_cdvdstm_last_error_for_ee; + } + else + { + g_cdvdstm_retrycnt_ee_cdda = 0; + } + if ( g_cdvdstm_retrycnt_ee_cdda ) + { + g_cdvdstm_retrycnt_ee_cdda -= 1; + if ( + !g_cdvdstm_retrycnt_ee_cdda + && (g_cdvdstm_last_error_for_ee == SCECdErREAD || g_cdvdstm_last_error_for_ee == SCECdErABRT) ) + { + g_cdvdstm_readlbn_ee_cdda = + g_cdvdstm_lsn_ee + ((g_cdvdstm_sectorcount2 < 0x1D) ? (0x1D - g_cdvdstm_sectorcount2) : 0); + g_cdvdstm_lsn_ee = g_cdvdstm_readlbn_ee_cdda + g_cdvdstm_sectorcount2; + } + if ( sceCdReadCDDA( + g_cdvdstm_readlbn_ee_cdda, + g_cdvdstm_sectorcount2, + (char *)g_cdvdstm_buffer2 + g_cdvdstm_bankgp_ee * g_cdvdstm_chunksz2, + &g_cdvdstm_mode_ee) ) + { + iSetAlarm(&g_cdvdstm_curclk_ee, (unsigned int (*)(void *))stm_ee_read_timeout_alarm_cb, &g_cdvdstm_curclk_ee); + } + else + { + VERBOSE_KPRINTF(1, "Stm Read Call fail\n"); + g_cdvdstm_curclk_ee.lo = 0x708000; + if ( + iSetAlarm(&g_cdvdstm_curclk_ee, (unsigned int (*)(void *))ee_stream_intr_cb_cdda, &g_cdvdstm_curclk_ee) + && !sceCdNop() ) + { + sceCdSC(0, &g_cdvdstm_last_error_for_ee); + } + g_cdvdstm_retrycnt_ee_cdda += 1; + } + } + else + { + int gptmp; + + if ( !g_cdvdstm_stmstart_ee ) + { + g_cdvdstm_usedmap_ee[g_cdvdstm_bankgp_ee] = 1; + gptmp = g_cdvdstm_bankgp_ee; + g_cdvdstm_bankgp_ee += 1; + if ( (unsigned int)g_cdvdstm_bankgp_ee >= (unsigned int)g_cdvdstm_bankcnt2 ) + g_cdvdstm_bankgp_ee = 0; + } + if ( + !g_cdvdstm_stmstart_ee + && (g_cdvdstm_usedmap_ee[g_cdvdstm_bankgp_ee] || g_cdvdstm_bankcur_ee == g_cdvdstm_bankgp_ee) ) + { + g_cdvdstm_bankgp_ee = gptmp; + g_cdvdstm_usedmap_ee[gptmp] = 0; + VERBOSE_KPRINTF( + 1, + "read Full %d %d %d %d %d gp %d pp %d spn %d\n", + (u8)g_cdvdstm_usedmap_ee[0], + (u8)g_cdvdstm_usedmap_ee[1], + (u8)g_cdvdstm_usedmap_ee[2], + (u8)g_cdvdstm_usedmap_ee[3], + (u8)g_cdvdstm_usedmap_ee[4], + g_cdvdstm_bankgp_ee, + g_cdvdstm_bankcur_ee, + g_cdvdstm_mode_ee.spindlctrl); + g_cdvdstm_curclk_ee.lo = 0x48000; + if ( + iSetAlarm(&g_cdvdstm_curclk_ee, (unsigned int (*)(void *))ee_stream_intr_cb_cdda, &g_cdvdstm_curclk_ee) + && !sceCdNop() ) + { + sceCdSC(0, &g_cdvdstm_last_error_for_ee); + } + } + else + { + if ( g_cdvdstm_stmstart_ee == 2 ) + { + unsigned int i; + + g_cdvdstm_bankoffs_ee = 0; + g_cdvdstm_bankcur_ee = 0; + g_cdvdstm_bankgp_ee = 0; + for ( i = 0; i < (unsigned int)g_cdvdstm_bankcnt2; i += 1 ) + g_cdvdstm_usedmap_ee[i] = 0; + } + g_cdvdstm_stmstart_ee = 0; + g_cdvdstm_readlbn_ee_cdda = g_cdvdstm_lsn_ee; + if ( sceCdReadCDDA( + g_cdvdstm_lsn_ee, + g_cdvdstm_sectorcount2, + (char *)g_cdvdstm_buffer2 + g_cdvdstm_bankgp_ee * g_cdvdstm_chunksz2, + &g_cdvdstm_mode_ee) ) + { + iSetAlarm(&g_cdvdstm_curclk_ee, (unsigned int (*)(void *))stm_ee_read_timeout_alarm_cb, &g_cdvdstm_curclk_ee); + } + else + { + VERBOSE_KPRINTF(1, "Stm Read Call1 fail\n"); + g_cdvdstm_curclk_ee.lo = 0x708000; + if ( + iSetAlarm(&g_cdvdstm_curclk_ee, (unsigned int (*)(void *))ee_stream_intr_cb_cdda, &g_cdvdstm_curclk_ee) + && !sceCdNop() ) + { + sceCdSC(0, &g_cdvdstm_last_error_for_ee); + } + g_cdvdstm_retrycnt_ee_cdda = 1; + } + g_cdvdstm_lsn_ee += g_cdvdstm_sectorcount2; + } + } + return 0; +} + +// clang-format off +__asm__ ( + "\t" ".set push" "\n" + "\t" ".set noat" "\n" + "\t" ".set noreorder" "\n" + "\t" ".global optimized_memcpy" "\n" + "\t" "optimized_memcpy:" "\n" + "\t" " srl $a3, $a2, 2" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_12" "\n" + "\t" " or $a3, $a0, $a1" "\n" + "\t" " andi $a3, $a3, 0x3" "\n" + "\t" " bnez $a3, .Loptimized_memcpy_3" "\n" + "\t" " nop" "\n" + "\t" " srl $a3, $a2, 2" "\n" + "\t" " addiu $at, $zero, 0xC" "\n" + "\t" " div $zero, $a3, $at" "\n" + "\t" " mflo $a3" "\n" + "\t" " mfhi $v1" "\n" + "\t" " beqz $v1, .Loptimized_memcpy_2" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_1:" "\n" + "\t" " lw $v0, 0x0($a1)" "\n" + "\t" " addiu $v1, $v1, -0x1" "\n" + "\t" " sw $v0, 0x0($a0)" "\n" + "\t" " addiu $a1, $a1, 0x4" "\n" + "\t" " bnez $v1, .Loptimized_memcpy_1" "\n" + "\t" " addiu $a0, $a0, 0x4" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_12" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_2:" "\n" + "\t" " lw $v0, 0x0($a1)" "\n" + "\t" " lw $v1, 0x4($a1)" "\n" + "\t" " lw $t0, 0x8($a1)" "\n" + "\t" " lw $t1, 0xC($a1)" "\n" + "\t" " lw $t2, 0x10($a1)" "\n" + "\t" " lw $t3, 0x14($a1)" "\n" + "\t" " lw $t4, 0x18($a1)" "\n" + "\t" " lw $t5, 0x1C($a1)" "\n" + "\t" " lw $t6, 0x20($a1)" "\n" + "\t" " lw $t7, 0x24($a1)" "\n" + "\t" " lw $t8, 0x28($a1)" "\n" + "\t" " lw $t9, 0x2C($a1)" "\n" + "\t" " addiu $a3, $a3, -0x1" "\n" + "\t" " sw $v0, 0x0($a0)" "\n" + "\t" " sw $v1, 0x4($a0)" "\n" + "\t" " sw $t0, 0x8($a0)" "\n" + "\t" " sw $t1, 0xC($a0)" "\n" + "\t" " sw $t2, 0x10($a0)" "\n" + "\t" " sw $t3, 0x14($a0)" "\n" + "\t" " sw $t4, 0x18($a0)" "\n" + "\t" " sw $t5, 0x1C($a0)" "\n" + "\t" " sw $t6, 0x20($a0)" "\n" + "\t" " sw $t7, 0x24($a0)" "\n" + "\t" " sw $t8, 0x28($a0)" "\n" + "\t" " sw $t9, 0x2C($a0)" "\n" + "\t" " addiu $a1, $a1, 0x30" "\n" + "\t" " bnez $a3, .Loptimized_memcpy_2" "\n" + "\t" " addiu $a0, $a0, 0x30" "\n" + "\t" " j .Loptimized_memcpy_12" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_3:" "\n" + "\t" " andi $a3, $a0, 0x3" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_6" "\n" + "\t" " andi $a3, $a1, 0x3" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_6" "\n" + "\t" " nop" "\n" + "\t" " srl $a3, $a2, 2" "\n" + "\t" " addiu $at, $zero, 0xC" "\n" + "\t" " div $zero, $a3, $at" "\n" + "\t" " mflo $a3" "\n" + "\t" " mfhi $v1" "\n" + "\t" " beqz $v1, .Loptimized_memcpy_5" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_4:" "\n" + "\t" " lwl $v0, 0x3($a1)" "\n" + "\t" " lwr $v0, 0x0($a1)" "\n" + "\t" " addiu $v1, $v1, -0x1" "\n" + "\t" " swl $v0, 0x3($a0)" "\n" + "\t" " swr $v0, 0x0($a0)" "\n" + "\t" " addiu $a1, $a1, 0x4" "\n" + "\t" " bnez $v1, .Loptimized_memcpy_4" "\n" + "\t" " addiu $a0, $a0, 0x4" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_12" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_5:" "\n" + "\t" " lwl $v0, 0x3($a1)" "\n" + "\t" " lwr $v0, 0x0($a1)" "\n" + "\t" " lwl $v1, 0x7($a1)" "\n" + "\t" " lwr $v1, 0x4($a1)" "\n" + "\t" " lwl $t0, 0xB($a1)" "\n" + "\t" " lwr $t0, 0x8($a1)" "\n" + "\t" " lwl $t1, 0xF($a1)" "\n" + "\t" " lwr $t1, 0xC($a1)" "\n" + "\t" " lwl $t2, 0x13($a1)" "\n" + "\t" " lwr $t2, 0x10($a1)" "\n" + "\t" " lwl $t3, 0x17($a1)" "\n" + "\t" " lwr $t3, 0x14($a1)" "\n" + "\t" " lwl $t4, 0x1B($a1)" "\n" + "\t" " lwr $t4, 0x18($a1)" "\n" + "\t" " lwl $t5, 0x1F($a1)" "\n" + "\t" " lwr $t5, 0x1C($a1)" "\n" + "\t" " lwl $t6, 0x23($a1)" "\n" + "\t" " lwr $t6, 0x20($a1)" "\n" + "\t" " lwl $t7, 0x27($a1)" "\n" + "\t" " lwr $t7, 0x24($a1)" "\n" + "\t" " lwl $t8, 0x2B($a1)" "\n" + "\t" " lwr $t8, 0x28($a1)" "\n" + "\t" " lwl $t9, 0x2F($a1)" "\n" + "\t" " lwr $t9, 0x2C($a1)" "\n" + "\t" " addiu $a3, $a3, -0x1" "\n" + "\t" " swl $v0, 0x3($a0)" "\n" + "\t" " swr $v0, 0x0($a0)" "\n" + "\t" " swl $v1, 0x7($a0)" "\n" + "\t" " swr $v1, 0x4($a0)" "\n" + "\t" " swl $t0, 0xB($a0)" "\n" + "\t" " swr $t0, 0x8($a0)" "\n" + "\t" " swl $t1, 0xF($a0)" "\n" + "\t" " swr $t1, 0xC($a0)" "\n" + "\t" " swl $t2, 0x13($a0)" "\n" + "\t" " swr $t2, 0x10($a0)" "\n" + "\t" " swl $t3, 0x17($a0)" "\n" + "\t" " swr $t3, 0x14($a0)" "\n" + "\t" " swl $t4, 0x1B($a0)" "\n" + "\t" " swr $t4, 0x18($a0)" "\n" + "\t" " swl $t5, 0x1F($a0)" "\n" + "\t" " swr $t5, 0x1C($a0)" "\n" + "\t" " swl $t6, 0x23($a0)" "\n" + "\t" " swr $t6, 0x20($a0)" "\n" + "\t" " swl $t7, 0x27($a0)" "\n" + "\t" " swr $t7, 0x24($a0)" "\n" + "\t" " swl $t8, 0x2B($a0)" "\n" + "\t" " swr $t8, 0x28($a0)" "\n" + "\t" " swl $t9, 0x2F($a0)" "\n" + "\t" " swr $t9, 0x2C($a0)" "\n" + "\t" " addiu $a1, $a1, 0x30" "\n" + "\t" " bnez $a3, .Loptimized_memcpy_5" "\n" + "\t" " addiu $a0, $a0, 0x30" "\n" + "\t" " j .Loptimized_memcpy_12" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_6:" "\n" + "\t" " andi $a3, $a0, 0x3" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_9" "\n" + "\t" " nop" "\n" + "\t" " srl $a3, $a2, 2" "\n" + "\t" " addiu $at, $zero, 0xC" "\n" + "\t" " div $zero, $a3, $at" "\n" + "\t" " mflo $a3" "\n" + "\t" " mfhi $v1" "\n" + "\t" " beqz $v1, .Loptimized_memcpy_8" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_7:" "\n" + "\t" " lw $v0, 0x0($a1)" "\n" + "\t" " addiu $v1, $v1, -0x1" "\n" + "\t" " swl $v0, 0x3($a0)" "\n" + "\t" " swr $v0, 0x0($a0)" "\n" + "\t" " addiu $a1, $a1, 0x4" "\n" + "\t" " bnez $v1, .Loptimized_memcpy_7" "\n" + "\t" " addiu $a0, $a0, 0x4" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_12" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_8:" "\n" + "\t" " lw $v0, 0x0($a1)" "\n" + "\t" " lw $v1, 0x4($a1)" "\n" + "\t" " lw $t0, 0x8($a1)" "\n" + "\t" " lw $t1, 0xC($a1)" "\n" + "\t" " lw $t2, 0x10($a1)" "\n" + "\t" " lw $t3, 0x14($a1)" "\n" + "\t" " lw $t4, 0x18($a1)" "\n" + "\t" " lw $t5, 0x1C($a1)" "\n" + "\t" " lw $t6, 0x20($a1)" "\n" + "\t" " lw $t7, 0x24($a1)" "\n" + "\t" " lw $t8, 0x28($a1)" "\n" + "\t" " lw $t9, 0x2C($a1)" "\n" + "\t" " addiu $a3, $a3, -0x1" "\n" + "\t" " swl $v0, 0x3($a0)" "\n" + "\t" " swr $v0, 0x0($a0)" "\n" + "\t" " swl $v1, 0x7($a0)" "\n" + "\t" " swr $v1, 0x4($a0)" "\n" + "\t" " swl $t0, 0xB($a0)" "\n" + "\t" " swr $t0, 0x8($a0)" "\n" + "\t" " swl $t1, 0xF($a0)" "\n" + "\t" " swr $t1, 0xC($a0)" "\n" + "\t" " swl $t2, 0x13($a0)" "\n" + "\t" " swr $t2, 0x10($a0)" "\n" + "\t" " swl $t3, 0x17($a0)" "\n" + "\t" " swr $t3, 0x14($a0)" "\n" + "\t" " swl $t4, 0x1B($a0)" "\n" + "\t" " swr $t4, 0x18($a0)" "\n" + "\t" " swl $t5, 0x1F($a0)" "\n" + "\t" " swr $t5, 0x1C($a0)" "\n" + "\t" " swl $t6, 0x23($a0)" "\n" + "\t" " swr $t6, 0x20($a0)" "\n" + "\t" " swl $t7, 0x27($a0)" "\n" + "\t" " swr $t7, 0x24($a0)" "\n" + "\t" " swl $t8, 0x2B($a0)" "\n" + "\t" " swr $t8, 0x28($a0)" "\n" + "\t" " swl $t9, 0x2F($a0)" "\n" + "\t" " swr $t9, 0x2C($a0)" "\n" + "\t" " addiu $a1, $a1, 0x30" "\n" + "\t" " bnez $a3, .Loptimized_memcpy_8" "\n" + "\t" " addiu $a0, $a0, 0x30" "\n" + "\t" " j .Loptimized_memcpy_12" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_9:" "\n" + "\t" " srl $a3, $a2, 2" "\n" + "\t" " addiu $at, $zero, 0xC" "\n" + "\t" " div $zero, $a3, $at" "\n" + "\t" " mflo $a3" "\n" + "\t" " mfhi $v1" "\n" + "\t" " beqz $v1, .Loptimized_memcpy_11" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_10:" "\n" + "\t" " lwl $v0, 0x3($a1)" "\n" + "\t" " lwr $v0, 0x0($a1)" "\n" + "\t" " addiu $v1, $v1, -0x1" "\n" + "\t" " sw $v0, 0x0($a0)" "\n" + "\t" " addiu $a1, $a1, 0x4" "\n" + "\t" " bnez $v1, .Loptimized_memcpy_10" "\n" + "\t" " addiu $a0, $a0, 0x4" "\n" + "\t" " beqz $a3, .Loptimized_memcpy_12" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_11:" "\n" + "\t" " lwl $v0, 0x3($a1)" "\n" + "\t" " lwr $v0, 0x0($a1)" "\n" + "\t" " lwl $v1, 0x7($a1)" "\n" + "\t" " lwr $v1, 0x4($a1)" "\n" + "\t" " lwl $t0, 0xB($a1)" "\n" + "\t" " lwr $t0, 0x8($a1)" "\n" + "\t" " lwl $t1, 0xF($a1)" "\n" + "\t" " lwr $t1, 0xC($a1)" "\n" + "\t" " lwl $t2, 0x13($a1)" "\n" + "\t" " lwr $t2, 0x10($a1)" "\n" + "\t" " lwl $t3, 0x17($a1)" "\n" + "\t" " lwr $t3, 0x14($a1)" "\n" + "\t" " lwl $t4, 0x1B($a1)" "\n" + "\t" " lwr $t4, 0x18($a1)" "\n" + "\t" " lwl $t5, 0x1F($a1)" "\n" + "\t" " lwr $t5, 0x1C($a1)" "\n" + "\t" " lwl $t6, 0x23($a1)" "\n" + "\t" " lwr $t6, 0x20($a1)" "\n" + "\t" " lwl $t7, 0x27($a1)" "\n" + "\t" " lwr $t7, 0x24($a1)" "\n" + "\t" " lwl $t8, 0x2B($a1)" "\n" + "\t" " lwr $t8, 0x28($a1)" "\n" + "\t" " lwl $t9, 0x2F($a1)" "\n" + "\t" " lwr $t9, 0x2C($a1)" "\n" + "\t" " addiu $a3, $a3, -0x1" "\n" + "\t" " sw $v0, 0x0($a0)" "\n" + "\t" " sw $v1, 0x4($a0)" "\n" + "\t" " sw $t0, 0x8($a0)" "\n" + "\t" " sw $t1, 0xC($a0)" "\n" + "\t" " sw $t2, 0x10($a0)" "\n" + "\t" " sw $t3, 0x14($a0)" "\n" + "\t" " sw $t4, 0x18($a0)" "\n" + "\t" " sw $t5, 0x1C($a0)" "\n" + "\t" " sw $t6, 0x20($a0)" "\n" + "\t" " sw $t7, 0x24($a0)" "\n" + "\t" " sw $t8, 0x28($a0)" "\n" + "\t" " sw $t9, 0x2C($a0)" "\n" + "\t" " addiu $a1, $a1, 0x30" "\n" + "\t" " bnez $a3, .Loptimized_memcpy_11" "\n" + "\t" " addiu $a0, $a0, 0x30" "\n" + "\t" ".Loptimized_memcpy_12:" "\n" + "\t" " andi $v1, $a2, 0x3" "\n" + "\t" " beqz $v1, .Loptimized_memcpy_14" "\n" + "\t" " nop" "\n" + "\t" ".Loptimized_memcpy_13:" "\n" + "\t" " lb $v0, 0x0($a1)" "\n" + "\t" " addiu $v1, $v1, -0x1" "\n" + "\t" " sb $v0, 0x0($a0)" "\n" + "\t" " addiu $a1, $a1, 0x1" "\n" + "\t" " bnez $v1, .Loptimized_memcpy_13" "\n" + "\t" " addiu $a0, $a0, 0x1" "\n" + "\t" ".Loptimized_memcpy_14:" "\n" + "\t" " addu $v0, $a2, $zero" "\n" + "\t" " jr $ra" "\n" + "\t" " nop" "\n" + "\t" ".set pop" "\n" +); +// clang-format on diff --git a/iop/cdvd/cdvdstm/src/exports.tab b/iop/cdvd/cdvdstm/src/exports.tab new file mode 100644 index 00000000000..0d77e4d4096 --- /dev/null +++ b/iop/cdvd/cdvdstm/src/exports.tab @@ -0,0 +1,10 @@ + +DECLARE_EXPORT_TABLE(cdvdstm, 1, 1) +DECLARE_EXPORT(_start) +DECLARE_EXPORT(_retonly) +DECLARE_EXPORT(cdvdstm_termcall) +DECLARE_EXPORT(_retonly) +DECLARE_EXPORT(cdvdstm_dummyentry) +END_EXPORT_TABLE + +void _retonly() {} diff --git a/iop/cdvd/cdvdstm/src/imports.lst b/iop/cdvd/cdvdstm/src/imports.lst new file mode 100644 index 00000000000..3752f4efa78 --- /dev/null +++ b/iop/cdvd/cdvdstm/src/imports.lst @@ -0,0 +1,68 @@ + +sysmem_IMPORTS_start +I_Kprintf +sysmem_IMPORTS_end + +loadcore_IMPORTS_start +I_RegisterLibraryEntries +I_ReleaseLibraryEntries +loadcore_IMPORTS_end + +intrman_IMPORTS_start +I_CpuSuspendIntr +I_CpuResumeIntr +I_QueryIntrContext +intrman_IMPORTS_end + +stdio_IMPORTS_start +I_printf +stdio_IMPORTS_end + +thbase_IMPORTS_start +I_DelayThread +I_iSetAlarm +I_CancelAlarm +I_iCancelAlarm +thbase_IMPORTS_end + +thevent_IMPORTS_start +I_SetEventFlag +I_iSetEventFlag +I_ClearEventFlag +I_iClearEventFlag +I_WaitEventFlag +thevent_IMPORTS_end + +thsemap_IMPORTS_start +I_CreateSema +I_DeleteSema +I_SignalSema +I_WaitSema +thsemap_IMPORTS_end + +sifman_IMPORTS_start +I_sceSifSetDma +I_sceSifDmaStat +sifman_IMPORTS_end + +iomanX_IMPORTS_start +I_AddDrv +I_DelDrv +iomanX_IMPORTS_end + +cdvdman_IMPORTS_start +I_sceCdSync +I_sceCdGetDiskType +I_sceCdBreak +I_sceCdReadCDDA +I_sceCdNop +I_sceCdstm0Cb +I_sceCdstm1Cb +I_sceCdSC +I_sceCdStStop +I_sceCdRE +cdvdman_IMPORTS_end + +sysclib_IMPORTS_start +I_memset +sysclib_IMPORTS_end diff --git a/iop/cdvd/cdvdstm/src/irx_imports.h b/iop/cdvd/cdvdstm/src/irx_imports.h new file mode 100644 index 00000000000..290d94e9e1d --- /dev/null +++ b/iop/cdvd/cdvdstm/src/irx_imports.h @@ -0,0 +1,29 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +*/ + +#ifndef IOP_IRX_IMPORTS_H +#define IOP_IRX_IMPORTS_H + +#include "irx.h" + +/* Please keep these in alphabetical order! */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif /* IOP_IRX_IMPORTS_H */ From fba28f53b198557eb2293dcb4b79f04dff1b8da7 Mon Sep 17 00:00:00 2001 From: Julian Uy Date: Wed, 23 Oct 2024 09:45:45 -0500 Subject: [PATCH 8/8] add: Hook up cdvd modules to buildsystem --- iop/cdvd/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/iop/cdvd/Makefile b/iop/cdvd/Makefile index cbe0be55eec..f24c1a5af46 100644 --- a/iop/cdvd/Makefile +++ b/iop/cdvd/Makefile @@ -8,6 +8,9 @@ SUBDIRS = \ cdfs \ + cdvdfsv \ + cdvdman \ + cdvdstm \ xesdrv include $(PS2SDKSRC)/Defs.make