mirror of
https://github.com/astromaddie/HaloCE-VR.git
synced 2026-10-23 07:00:12 +02:00
Integrate coherent B3, P2/K17 prerequisites, completed K1-K16 + S, and the independent profile/effects rulings. Five gains and two explicitly approved B3 debits: net +3 strict functions, +2770 meaningful/+2800 padded bytes (+2774 progress credit). No additional losses; Halo objects 394 to 396 and data unchanged. Clean rebuild, identical 8252-row stable sweep, 68 valid parks, admission/provider checks, 467-unit warning comparison, unchanged fake scan, and 1318 tests passed. Preserve canonical helper recoveries and unrelated work. Full evidence and disclosures in docs/object_matching_logs/astra_five_function_reconciliation_20260928.md.
1809 lines
50 KiB
C
1809 lines
50 KiB
C
/*
|
|
CACHE_FILES_DECOMPRESS_WINDOWS.C
|
|
|
|
symbols in this file:
|
|
001A9C10 0020:
|
|
_code_001a9c10 (0000)
|
|
001A9C30 0040:
|
|
_cache_copy_buffer_size (0000)
|
|
001A9C70 0040:
|
|
_cache_copy_set_priority (0000)
|
|
001A9CB0 0020:
|
|
_cache_copy_compressed_file_complete (0000)
|
|
001A9CD0 02e0:
|
|
_cache_copy_begin (0000)
|
|
001A9FB0 0030:
|
|
_cache_copy_queue_end (0000)
|
|
001A9FE0 0030:
|
|
_code_001a9fe0 (0000)
|
|
001AA010 0030:
|
|
_code_001aa010 (0000)
|
|
001AA040 0060:
|
|
_code_001aa040 (0000)
|
|
001AA0A0 0050:
|
|
_code_001aa0a0 (0000)
|
|
001AA0F0 00b0:
|
|
_code_001aa0f0 (0000)
|
|
001AA1A0 00f0:
|
|
_code_001aa1a0 (0000)
|
|
001AA290 0080:
|
|
_code_001aa290 (0000)
|
|
001AA310 00a0:
|
|
_code_001aa310 (0000)
|
|
001AA3B0 0070:
|
|
_acquire_read_request (0000)
|
|
001AA420 0010:
|
|
_code_001aa420 (0000)
|
|
001AA430 0050:
|
|
_code_001aa430 (0000)
|
|
001AA480 0050:
|
|
_code_001aa480 (0000)
|
|
001AA4D0 0040:
|
|
_code_001aa4d0 (0000)
|
|
001AA510 0030:
|
|
_code_001aa510 (0000)
|
|
001AA540 00a0:
|
|
_code_001aa540 (0000)
|
|
001AA5E0 0030:
|
|
_code_001aa5e0 (0000)
|
|
001AA610 0010:
|
|
_code_001aa610 (0000)
|
|
001AA620 0020:
|
|
_code_001aa620 (0000)
|
|
001AA640 0010:
|
|
_code_001aa640 (0000)
|
|
001AA650 0030:
|
|
_code_001aa650 (0000)
|
|
001AA680 0100:
|
|
_code_001aa680 (0000)
|
|
001AA780 0020:
|
|
_code_001aa780 (0000)
|
|
001AA7A0 0190:
|
|
_cache_copy_get_status (0000)
|
|
001AA930 0050:
|
|
_cache_copy_end (0000)
|
|
001AA980 01f0:
|
|
_cache_copy_FileIOCompletionRoutine@12 (0000)
|
|
001AAB70 0140:
|
|
_code_001aab70 (0000)
|
|
001AACB0 0140:
|
|
_code_001aacb0 (0000)
|
|
001AADF0 0010:
|
|
_code_001aadf0 (0000)
|
|
001AAE00 0010:
|
|
_code_001aae00 (0000)
|
|
001AAE10 0100:
|
|
_code_001aae10 (0000)
|
|
001AAF10 0020:
|
|
_code_001aaf10 (0000)
|
|
001AAF30 0050:
|
|
_code_001aaf30 (0000)
|
|
001AAF80 00a0:
|
|
_code_001aaf80 (0000)
|
|
001AB020 0190:
|
|
_code_001ab020 (0000)
|
|
001AB1B0 00d0:
|
|
_code_001ab1b0 (0000)
|
|
001AB280 00d0:
|
|
_code_001ab280 (0000)
|
|
001AB350 01f0:
|
|
_code_001ab350 (0000)
|
|
001AB540 0340:
|
|
_code_001ab540 (0000)
|
|
001AB880 03e0:
|
|
_code_001ab880 (0000)
|
|
001ABC60 00e0:
|
|
_cache_copy_initialize (0000)
|
|
002A678C 0027:
|
|
??_C@_0CH@DEOMLBEE@previous?5copy?5session?5did?5not?5co@ (0000)
|
|
002A67B4 001f:
|
|
??_C@_0BP@HMMCGILP@global_self?9?$DOzlib_stream?4zfree?$AA@ (0000)
|
|
002A67D4 0020:
|
|
??_C@_0CA@KHDIIHBG@global_self?9?$DOzlib_stream?4zalloc?$AA@ (0000)
|
|
002A67F4 0019:
|
|
??_C@_0BJ@OMJKHEGP@global_self?9?$DOcopy_thread?$AA@ (0000)
|
|
002A6810 0023:
|
|
??_C@_0CD@LDNLLCFF@global_self?9?$DOprogress_update_eve@ (0000)
|
|
002A6834 001e:
|
|
??_C@_0BO@JMEKOEMJ@global_self?9?$DOcopy_start_event?$AA@ (0000)
|
|
002A6854 001d:
|
|
??_C@_0BN@CPKCEALK@global_self?9?$DOcopy_stop_event?$AA@ (0000)
|
|
002A6874 0021:
|
|
??_C@_0CB@BCJBNPEM@global_self?9?$DOcopy_complete_event@ (0000)
|
|
002A6898 003b:
|
|
??_C@_0DL@ONPPJPGL@destination_file_size?$DN?$DNGetFileSi@ (0000)
|
|
002A68D4 0019:
|
|
??_C@_0BJ@OEKJHJKP@size?$DO?$DN?5TOTAL_BUFFER_SIZE?$AA@ (0000)
|
|
002A68F0 0027:
|
|
??_C@_0CH@CBDPEJFF@destination_file?$CB?$DNINVALID_HANDLE@ (0000)
|
|
002A6918 0011:
|
|
??_C@_0BB@BCPHFHCK@source_file_name?$AA@ (0000)
|
|
002A692C 0036:
|
|
??_C@_0DG@MLNPNOIK@c?3?2halo?2SOURCE?2cache?2cache_files@ (0000)
|
|
002A6968 0054:
|
|
??_C@_0FE@LDLBBNEG@global_self?9?$DOnext_allocation?9glo@ (0000)
|
|
002A69BC 002d:
|
|
??_C@_0CN@FECNJEGA@?$CIbyte?$CK?$CJaddress?$DM?$DNglobal_self?9?$DOnex@ (0000)
|
|
002A69EC 002c:
|
|
??_C@_0CM@LBNMACHE@self?9?$DOread_bytes_left?$DO?$DNsizeof?$CIse@ (0000)
|
|
002A6A18 0020:
|
|
??_C@_0CA@HLJBOAAC@wait_result?$DN?$DNWAIT_IO_COMPLETION?$AA@ (0000)
|
|
002A6A38 0047:
|
|
??_C@_0EH@PCOCAIPP@?$CBBIT_VECTOR_TEST_FLAG?$CIself?9?$DOover@ (0000)
|
|
002A6A80 0048:
|
|
??_C@_0EI@PCEOFLKP@?$CBBIT_VECTOR_TEST_FLAG?$CIself?9?$DOover@ (0000)
|
|
002A6AC8 0047:
|
|
??_C@_0EH@IFOIJONL@BIT_VECTOR_TEST_FLAG?$CIself?9?$DOoverl@ (0000)
|
|
002A6B10 0041:
|
|
??_C@_0EB@CMIFFJIK@read_buffer_index?$DO?$DN0?5?$CG?$CG?5read_buf@ (0000)
|
|
002A6B58 0044:
|
|
??_C@_0EE@OHEFCECI@write_buffer_index?$DO?$DN0?5?$CG?$CG?5write_b@ (0000)
|
|
002A6BA0 0073:
|
|
??_C@_0HD@EMNFMEOI@?$CBany_bit_vector_flag_set?$CIself?9?$DOo@ (0000)
|
|
002A6C14 001d:
|
|
??_C@_0BN@LPNNBCIB@?5?5?5?5Total?5copying?5time?3?5?$CF?43f?$AA@ (0000)
|
|
002A6C34 002d:
|
|
??_C@_0CN@LCCDIMEO@?5?5?5?5Total?5thread?5blocked?5on?5writ@ (0000)
|
|
002A6C64 002c:
|
|
??_C@_0CM@JPMPFADM@?5?5?5?5Total?5thread?5blocked?5on?5read@ (0000)
|
|
002A6C90 0024:
|
|
??_C@_0CE@BLKMPKLJ@?5?5?5?5Total?5thread?5blocked?5time?3?5?$CF@ (0000)
|
|
002A6CB4 002c:
|
|
??_C@_0CM@KIFMLGDM@?5?5?5?5Total?5zlib?5during?5write?5file@ (0000)
|
|
002A6CE0 001a:
|
|
??_C@_0BK@BCPDIOIM@?5?5?5?5Total?5zlib?5time?3?5?$CF?43f?$AA@ (0000)
|
|
002A6CFC 0020:
|
|
??_C@_0CA@ENEIKNJP@?5?5?5?5Total?5write?5file?5time?3?5?$CF?43f?$AA@ (0000)
|
|
002A6D1C 001f:
|
|
??_C@_0BP@PBPKHODK@?5?5?5?5Total?5read?5file?5time?3?5?$CF?43f?$AA@ (0000)
|
|
002A6D3C 0024:
|
|
??_C@_0CE@MEJJJAJL@Timing?5for?5copying?5last?5cache?5fi@ (0000)
|
|
002A6D60 0009:
|
|
??_C@_08LCGAPFCF@progress?$AA@ (0000)
|
|
002A6D6C 0026:
|
|
??_C@_0CG@JIHKMCLM@async?5i?1o?5finished?5with?5error?5co@ (0000)
|
|
002A6D94 0026:
|
|
??_C@_0CG@LFNPHDNB@global_self?9?$DOasync_write_bytes_l@ (0000)
|
|
002A6DBC 0025:
|
|
??_C@_0CF@BLFCMLCE@global_self?9?$DOasync_read_bytes_le@ (0000)
|
|
002A6DE4 0024:
|
|
??_C@_0CE@KFFHFCII@couldn?8t?5issue?5an?5asynchronous?5r@ (0000)
|
|
002A6E08 0047:
|
|
??_C@_0EH@DHKKDFLG@?$CBBIT_VECTOR_TEST_FLAG?$CIself?9?$DOover@ (0000)
|
|
002A6E50 0025:
|
|
??_C@_0CF@KANDJCBM@couldn?8t?5issue?5an?5asynchronous?5w@ (0000)
|
|
002A6E78 0030:
|
|
??_C@_0DA@INJGOAAO@self?9?$DOcurrent_read_offset?$DM?$DNself?9@ (0000)
|
|
002A6EA8 0023:
|
|
??_C@_0CD@JCFNHENM@request?9?$DOread_sequence_index?$DN?$DNNO@ (0000)
|
|
002A6ED0 005c:
|
|
??_C@_0FM@IKECPIPA@BIT_VECTOR_TEST_FLAG?$CIself?9?$DOoverl@ (0000)
|
|
002A6F2C 002e:
|
|
??_C@_0CO@NCHCHCFL@self?9?$DOcurrent_write_offset?$DM?$DNself@ (0000)
|
|
002A6F5C 0005:
|
|
??_C@_04EPOOCEMM@blah?$AA@ (0000)
|
|
002A6F64 0027:
|
|
??_C@_0CH@DEEKDHHP@global_self?9?$DOasync_write_bytes_l@ (0000)
|
|
002A6F90 006f:
|
|
??_C@_0GP@MFMJKDCA@self?9?$DOwrite_requests?$FLself?9?$DOcurre@ (0000)
|
|
002A7000 0036:
|
|
??_C@_0DG@CAGFFOJ@self?9?$DOwrite_requests_pending?$DM?$DNNU@ (0000)
|
|
002A7038 0027:
|
|
??_C@_0CH@BJIGNIOE@self?9?$DOcurrent_write_buffer_index@ (0000)
|
|
002A7060 0020:
|
|
??_C@_0CA@IJMJJMKI@self?9?$DOwrite_requests_pending?$DO?$DN0?$AA@ (0000)
|
|
002A7080 0037:
|
|
??_C@_0DH@MLFGOAED@decompression?5fucked?5up?5with?5err@ (0000)
|
|
002A70B8 0016:
|
|
??_C@_0BG@HEJBEIKN@self?9?$DOcurrent_request?$AA@ (0000)
|
|
002A70D0 0027:
|
|
??_C@_0CH@HCGDPEBO@zlib_stream?9?$DOavail_in?$DN?$DNFILE_BLOC@ (0000)
|
|
002A70F8 0023:
|
|
??_C@_0CD@IMPCPEEA@?$CBself?9?$DOcurrent_read_sequence_cou@ (0000)
|
|
002A711C 0017:
|
|
??_C@_0BH@DHIODLEF@?$CBself?9?$DOcurrent_request?$AA@ (0000)
|
|
002A7138 0075:
|
|
??_C@_0HF@HFIKFPMB@any_bit_vector_flag_set?$CIself?9?$DOov@ (0000)
|
|
002A71B0 001d:
|
|
??_C@_0BN@OOGFMPNB@timeout?5for?5asynchronous?5i?1o?$AA@ (0000)
|
|
002A71D0 0013:
|
|
??_C@_0BD@OOCFHNP@cache?5decompressed?$AA@ (0000)
|
|
002A71E4 0013:
|
|
??_C@_0BD@KBCBBGOA@freq?4u?4HighPart?$DN?$DN0?$AA@ (0000)
|
|
00316838 0008:
|
|
_data_00316838 (0000)
|
|
004CD330 0cc1:
|
|
_bss_004cd330 (0000)
|
|
_decompressor_print_timing (0cc0)
|
|
*/
|
|
|
|
/* ---------- headers */
|
|
|
|
#include "cseries/cseries.h"
|
|
#include "cseries/errors.h"
|
|
#include "cache/cache_files.h"
|
|
#include "cache/cache_files_decompress_windows.h"
|
|
#include "memory/zlib/zlib.h"
|
|
|
|
#include <xtl.h>
|
|
|
|
/* ---------- constants */
|
|
|
|
enum
|
|
{
|
|
FILE_BLOCK_SIZE = 0x20000,
|
|
|
|
NUMBER_OF_READ_BUFFERS = 8,
|
|
NUMBER_OF_WRITE_BUFFERS = 1,
|
|
|
|
_read_buffer_base = 0,
|
|
_raw_read_offset = NUMBER_OF_READ_BUFFERS,
|
|
_write_buffer_base,
|
|
_raw_write_offset = _write_buffer_base + NUMBER_OF_WRITE_BUFFERS,
|
|
NUMBER_OF_OVERLAPPED_STRUCTURES,
|
|
|
|
READ_BUFFER_SIZE = FILE_BLOCK_SIZE,
|
|
WRITE_BUFFER_SIZE = 0x400000,
|
|
ZLIB_BUFFER_SIZE = 0x12000,
|
|
|
|
TOTAL_BUFFER_SIZE =
|
|
NUMBER_OF_READ_BUFFERS * READ_BUFFER_SIZE +
|
|
NUMBER_OF_WRITE_BUFFERS * WRITE_BUFFER_SIZE +
|
|
ZLIB_BUFFER_SIZE,
|
|
|
|
DECOMPRESSOR_MESSAGE_BUFFER_SIZE = 256,
|
|
|
|
CACHE_COPY_THREAD_STACK_SIZE = 0x4000,
|
|
};
|
|
|
|
enum
|
|
{
|
|
_copy_write_failed_bit,
|
|
_copy_read_failed_bit,
|
|
_copy_bad_file_bit,
|
|
NUMBER_OF_COPY_FLAGS,
|
|
|
|
ALL_COPY_FAILURE_FLAGS =
|
|
FLAG(_copy_write_failed_bit) | FLAG(_copy_read_failed_bit) | FLAG(_copy_bad_file_bit)
|
|
};
|
|
|
|
/* timer 0 is never printed; it brackets the copy thread's read-data + zlib setup */
|
|
enum decompressor_timer
|
|
{
|
|
_decompressor_timer_setup,
|
|
_decompressor_timer_read_file,
|
|
_decompressor_timer_write_file,
|
|
_decompressor_timer_zlib,
|
|
_decompressor_timer_zlib_during_write_file,
|
|
_decompressor_timer_thread_blocked,
|
|
_decompressor_timer_thread_blocked_on_read,
|
|
_decompressor_timer_thread_blocked_on_write,
|
|
_decompressor_timer_copying,
|
|
NUMBER_OF_DECOMPRESSOR_TIMERS
|
|
};
|
|
|
|
/* ---------- macros */
|
|
|
|
/* ---------- structures */
|
|
|
|
struct cache_file_header
|
|
{
|
|
unsigned long header_signature;
|
|
long version;
|
|
long size;
|
|
byte reservedC[4];
|
|
long tag_data_offset;
|
|
long tag_data_size;
|
|
byte reserved18[8];
|
|
char name[0x20];
|
|
char build[0x20];
|
|
byte reserved60[4];
|
|
unsigned long checksum;
|
|
byte reserved68[0x794];
|
|
unsigned long footer_signature;
|
|
};
|
|
|
|
struct cache_copy_read_request
|
|
{
|
|
short read_sequence_index;
|
|
};
|
|
|
|
struct cache_copy_write_request
|
|
{
|
|
short write_sequence_index;
|
|
};
|
|
|
|
struct simple_decompressor_definition
|
|
{
|
|
char src_name[260];
|
|
struct cache_file_header header;
|
|
volatile unsigned long flags;
|
|
z_stream zlib_stream;
|
|
byte *zlib_buffer;
|
|
long zlib_buffer_size;
|
|
byte *next_allocation;
|
|
HANDLE copy_start_event;
|
|
HANDLE copy_stop_event;
|
|
HANDLE copy_complete_event;
|
|
HANDLE progress_update_event;
|
|
HANDLE copy_thread;
|
|
void *allocated_buffer;
|
|
void *read_buffers[NUMBER_OF_READ_BUFFERS];
|
|
void *write_buffers[NUMBER_OF_WRITE_BUFFERS];
|
|
boolean blocking;
|
|
byte pad0[3];
|
|
HANDLE destination_file;
|
|
HANDLE source_file;
|
|
long overlapped_in_use_flags[BIT_VECTOR_SIZE_IN_LONGS(NUMBER_OF_OVERLAPPED_STRUCTURES)];
|
|
long overlapped_completed_flags[BIT_VECTOR_SIZE_IN_LONGS(NUMBER_OF_OVERLAPPED_STRUCTURES)];
|
|
OVERLAPPED overlapped[NUMBER_OF_OVERLAPPED_STRUCTURES];
|
|
struct cache_copy_read_request read_requests[NUMBER_OF_READ_BUFFERS];
|
|
struct cache_copy_write_request write_requests[NUMBER_OF_WRITE_BUFFERS];
|
|
byte pad1[2];
|
|
long read_file_size;
|
|
long async_read_bytes_left;
|
|
long read_bytes_left;
|
|
long async_write_bytes_left;
|
|
long write_bytes_left;
|
|
volatile real read_progress;
|
|
long current_write_offset;
|
|
long current_read_offset;
|
|
struct cache_copy_read_request *current_request;
|
|
struct cache_copy_write_request *current_write_request;
|
|
long write_requests_pending;
|
|
short next_read_sequence_index;
|
|
short current_read_sequence_index;
|
|
short current_write_buffer_index;
|
|
short current_write_sequence_index;
|
|
short next_write_sequence_index;
|
|
short current_read_sequence_count;
|
|
byte pad2[4];
|
|
LARGE_INTEGER overlapped_timer_starts[NUMBER_OF_OVERLAPPED_STRUCTURES];
|
|
byte pad3[0x30];
|
|
};
|
|
|
|
struct decompressor_runtime_globals
|
|
{
|
|
char message[DECOMPRESSOR_MESSAGE_BUFFER_SIZE];
|
|
long times[NUMBER_OF_DECOMPRESSOR_TIMERS];
|
|
LARGE_INTEGER timer_starts[NUMBER_OF_DECOMPRESSOR_TIMERS];
|
|
struct simple_decompressor_definition self;
|
|
};
|
|
|
|
typedef char verify_cache_file_header_size[
|
|
sizeof(struct cache_file_header) == 0x800 ? 1 : -1];
|
|
typedef char verify_simple_decompressor_zlib_stream_offset[
|
|
offsetof(struct simple_decompressor_definition, zlib_stream) == 0x908 ? 1 : -1];
|
|
typedef char verify_simple_decompressor_copy_stop_event_offset[
|
|
offsetof(struct simple_decompressor_definition, copy_stop_event) == 0x950 ? 1 : -1];
|
|
typedef char verify_simple_decompressor_copy_complete_event_offset[
|
|
offsetof(struct simple_decompressor_definition, copy_complete_event) == 0x954 ? 1 : -1];
|
|
typedef char verify_simple_decompressor_copy_thread_offset[
|
|
offsetof(struct simple_decompressor_definition, copy_thread) == 0x95C ? 1 : -1];
|
|
typedef char verify_simple_decompressor_blocking_offset[
|
|
offsetof(struct simple_decompressor_definition, blocking) == 0x988 ? 1 : -1];
|
|
typedef char verify_simple_decompressor_overlapped_offset[
|
|
offsetof(struct simple_decompressor_definition, overlapped) == 0x99C ? 1 : -1];
|
|
typedef char verify_simple_decompressor_read_requests_offset[
|
|
offsetof(struct simple_decompressor_definition, read_requests) == 0xA78 ? 1 : -1];
|
|
typedef char verify_simple_decompressor_read_progress_offset[
|
|
offsetof(struct simple_decompressor_definition, read_progress) == 0xAA0 ? 1 : -1];
|
|
typedef char verify_simple_decompressor_current_request_offset[
|
|
offsetof(struct simple_decompressor_definition, current_request) == 0xAAC ? 1 : -1];
|
|
typedef char verify_simple_decompressor_overlapped_timers_offset[
|
|
offsetof(struct simple_decompressor_definition, overlapped_timer_starts) == 0xAC8 ? 1 : -1];
|
|
typedef char verify_simple_decompressor_size[
|
|
sizeof(struct simple_decompressor_definition) == 0xB50 ? 1 : -1];
|
|
typedef char verify_decompressor_runtime_globals_times_offset[
|
|
offsetof(struct decompressor_runtime_globals, times) == 0x100 ? 1 : -1];
|
|
typedef char verify_decompressor_runtime_globals_timer_starts_offset[
|
|
offsetof(struct decompressor_runtime_globals, timer_starts) == 0x128 ? 1 : -1];
|
|
typedef char verify_decompressor_runtime_globals_self_offset[
|
|
offsetof(struct decompressor_runtime_globals, self) == 0x170 ? 1 : -1];
|
|
typedef char verify_decompressor_runtime_globals_size[
|
|
sizeof(struct decompressor_runtime_globals) == 0xCC0 ? 1 : -1];
|
|
|
|
/* ---------- prototypes */
|
|
|
|
static void cache_copy_print_timing(
|
|
void);
|
|
static unsigned long cache_copy_get_flags(
|
|
void);
|
|
static voidpf cache_copy_compressed_alloc(
|
|
voidpf opaque,
|
|
uInt items,
|
|
uInt size);
|
|
static void cache_copy_compressed_free(
|
|
voidpf opaque,
|
|
voidpf address);
|
|
static boolean any_bit_vector_flag_set(
|
|
long *bit_vector,
|
|
long size_in_longs);
|
|
static void decompressor_timer_start(
|
|
long timer_index);
|
|
static void decompressor_timer_stop(
|
|
long timer_index);
|
|
static void decompressor_reset_timing(
|
|
void);
|
|
static boolean cache_copy_stop_requested(
|
|
void);
|
|
static void cache_copy_yield(
|
|
void);
|
|
static void cache_copy_set_flag(
|
|
short flag);
|
|
static long cache_copy_read_buffer_size(
|
|
void);
|
|
static long cache_copy_write_buffer_size(
|
|
short write_buffer_index);
|
|
static void *cache_copy_get_read_buffer(
|
|
struct simple_decompressor_definition *self,
|
|
struct cache_copy_read_request *request);
|
|
static void *cache_copy_get_write_buffer(
|
|
struct simple_decompressor_definition *self,
|
|
short write_buffer_index);
|
|
static void cache_copy_initialize_zlib(
|
|
struct simple_decompressor_definition *self);
|
|
static void cache_copy_dispose_zlib(
|
|
struct simple_decompressor_definition *self);
|
|
static void cache_copy_initialize_read_buffers(
|
|
struct simple_decompressor_definition *self);
|
|
static void cache_copy_initialize_file_data(
|
|
struct simple_decompressor_definition *self);
|
|
static void cache_copy_block_on_raw_read(
|
|
struct simple_decompressor_definition *self);
|
|
static void cache_copy_block_on_raw_write(
|
|
struct simple_decompressor_definition *self);
|
|
static void cache_copy_wait_for_async_io(
|
|
struct simple_decompressor_definition *self);
|
|
static void cache_copy_issue_read(
|
|
struct simple_decompressor_definition *self,
|
|
void *buffer,
|
|
long size,
|
|
long offset,
|
|
short overlapped_index);
|
|
static void cache_copy_issue_write(
|
|
struct simple_decompressor_definition *self,
|
|
void *buffer,
|
|
long size,
|
|
long offset,
|
|
short write_buffer_index);
|
|
static void cache_copy_issue_read_raw(
|
|
struct simple_decompressor_definition *self,
|
|
void *buffer,
|
|
long size,
|
|
long offset);
|
|
static void cache_copy_issue_write_raw(
|
|
struct simple_decompressor_definition *self,
|
|
void *buffer,
|
|
long size,
|
|
long offset);
|
|
static void cache_copy_issue_read_internal(
|
|
struct simple_decompressor_definition *self,
|
|
struct cache_copy_read_request *request,
|
|
short read_buffer_index);
|
|
static void cache_copy_issue_read_request(
|
|
struct simple_decompressor_definition *self,
|
|
struct cache_copy_read_request *request);
|
|
static void cache_copy_issue_read_by_index(
|
|
struct simple_decompressor_definition *self,
|
|
short read_buffer_index);
|
|
static void cache_copy_release_read_request(
|
|
struct simple_decompressor_definition *self,
|
|
struct cache_copy_read_request *request);
|
|
static void cache_copy_issue_write_internal(
|
|
struct simple_decompressor_definition *self,
|
|
short write_buffer_index);
|
|
static void cache_copy_update_write_buffers(
|
|
struct simple_decompressor_definition *self);
|
|
static void cache_copy_initialize_read_data(
|
|
struct simple_decompressor_definition *self);
|
|
static void cache_copy_issue_initial_reads(
|
|
struct simple_decompressor_definition *self);
|
|
static void cache_copy_run_decompression(
|
|
struct simple_decompressor_definition *self);
|
|
static unsigned long __stdcall simple_cache_copy_thread(
|
|
void *parameter);
|
|
void CALLBACK cache_copy_FileIOCompletionRoutine(
|
|
unsigned long error_code,
|
|
unsigned long bytes_transferred,
|
|
OVERLAPPED *overlapped);
|
|
|
|
/* ---------- globals */
|
|
|
|
static struct decompressor_runtime_globals decompressor_globals;
|
|
static struct simple_decompressor_definition *global_self = &decompressor_globals.self;
|
|
static long performance_frequency = 1;
|
|
/* January PDB: public, module 33 .bss+0xcc0; explicit zero avoids COMMON. */
|
|
boolean decompressor_print_timing = FALSE;
|
|
|
|
/* ---------- code */
|
|
|
|
static boolean cache_copy_stop_requested(
|
|
void)
|
|
{
|
|
return WaitForSingleObject(global_self->copy_stop_event, 0) == 0;
|
|
}
|
|
|
|
long cache_copy_buffer_size(
|
|
boolean blocking)
|
|
{
|
|
cache_copy_set_priority(blocking);
|
|
|
|
return TOTAL_BUFFER_SIZE;
|
|
}
|
|
|
|
void cache_copy_set_priority(
|
|
boolean blocking)
|
|
{
|
|
struct simple_decompressor_definition *self = global_self;
|
|
|
|
self->blocking = blocking;
|
|
if (blocking)
|
|
SetThreadPriority(self->copy_thread, THREAD_PRIORITY_ABOVE_NORMAL);
|
|
else
|
|
SetThreadPriority(self->copy_thread, THREAD_PRIORITY_NORMAL);
|
|
|
|
return;
|
|
}
|
|
|
|
boolean cache_copy_compressed_file_complete(
|
|
void)
|
|
{
|
|
return WaitForSingleObject(global_self->copy_complete_event, 0) == 0;
|
|
}
|
|
|
|
void cache_copy_begin(
|
|
void *buffer,
|
|
long size,
|
|
HANDLE destination_file,
|
|
long destination_file_size,
|
|
const char *source_file_name)
|
|
{
|
|
if (WaitForSingleObject(global_self->copy_complete_event, 0) == 0)
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
524,
|
|
source_file_name);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
525,
|
|
destination_file!=INVALID_HANDLE_VALUE);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
526,
|
|
buffer);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
527,
|
|
size>= TOTAL_BUFFER_SIZE);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
528,
|
|
destination_file_size==GetFileSize(destination_file, NULL));
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
530,
|
|
global_self->copy_complete_event);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
531,
|
|
global_self->copy_stop_event);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
532,
|
|
global_self->copy_start_event);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
533,
|
|
global_self->progress_update_event);
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
535,
|
|
global_self->copy_thread);
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
537,
|
|
global_self->zlib_stream.zalloc);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
538,
|
|
global_self->zlib_stream.zfree);
|
|
|
|
global_self->flags = 0;
|
|
global_self->allocated_buffer = buffer;
|
|
csstrcpy(global_self->src_name, source_file_name);
|
|
global_self->destination_file = destination_file;
|
|
global_self->read_progress = 0.0f;
|
|
|
|
ResetEvent(global_self->copy_complete_event);
|
|
ResetEvent(global_self->copy_stop_event);
|
|
|
|
csmemset(&global_self->header, 0, sizeof(global_self->header));
|
|
|
|
SetEvent(global_self->copy_start_event);
|
|
}
|
|
else
|
|
{
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
564,
|
|
FALSE,
|
|
"previous copy session did not complete");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void cache_copy_queue_end(
|
|
void)
|
|
{
|
|
if (WaitForSingleObject(global_self->copy_complete_event, 0))
|
|
SetEvent(global_self->copy_stop_event);
|
|
|
|
return;
|
|
}
|
|
|
|
static void cache_copy_initialize_zlib(
|
|
struct simple_decompressor_definition *self)
|
|
{
|
|
self->zlib_stream.next_in = NULL;
|
|
self->zlib_stream.avail_in = 0;
|
|
self->zlib_stream.next_out = NULL;
|
|
self->zlib_stream.avail_out = 0;
|
|
|
|
inflateInit(&self->zlib_stream);
|
|
|
|
return;
|
|
}
|
|
|
|
static void cache_copy_dispose_zlib(
|
|
struct simple_decompressor_definition *self)
|
|
{
|
|
inflateEnd(&self->zlib_stream);
|
|
|
|
self->zlib_stream.next_in = NULL;
|
|
self->zlib_stream.avail_in = 0;
|
|
self->zlib_stream.next_out = NULL;
|
|
self->zlib_stream.avail_out = 0;
|
|
|
|
return;
|
|
}
|
|
|
|
static voidpf cache_copy_compressed_alloc(
|
|
voidpf opaque,
|
|
uInt items,
|
|
uInt size)
|
|
{
|
|
byte *address = global_self->next_allocation;
|
|
|
|
global_self->next_allocation = address + items * size;
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
701,
|
|
global_self->next_allocation-global_self->zlib_buffer<global_self->zlib_buffer_size);
|
|
|
|
return address;
|
|
}
|
|
|
|
static void cache_copy_compressed_free(
|
|
voidpf opaque,
|
|
voidpf address)
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
710,
|
|
(byte*)address<=global_self->next_allocation);
|
|
global_self->next_allocation = address;
|
|
|
|
return;
|
|
}
|
|
|
|
static void cache_copy_initialize_read_buffers(
|
|
struct simple_decompressor_definition *self)
|
|
{
|
|
byte *address = self->allocated_buffer;
|
|
short read_buffer_index;
|
|
|
|
for (read_buffer_index = 0; read_buffer_index < NUMBER_OF_READ_BUFFERS; read_buffer_index++)
|
|
{
|
|
global_self->read_buffers[read_buffer_index] = address;
|
|
address += cache_copy_read_buffer_size();
|
|
}
|
|
global_self->write_buffers[0] = address;
|
|
|
|
XPhysicalProtect(self->allocated_buffer, TOTAL_BUFFER_SIZE, PAGE_READWRITE);
|
|
csmemset(self->allocated_buffer, 0xfd, TOTAL_BUFFER_SIZE - ZLIB_BUFFER_SIZE);
|
|
XPhysicalProtect(self->allocated_buffer, TOTAL_BUFFER_SIZE - ZLIB_BUFFER_SIZE, PAGE_READONLY);
|
|
|
|
self->zlib_buffer_size = ZLIB_BUFFER_SIZE;
|
|
self->zlib_buffer = (byte *)self->allocated_buffer + TOTAL_BUFFER_SIZE - ZLIB_BUFFER_SIZE;
|
|
self->next_allocation = self->zlib_buffer;
|
|
|
|
csmemset(
|
|
&self->source_file,
|
|
0xfa,
|
|
sizeof(*self) - offsetof(struct simple_decompressor_definition, source_file));
|
|
|
|
return;
|
|
}
|
|
|
|
static void cache_copy_initialize_file_data(
|
|
struct simple_decompressor_definition *self)
|
|
{
|
|
short read_buffer_index;
|
|
short write_buffer_index;
|
|
|
|
self->source_file = CreateFile(
|
|
self->src_name,
|
|
GENERIC_READ,
|
|
0,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED,
|
|
NULL);
|
|
self->read_bytes_left = GetFileSize(self->source_file, NULL);
|
|
self->read_file_size = self->read_bytes_left;
|
|
self->async_read_bytes_left = self->read_bytes_left;
|
|
|
|
csmemset(self->overlapped, 0, sizeof(self->overlapped));
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
964,
|
|
self->read_bytes_left>=sizeof(self->header));
|
|
|
|
csmemset(self->overlapped_in_use_flags, 0, sizeof(self->overlapped_in_use_flags));
|
|
csmemset(self->overlapped_completed_flags, 0, sizeof(self->overlapped_completed_flags));
|
|
|
|
for (read_buffer_index = 0; read_buffer_index < NUMBER_OF_READ_BUFFERS; read_buffer_index++)
|
|
self->read_requests[read_buffer_index].read_sequence_index = NONE;
|
|
for (write_buffer_index = 0; write_buffer_index < NUMBER_OF_WRITE_BUFFERS; write_buffer_index++)
|
|
self->write_requests[write_buffer_index].write_sequence_index = NONE;
|
|
|
|
self->next_read_sequence_index = 0;
|
|
self->current_read_sequence_index = 0;
|
|
self->current_write_sequence_index = 0;
|
|
self->next_write_sequence_index = 0;
|
|
self->write_requests_pending = 0;
|
|
self->current_write_buffer_index = NONE;
|
|
|
|
return;
|
|
}
|
|
|
|
static void cache_copy_block_on_raw_read(
|
|
struct simple_decompressor_definition *self)
|
|
{
|
|
unsigned long wait_result = WaitForSingleObjectEx(self->copy_stop_event, 5000, TRUE);
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1482,
|
|
!BIT_VECTOR_TEST_FLAG(self->overlapped_in_use_flags, _raw_read_offset));
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1483,
|
|
wait_result==WAIT_IO_COMPLETION);
|
|
|
|
BIT_VECTOR_SET_FLAG(self->overlapped_in_use_flags, _raw_read_offset, FALSE);
|
|
|
|
return;
|
|
}
|
|
|
|
static void cache_copy_block_on_raw_write(
|
|
struct simple_decompressor_definition *self)
|
|
{
|
|
unsigned long wait_result;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1494,
|
|
BIT_VECTOR_TEST_FLAG(self->overlapped_in_use_flags, _raw_write_offset));
|
|
|
|
wait_result = WaitForSingleObjectEx(self->copy_stop_event, 5000, TRUE);
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1498,
|
|
!BIT_VECTOR_TEST_FLAG(self->overlapped_in_use_flags, _raw_write_offset));
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1499,
|
|
wait_result==WAIT_IO_COMPLETION);
|
|
|
|
BIT_VECTOR_SET_FLAG(self->overlapped_in_use_flags, _raw_write_offset, FALSE);
|
|
|
|
return;
|
|
}
|
|
|
|
struct cache_copy_read_request *acquire_read_request(
|
|
struct simple_decompressor_definition *self,
|
|
short read_sequence_index)
|
|
{
|
|
struct cache_copy_read_request *request = NULL;
|
|
short read_buffer_index;
|
|
|
|
for (read_buffer_index = 0; read_buffer_index < NUMBER_OF_READ_BUFFERS; read_buffer_index++)
|
|
{
|
|
if (self->read_requests[read_buffer_index].read_sequence_index == read_sequence_index &&
|
|
BIT_VECTOR_TEST_FLAG(self->overlapped_completed_flags, _read_buffer_base + read_buffer_index))
|
|
{
|
|
request = &self->read_requests[read_buffer_index];
|
|
XPhysicalProtect(
|
|
self->read_buffers[read_buffer_index],
|
|
FILE_BLOCK_SIZE,
|
|
PAGE_READONLY);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return request;
|
|
}
|
|
|
|
static long cache_copy_read_buffer_size(
|
|
void)
|
|
{
|
|
return READ_BUFFER_SIZE;
|
|
}
|
|
|
|
static void *cache_copy_get_read_buffer(
|
|
struct simple_decompressor_definition *self,
|
|
struct cache_copy_read_request *request)
|
|
{
|
|
short read_buffer_index = (short)(request - self->read_requests);
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1606,
|
|
read_buffer_index>=0 && read_buffer_index<NUMBER_OF_READ_BUFFERS);
|
|
|
|
return self->read_buffers[read_buffer_index];
|
|
}
|
|
|
|
static void *cache_copy_get_write_buffer(
|
|
struct simple_decompressor_definition *self,
|
|
short write_buffer_index)
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1633,
|
|
write_buffer_index>=0 && write_buffer_index<NUMBER_OF_WRITE_BUFFERS);
|
|
|
|
return self->write_buffers[write_buffer_index];
|
|
}
|
|
|
|
static long cache_copy_write_buffer_size(
|
|
short write_buffer_index)
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1642,
|
|
write_buffer_index>=0 && write_buffer_index<NUMBER_OF_WRITE_BUFFERS);
|
|
|
|
return WRITE_BUFFER_SIZE;
|
|
}
|
|
|
|
static boolean any_bit_vector_flag_set(
|
|
long *bit_vector,
|
|
long size_in_longs)
|
|
{
|
|
boolean flag_set = FALSE;
|
|
short index;
|
|
|
|
for (index = 0; index < size_in_longs; index++)
|
|
flag_set = flag_set || bit_vector[index];
|
|
|
|
return flag_set;
|
|
}
|
|
|
|
static void cache_copy_wait_for_async_io(
|
|
struct simple_decompressor_definition *self)
|
|
{
|
|
short retry_count = NUMBER_OF_OVERLAPPED_STRUCTURES;
|
|
|
|
while (any_bit_vector_flag_set(
|
|
self->overlapped_in_use_flags,
|
|
BIT_VECTOR_SIZE_IN_LONGS(NUMBER_OF_OVERLAPPED_STRUCTURES)) &&
|
|
retry_count--)
|
|
{
|
|
unsigned long wait_result = SleepEx(5000, TRUE);
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1695,
|
|
wait_result==WAIT_IO_COMPLETION);
|
|
}
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1699,
|
|
!any_bit_vector_flag_set(self->overlapped_in_use_flags, BIT_VECTOR_SIZE_IN_LONGS(NUMBER_OF_OVERLAPPED_STRUCTURES)));
|
|
|
|
csmemset(self->overlapped_completed_flags, 0, sizeof(self->overlapped_completed_flags));
|
|
|
|
return;
|
|
}
|
|
|
|
static void cache_copy_set_flag(
|
|
short flag)
|
|
{
|
|
SET_FLAG(global_self->flags, flag, TRUE);
|
|
|
|
return;
|
|
}
|
|
|
|
static unsigned long cache_copy_get_flags(
|
|
void)
|
|
{
|
|
return global_self->flags;
|
|
}
|
|
|
|
static void decompressor_reset_timing(
|
|
void)
|
|
{
|
|
csmemset(decompressor_globals.times, 0, sizeof(decompressor_globals.times));
|
|
|
|
return;
|
|
}
|
|
|
|
static void decompressor_timer_start(
|
|
long timer_index)
|
|
{
|
|
QueryPerformanceCounter(&decompressor_globals.timer_starts[timer_index]);
|
|
|
|
return;
|
|
}
|
|
|
|
static void decompressor_timer_stop(
|
|
long timer_index)
|
|
{
|
|
LARGE_INTEGER now;
|
|
|
|
QueryPerformanceCounter(&now);
|
|
decompressor_globals.times[timer_index] +=
|
|
now.u.LowPart - decompressor_globals.timer_starts[timer_index].u.LowPart;
|
|
|
|
return;
|
|
}
|
|
|
|
static void cache_copy_print_timing(
|
|
void)
|
|
{
|
|
error(_error_silent, "Timing for copying last cache file:");
|
|
error(_error_silent, " Total read file time: %.3f",
|
|
(double)decompressor_globals.times[_decompressor_timer_read_file] / performance_frequency);
|
|
error(_error_silent, " Total write file time: %.3f",
|
|
(double)decompressor_globals.times[_decompressor_timer_write_file] / performance_frequency);
|
|
error(_error_silent, " Total zlib time: %.3f",
|
|
(double)decompressor_globals.times[_decompressor_timer_zlib] / performance_frequency);
|
|
error(_error_silent, " Total zlib during write file time: %.3f",
|
|
(double)decompressor_globals.times[_decompressor_timer_zlib_during_write_file] / performance_frequency);
|
|
error(_error_silent, " Total thread blocked time: %.3f",
|
|
(double)decompressor_globals.times[_decompressor_timer_thread_blocked] / performance_frequency);
|
|
error(_error_silent, " Total thread blocked on read time: %.3f",
|
|
(double)decompressor_globals.times[_decompressor_timer_thread_blocked_on_read] / performance_frequency);
|
|
error(_error_silent, " Total thread blocked on write time: %.3f",
|
|
(double)decompressor_globals.times[_decompressor_timer_thread_blocked_on_write] / performance_frequency);
|
|
error(_error_silent, " Total copying time: %.3f",
|
|
(double)decompressor_globals.times[_decompressor_timer_copying] / performance_frequency);
|
|
|
|
return;
|
|
}
|
|
|
|
static void cache_copy_yield(
|
|
void)
|
|
{
|
|
if (!global_self->blocking)
|
|
SwitchToThread();
|
|
|
|
return;
|
|
}
|
|
|
|
short cache_copy_get_status(
|
|
real *progress)
|
|
{
|
|
unsigned long flags = cache_copy_get_flags();
|
|
short status = 0;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
574,
|
|
progress);
|
|
|
|
if (global_self->blocking)
|
|
Sleep(16);
|
|
|
|
if (!flags && global_self->copy_thread)
|
|
{
|
|
if (global_self->header.size > 0)
|
|
{
|
|
status = (short)((WaitForSingleObject(global_self->copy_complete_event, 0) == 0) +
|
|
_cache_copy_in_progress);
|
|
if (WaitForSingleObject(global_self->progress_update_event, 0) == 0)
|
|
{
|
|
real read_progress;
|
|
|
|
if (global_self->read_progress < 0.0f)
|
|
{
|
|
read_progress = 0.0f;
|
|
}
|
|
else if (global_self->read_progress > 1.0f)
|
|
{
|
|
read_progress = 1.0f;
|
|
}
|
|
else
|
|
{
|
|
read_progress = global_self->read_progress;
|
|
}
|
|
|
|
*progress = read_progress;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*progress = 0.0f;
|
|
status = _cache_copy_in_progress;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (TEST_FLAG(flags, _copy_read_failed_bit))
|
|
status = _cache_copy_read_failure;
|
|
else if (TEST_FLAG(flags, _copy_bad_file_bit))
|
|
status = _cache_copy_bad_file_failure;
|
|
else if (TEST_FLAG(flags, _copy_write_failed_bit))
|
|
status = _cache_copy_write_failure;
|
|
else
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
626,
|
|
!"unreachable");
|
|
*progress = 0.0f;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
void cache_copy_end(
|
|
void)
|
|
{
|
|
if (WaitForSingleObject(global_self->copy_complete_event, 0))
|
|
{
|
|
SetEvent(global_self->copy_stop_event);
|
|
WaitForSingleObject(global_self->copy_complete_event, INFINITE);
|
|
}
|
|
|
|
if (decompressor_print_timing)
|
|
cache_copy_print_timing();
|
|
|
|
return;
|
|
}
|
|
|
|
void CALLBACK cache_copy_FileIOCompletionRoutine(
|
|
unsigned long error_code,
|
|
unsigned long bytes_transferred,
|
|
OVERLAPPED *overlapped)
|
|
{
|
|
long *in_use_flags = global_self->overlapped_in_use_flags;
|
|
long *completed_flags = global_self->overlapped_completed_flags;
|
|
long overlapped_index = overlapped - global_self->overlapped;
|
|
|
|
if (!error_code)
|
|
{
|
|
if (overlapped_index >= 0 && overlapped_index < NUMBER_OF_OVERLAPPED_STRUCTURES)
|
|
{
|
|
LARGE_INTEGER now;
|
|
|
|
QueryPerformanceCounter(&now);
|
|
BIT_VECTOR_SET_FLAG(in_use_flags, overlapped_index, FALSE);
|
|
BIT_VECTOR_SET_FLAG(completed_flags, overlapped_index, TRUE);
|
|
}
|
|
|
|
if (overlapped_index >= _read_buffer_base &&
|
|
overlapped_index <= _read_buffer_base + NUMBER_OF_READ_BUFFERS - 1)
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1291,
|
|
global_self->async_read_bytes_left>0);
|
|
|
|
global_self->async_read_bytes_left -= bytes_transferred;
|
|
|
|
ResetEvent(global_self->progress_update_event);
|
|
global_self->read_progress =
|
|
(real)(global_self->header.size - global_self->async_read_bytes_left) /
|
|
global_self->header.size;
|
|
SetEvent(global_self->progress_update_event);
|
|
}
|
|
else if (overlapped_index >= _write_buffer_base &&
|
|
overlapped_index <= _write_buffer_base + NUMBER_OF_WRITE_BUFFERS - 1)
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1300,
|
|
global_self->async_write_bytes_left>0);
|
|
|
|
global_self->async_write_bytes_left -= bytes_transferred;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1306,
|
|
FALSE,
|
|
csprintf(
|
|
decompressor_globals.message,
|
|
"async i/o finished with error code %d",
|
|
error_code));
|
|
|
|
if (overlapped_index >= _write_buffer_base &&
|
|
overlapped_index <= _write_buffer_base + NUMBER_OF_WRITE_BUFFERS - 1)
|
|
cache_copy_set_flag(_copy_write_failed_bit);
|
|
else
|
|
cache_copy_set_flag(_copy_read_failed_bit);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static void cache_copy_issue_read(
|
|
struct simple_decompressor_definition *self,
|
|
void *buffer,
|
|
long size,
|
|
long offset,
|
|
short overlapped_index)
|
|
{
|
|
HANDLE file;
|
|
OVERLAPPED *overlapped;
|
|
long error;
|
|
BOOL issued;
|
|
|
|
decompressor_timer_start(_decompressor_timer_read_file);
|
|
|
|
file = self->source_file;
|
|
overlapped = &self->overlapped[overlapped_index];
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1334,
|
|
!BIT_VECTOR_TEST_FLAG(self->overlapped_in_use_flags, overlapped_index));
|
|
BIT_VECTOR_SET_FLAG(self->overlapped_in_use_flags, overlapped_index, TRUE);
|
|
|
|
overlapped->hEvent = (HANDLE)overlapped_index;
|
|
overlapped->Offset = offset;
|
|
overlapped->OffsetHigh = 0;
|
|
|
|
QueryPerformanceCounter(&self->overlapped_timer_starts[overlapped_index]);
|
|
|
|
do
|
|
{
|
|
SleepEx(0, TRUE);
|
|
SetLastError(ERROR_SUCCESS);
|
|
issued = ReadFileEx(file, buffer, size, overlapped, cache_copy_FileIOCompletionRoutine);
|
|
error = GetLastError();
|
|
}
|
|
while (!issued &&
|
|
(error == ERROR_INVALID_USER_BUFFER || error == ERROR_NOT_ENOUGH_MEMORY ||
|
|
error == ERROR_NO_SYSTEM_RESOURCES));
|
|
|
|
if (!issued)
|
|
{
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1369,
|
|
FALSE,
|
|
"couldn't issue an asynchronous read");
|
|
cache_copy_set_flag(_copy_read_failed_bit);
|
|
}
|
|
|
|
decompressor_timer_stop(_decompressor_timer_read_file);
|
|
|
|
return;
|
|
}
|
|
|
|
static void cache_copy_issue_write(
|
|
struct simple_decompressor_definition *self,
|
|
void *buffer,
|
|
long size,
|
|
long offset,
|
|
short write_buffer_index)
|
|
{
|
|
long overlapped_index;
|
|
HANDLE file;
|
|
OVERLAPPED *overlapped;
|
|
long error;
|
|
BOOL issued;
|
|
|
|
decompressor_timer_start(_decompressor_timer_write_file);
|
|
|
|
file = self->destination_file;
|
|
overlapped_index = _write_buffer_base + write_buffer_index;
|
|
overlapped = &self->overlapped[overlapped_index];
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1411,
|
|
!BIT_VECTOR_TEST_FLAG(self->overlapped_in_use_flags, overlapped_index));
|
|
BIT_VECTOR_SET_FLAG(self->overlapped_in_use_flags, overlapped_index, TRUE);
|
|
|
|
overlapped->hEvent = (HANDLE)overlapped_index;
|
|
overlapped->Offset = offset;
|
|
overlapped->OffsetHigh = 0;
|
|
|
|
QueryPerformanceCounter(&self->overlapped_timer_starts[overlapped_index]);
|
|
|
|
do
|
|
{
|
|
SleepEx(0, TRUE);
|
|
SetLastError(ERROR_SUCCESS);
|
|
issued = WriteFileEx(file, buffer, size, overlapped, cache_copy_FileIOCompletionRoutine);
|
|
error = GetLastError();
|
|
}
|
|
while (!issued &&
|
|
(error == ERROR_INVALID_USER_BUFFER || error == ERROR_NOT_ENOUGH_MEMORY ||
|
|
error == ERROR_NO_SYSTEM_RESOURCES));
|
|
|
|
if (!issued)
|
|
{
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1441,
|
|
FALSE,
|
|
"couldn't issue an asynchronous write");
|
|
cache_copy_set_flag(_copy_write_failed_bit);
|
|
}
|
|
|
|
decompressor_timer_stop(_decompressor_timer_write_file);
|
|
|
|
return;
|
|
}
|
|
|
|
static void cache_copy_issue_read_raw(
|
|
struct simple_decompressor_definition *self,
|
|
void *buffer,
|
|
long size,
|
|
long offset)
|
|
{
|
|
cache_copy_issue_read(self, buffer, size, offset, _raw_read_offset);
|
|
|
|
return;
|
|
}
|
|
|
|
static void cache_copy_issue_write_raw(
|
|
struct simple_decompressor_definition *self,
|
|
void *buffer,
|
|
long size,
|
|
long offset)
|
|
{
|
|
cache_copy_issue_write(self, buffer, size, offset, NUMBER_OF_WRITE_BUFFERS);
|
|
|
|
return;
|
|
}
|
|
|
|
static void cache_copy_issue_read_internal(
|
|
struct simple_decompressor_definition *self,
|
|
struct cache_copy_read_request *request,
|
|
short read_buffer_index)
|
|
{
|
|
void *buffer = cache_copy_get_read_buffer(self, request);
|
|
long size = self->read_bytes_left < FILE_BLOCK_SIZE ? self->read_bytes_left : FILE_BLOCK_SIZE;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1516,
|
|
read_buffer_index>=0 && read_buffer_index<NUMBER_OF_READ_BUFFERS);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1517,
|
|
request->read_sequence_index==NONE);
|
|
|
|
request->read_sequence_index = self->next_read_sequence_index;
|
|
|
|
XPhysicalProtect(buffer, size, PAGE_READWRITE);
|
|
cache_copy_issue_read(self, buffer, size, self->current_read_offset, read_buffer_index);
|
|
|
|
self->next_read_sequence_index++;
|
|
self->read_bytes_left -= size;
|
|
self->current_read_offset += size;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1537,
|
|
self->current_read_offset<=self->read_file_size);
|
|
|
|
return;
|
|
}
|
|
|
|
static void cache_copy_issue_read_request(
|
|
struct simple_decompressor_definition *self,
|
|
struct cache_copy_read_request *request)
|
|
{
|
|
cache_copy_issue_read_internal(self, request, (short)(request - self->read_requests));
|
|
|
|
return;
|
|
}
|
|
|
|
static void cache_copy_issue_read_by_index(
|
|
struct simple_decompressor_definition *self,
|
|
short read_buffer_index)
|
|
{
|
|
struct cache_copy_read_request *request = &self->read_requests[read_buffer_index];
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1561,
|
|
read_buffer_index>=0 && read_buffer_index<NUMBER_OF_READ_BUFFERS);
|
|
|
|
cache_copy_issue_read_internal(self, request, read_buffer_index);
|
|
|
|
return;
|
|
}
|
|
|
|
static void cache_copy_release_read_request(
|
|
struct simple_decompressor_definition *self,
|
|
struct cache_copy_read_request *request)
|
|
{
|
|
short read_buffer_index = (short)(request - self->read_requests);
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1618,
|
|
read_buffer_index>=0 && read_buffer_index<NUMBER_OF_READ_BUFFERS);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1619,
|
|
BIT_VECTOR_TEST_FLAG(self->overlapped_completed_flags, _read_buffer_base+read_buffer_index));
|
|
|
|
BIT_VECTOR_SET_FLAG(
|
|
self->overlapped_completed_flags,
|
|
_read_buffer_base + read_buffer_index,
|
|
FALSE);
|
|
request->read_sequence_index = NONE;
|
|
|
|
cache_copy_issue_read_request(self, request);
|
|
|
|
return;
|
|
}
|
|
|
|
static void cache_copy_issue_write_internal(
|
|
struct simple_decompressor_definition *self,
|
|
short write_buffer_index)
|
|
{
|
|
void *buffer = cache_copy_get_write_buffer(self, write_buffer_index);
|
|
long size = self->write_bytes_left < cache_copy_write_buffer_size(write_buffer_index) ?
|
|
self->write_bytes_left :
|
|
cache_copy_write_buffer_size(write_buffer_index);
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1654,
|
|
write_buffer_index>=0 && write_buffer_index<NUMBER_OF_WRITE_BUFFERS);
|
|
|
|
XPhysicalProtect(buffer, WRITE_BUFFER_SIZE, PAGE_READONLY);
|
|
|
|
cache_copy_issue_write(
|
|
self,
|
|
cache_copy_get_write_buffer(self, write_buffer_index),
|
|
size,
|
|
self->current_write_offset,
|
|
write_buffer_index);
|
|
|
|
self->current_write_offset += size;
|
|
self->write_bytes_left -= size;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1666,
|
|
self->current_write_offset<=self->header.size);
|
|
|
|
return;
|
|
}
|
|
|
|
static void cache_copy_initialize_read_data(
|
|
struct simple_decompressor_definition *self)
|
|
{
|
|
self->async_write_bytes_left = 0;
|
|
csmemset(&self->header, 0, sizeof(self->header));
|
|
|
|
cache_copy_issue_write_raw(self, &self->header, sizeof(self->header), 0);
|
|
cache_copy_block_on_raw_write(self);
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1003,
|
|
global_self->async_write_bytes_left==0);
|
|
|
|
cache_copy_issue_read_raw(self, &self->header, sizeof(self->header), 0);
|
|
cache_copy_block_on_raw_read(self);
|
|
|
|
cache_file_header_verify(&self->header, "blah", TRUE);
|
|
|
|
self->read_bytes_left -= sizeof(self->header);
|
|
self->current_read_offset = sizeof(self->header);
|
|
self->current_write_offset = sizeof(self->header);
|
|
self->read_progress = 0.0f;
|
|
self->current_request = NULL;
|
|
self->current_read_sequence_count = 0;
|
|
self->current_write_request = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
static void cache_copy_issue_initial_reads(
|
|
struct simple_decompressor_definition *self)
|
|
{
|
|
short overlapped_index;
|
|
|
|
for (overlapped_index = 0; overlapped_index < NUMBER_OF_READ_BUFFERS; overlapped_index++)
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1046,
|
|
!BIT_VECTOR_TEST_FLAG(self->overlapped_in_use_flags, overlapped_index));
|
|
|
|
cache_copy_issue_read_by_index(self, overlapped_index);
|
|
|
|
BIT_VECTOR_SET_FLAG(self->overlapped_in_use_flags, overlapped_index, TRUE);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static void cache_copy_update_write_buffers(
|
|
struct simple_decompressor_definition *self)
|
|
{
|
|
short write_buffer_index;
|
|
|
|
if (self->write_requests_pending > 0 && self->current_write_request)
|
|
{
|
|
for (write_buffer_index = 0; write_buffer_index < NUMBER_OF_WRITE_BUFFERS; write_buffer_index++)
|
|
{
|
|
if (BIT_VECTOR_TEST_FLAG(self->overlapped_completed_flags, _write_buffer_base + write_buffer_index))
|
|
{
|
|
self->write_requests[write_buffer_index].write_sequence_index = NONE;
|
|
BIT_VECTOR_SET_FLAG(self->overlapped_completed_flags, _write_buffer_base + write_buffer_index, FALSE);
|
|
self->write_requests_pending--;
|
|
self->current_write_request = NULL;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1075,
|
|
self->write_requests_pending>=0);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (self->write_bytes_left &&
|
|
!self->current_write_request &&
|
|
self->write_requests_pending > 0)
|
|
{
|
|
if (self->current_write_buffer_index == NONE ||
|
|
self->write_requests[self->current_write_buffer_index].write_sequence_index >
|
|
self->current_write_sequence_index)
|
|
{
|
|
for (write_buffer_index = 0;
|
|
write_buffer_index < NUMBER_OF_WRITE_BUFFERS;
|
|
write_buffer_index++)
|
|
{
|
|
if (self->current_write_buffer_index != write_buffer_index &&
|
|
self->write_requests[write_buffer_index].write_sequence_index ==
|
|
self->current_write_sequence_index)
|
|
{
|
|
self->current_write_request = &self->write_requests[write_buffer_index];
|
|
cache_copy_issue_write_internal(self, write_buffer_index);
|
|
self->current_write_sequence_index++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (self->current_write_buffer_index == NONE && self->write_requests_pending < 1)
|
|
{
|
|
for (write_buffer_index = 0;
|
|
write_buffer_index < NUMBER_OF_WRITE_BUFFERS;
|
|
write_buffer_index++)
|
|
{
|
|
if (self->write_requests[write_buffer_index].write_sequence_index == NONE)
|
|
{
|
|
self->write_requests[write_buffer_index].write_sequence_index =
|
|
self->next_write_sequence_index;
|
|
self->next_write_sequence_index++;
|
|
self->write_requests_pending++;
|
|
self->current_write_buffer_index = write_buffer_index;
|
|
XPhysicalProtect(
|
|
self->write_buffers[write_buffer_index],
|
|
WRITE_BUFFER_SIZE,
|
|
PAGE_READWRITE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1124,
|
|
self->current_write_buffer_index!=NONE);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1125,
|
|
self->write_requests_pending<=NUMBER_OF_WRITE_BUFFERS);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1126,
|
|
self->write_requests[self->current_write_buffer_index].write_sequence_index+1==self->next_write_sequence_index);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static void cache_copy_run_decompression(
|
|
struct simple_decompressor_definition *self)
|
|
{
|
|
z_stream *zlib_stream = &self->zlib_stream;
|
|
|
|
for (;;)
|
|
{
|
|
long zlib_result;
|
|
|
|
SleepEx(0, TRUE);
|
|
cache_copy_update_write_buffers(self);
|
|
|
|
if (!zlib_stream->avail_in)
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1149,
|
|
!self->current_request);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1150,
|
|
!self->current_read_sequence_count);
|
|
|
|
self->current_request = acquire_read_request(self, self->current_read_sequence_index);
|
|
if (self->current_request)
|
|
{
|
|
zlib_stream->avail_in = FILE_BLOCK_SIZE;
|
|
zlib_stream->next_in = cache_copy_get_read_buffer(self, self->current_request);
|
|
self->current_read_sequence_count = 1;
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1163,
|
|
zlib_stream->avail_in==FILE_BLOCK_SIZE);
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1172,
|
|
self->current_request);
|
|
|
|
if (self->current_write_buffer_index == NONE)
|
|
break;
|
|
|
|
if (!zlib_stream->avail_out)
|
|
{
|
|
zlib_stream->next_out = cache_copy_get_write_buffer(self, self->current_write_buffer_index);
|
|
zlib_stream->avail_out = cache_copy_write_buffer_size(self->current_write_buffer_index);
|
|
}
|
|
|
|
if (!zlib_stream->avail_in || !zlib_stream->avail_out)
|
|
continue;
|
|
|
|
cache_copy_yield();
|
|
|
|
decompressor_timer_start(_decompressor_timer_zlib);
|
|
if (self->write_requests_pending > 1)
|
|
decompressor_timer_start(_decompressor_timer_zlib_during_write_file);
|
|
|
|
zlib_result = inflate(zlib_stream, 0);
|
|
|
|
decompressor_timer_stop(_decompressor_timer_zlib);
|
|
if (self->write_requests_pending > 1)
|
|
decompressor_timer_stop(_decompressor_timer_zlib_during_write_file);
|
|
|
|
if (zlib_result == Z_OK || zlib_result == Z_STREAM_END)
|
|
{
|
|
if (!zlib_stream->avail_in)
|
|
{
|
|
cache_copy_release_read_request(self, self->current_request);
|
|
self->current_read_sequence_index++;
|
|
self->current_read_sequence_count--;
|
|
self->current_request = NULL;
|
|
}
|
|
|
|
if (!zlib_stream->avail_out || zlib_result == Z_STREAM_END)
|
|
self->current_write_buffer_index = NONE;
|
|
}
|
|
else
|
|
{
|
|
if (cache_copy_stop_requested())
|
|
break;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
1248,
|
|
FALSE,
|
|
csprintf(
|
|
decompressor_globals.message,
|
|
"decompression fucked up with error code (%d), msg '%s'",
|
|
zlib_result,
|
|
zlib_stream->msg ? zlib_stream->msg : ""));
|
|
cache_copy_set_flag(_copy_bad_file_bit);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static unsigned long __stdcall simple_cache_copy_thread(
|
|
void *parameter)
|
|
{
|
|
struct simple_decompressor_definition *self = global_self;
|
|
|
|
for (;;)
|
|
{
|
|
WaitForSingleObject(self->copy_start_event, INFINITE);
|
|
|
|
decompressor_reset_timing();
|
|
decompressor_timer_start(_decompressor_timer_copying);
|
|
|
|
cache_copy_initialize_read_buffers(self);
|
|
cache_copy_initialize_file_data(self);
|
|
|
|
if (!cache_copy_stop_requested())
|
|
{
|
|
decompressor_timer_start(_decompressor_timer_setup);
|
|
cache_copy_initialize_read_data(self);
|
|
cache_copy_initialize_zlib(self);
|
|
decompressor_timer_stop(_decompressor_timer_setup);
|
|
|
|
if (cache_file_header_verify(&self->header, "cache decompressed", TRUE))
|
|
{
|
|
boolean keep_going = TRUE;
|
|
|
|
self->write_bytes_left = self->header.size - sizeof(self->header);
|
|
self->async_write_bytes_left = self->write_bytes_left;
|
|
|
|
cache_copy_issue_initial_reads(self);
|
|
|
|
while (!cache_copy_stop_requested() && self->write_bytes_left > 0 && keep_going)
|
|
{
|
|
unsigned long wait_result;
|
|
|
|
if (self->overlapped_in_use_flags[0])
|
|
{
|
|
boolean blocked_on_read =
|
|
acquire_read_request(self, self->current_read_sequence_index) == NULL;
|
|
boolean blocked_on_write =
|
|
self->write_requests_pending == 1 &&
|
|
self->current_write_buffer_index == NONE;
|
|
|
|
if (blocked_on_read || blocked_on_write)
|
|
{
|
|
if (blocked_on_read)
|
|
decompressor_timer_start(_decompressor_timer_thread_blocked_on_read);
|
|
if (blocked_on_write)
|
|
decompressor_timer_start(_decompressor_timer_thread_blocked_on_write);
|
|
decompressor_timer_start(_decompressor_timer_thread_blocked);
|
|
|
|
SetEvent(self->progress_update_event);
|
|
wait_result = WaitForSingleObjectEx(self->copy_stop_event, 5000, TRUE);
|
|
|
|
decompressor_timer_stop(_decompressor_timer_thread_blocked);
|
|
if (blocked_on_write)
|
|
decompressor_timer_stop(_decompressor_timer_thread_blocked_on_write);
|
|
if (blocked_on_read)
|
|
decompressor_timer_stop(_decompressor_timer_thread_blocked_on_read);
|
|
}
|
|
else
|
|
{
|
|
wait_result = WAIT_IO_COMPLETION;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
wait_result = WAIT_IO_COMPLETION;
|
|
}
|
|
|
|
keep_going = FALSE;
|
|
switch (wait_result)
|
|
{
|
|
case WAIT_OBJECT_0:
|
|
break;
|
|
|
|
case WAIT_IO_COMPLETION:
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
849,
|
|
any_bit_vector_flag_set(self->overlapped_completed_flags, BIT_VECTOR_SIZE_IN_LONGS(NUMBER_OF_OVERLAPPED_STRUCTURES)));
|
|
|
|
cache_copy_update_write_buffers(self);
|
|
cache_copy_run_decompression(self);
|
|
|
|
keep_going = !(global_self->flags & ALL_COPY_FAILURE_FLAGS);
|
|
break;
|
|
|
|
case WAIT_TIMEOUT:
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
866,
|
|
FALSE,
|
|
"timeout for asynchronous i/o");
|
|
cache_copy_set_flag(_copy_read_failed_bit);
|
|
break;
|
|
|
|
default:
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
875,
|
|
!"unreachable");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!self->write_bytes_left)
|
|
{
|
|
cache_copy_wait_for_async_io(self);
|
|
cache_copy_issue_write_raw(self, &self->header, sizeof(self->header), 0);
|
|
}
|
|
}
|
|
|
|
cache_copy_dispose_zlib(self);
|
|
}
|
|
|
|
cache_copy_wait_for_async_io(self);
|
|
|
|
CloseHandle(self->source_file);
|
|
self->source_file = NULL;
|
|
|
|
decompressor_timer_stop(_decompressor_timer_copying);
|
|
|
|
self->destination_file = NULL;
|
|
SetEvent(self->copy_complete_event);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void cache_copy_initialize(
|
|
void)
|
|
{
|
|
LARGE_INTEGER freq;
|
|
|
|
QueryPerformanceFrequency(&freq);
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\cache\\cache_files_decompress_windows.c",
|
|
487,
|
|
freq.u.HighPart==0);
|
|
performance_frequency = freq.u.LowPart;
|
|
|
|
global_self->copy_complete_event = CreateEvent(NULL, TRUE, TRUE, NULL);
|
|
global_self->copy_start_event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
global_self->copy_stop_event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
global_self->progress_update_event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
|
|
global_self->zlib_stream.zalloc = cache_copy_compressed_alloc;
|
|
global_self->zlib_stream.zfree = cache_copy_compressed_free;
|
|
|
|
global_self->copy_thread = CreateThread(
|
|
NULL,
|
|
CACHE_COPY_THREAD_STACK_SIZE,
|
|
simple_cache_copy_thread,
|
|
NULL,
|
|
0,
|
|
NULL);
|
|
|
|
return;
|
|
}
|