You are not logged in.
Pages: 1
Кстати, может тебе пригодится вот этот кусок кода с одной программки, а то я смотрю у вас невнятно эта структрура описана здесь на форуме:
struct GTASA_SCRIPT_THREAD // 0xE0 bytes total { void* pNext; // 0x00 void* pPrev; // 0x04 char strName[8]; // 0x08 DWORD dwBaseIP; // 0x10 DWORD dwScriptIP; // 0x14 DWORD dwReturnStack[8]; // 0x18 WORD dwStackPointer; // 0x38 DWORD dwLocalVar[34]; // 0x3C BYTE bStartNewScript; // 0xC4 BYTE bJumpFlag; // 0xC5 BYTE bIsMissionThread; // 0xC6 BYTE bIsExternalScript; // 0xC7 BYTE bInMenu; // 0xC8 BYTE bUnknown; // 0xC9 DWORD dwWakeTime; // 0xCC WORD wIfParam; // 0xD0 BYTE bNotFlag; // 0xD2 BYTE bWastedBustedCheck;// 0xD3 BYTE bWastedBustedFlag; // 0xD4 DWORD dwSceneSkipIP; // 0xD8 BYTE bMissionThread; // 0xDC };
На закуску:)
018c=4,play_sound %4d% at %1d% %2d% %3d% 097A=4,play_audio_at %1d% %2d% %3d% event %4d% 00507340 CAudioEvent::Buffer::PlayAt (t_coords Coords; int16 EventID)
Покапавшись в ассемблере отличий у этих опкодов не нашёл. Они положи почти как две капли воды. Хотя последний, наверное, должен использоваться после 03CF, который загружает банки.
Я думаю, так будет логичнее их назвать:
018c=4,play_at %1d% %2d% %3d% loaded_audio_event %4d% // проигрывает уже загруженные события (1000..1800) 097A=4,play_at %1d% %2d% %3d% loaded_bank_audio_event %4d% // проигрывает уже загруженные события (1000..1800) из банков (1800..2000) %4d% = -1 // возможно проигрывает последний загруженный звук, но неуверен. Надо проверить в игре.
Edit:
На всякий случай скажу, что 0xC47A0000 = -100.0
Почему -100 ?
(Добавлено) А точно это ж float! Блин, это значит, что в буфере содержутся координаты воспроизведения звука!
...посмотреть исходники SAAT.
Зачем? Я смотрел раньше, но ничего нового я не узнал.
А программа работает нормально? В будущем я ещё и для AudioStreams что-то подобное сделаю.
Не совсем в рамках темы, но всё таки...
В ходе разработки своей программы SFX Editor(http://rapidshare.com/files/44154049/SF … r.rar.html) у меня возникла мысль заглянуть в дебри опкода 03CF и в ходе разбора кода я нарыл много полезной информации. Думаю она вам пригодится.
Вот функции и структуры связанные со звуком (в основном звуковые эффекты):
CODE: 004D88A0 void CAudio->AudioSFX::LoadBankWave (int16 BankID,BankSlotID) 004D8ED0 void CAudio->AudioSFX::LoadWave (int16 BankID,WaveID,BankSlotID) 004D9930 bool CAudio::Create() 004D9CC0 bool CAudioEvents::Buffer::LoadInfo (int32* pAudioEvent,pBankID,pWaveID,EBufferID) 004E01B0 BankLookup* CAudioSFX::GetBankLookupAddress (uint8 BankID) 004E0220 bool CAudioSFX::LoadedBankToSlot (uint16 BankID; int16 BankSlotID) 004EBFE0 bool CAudioEvents::Buffer::LoadedSlot (uint8 BufferID) 004EF520 int8 CSoundManager::LoadedBank (int16 BankSlotID) 00507290 void CAudioEvents::Buffer::Load (uint8 BufferId; int32 AudioEvent) 005B9A60 void CAudioEvents::LoadExplosionSounds() 005B9690 bool CSoundManager::Init(?) 005B9A60 void CAudioEvents::LoadExplosionSounds 005B9C60 bool CAudioEvents::Create() DATA: 00B5F8B8 CAudio +D98 CAudioSFX* // здесь лежит указатель, адрес динамический, обычно 021F0000, насчёт класса не уверен 00B62CB0 CSoundManager 00B6BC90 CAudioEvents CAudioSFX +0 dd* pBankSlotData // BankSlot.dat +4 dd* pBankLookupData // BankLkup.dat +8 dd* pPakFilesData // PakFiles.dat +C dw NumSlots +E dw NumBanks +10 db NumPakFiles +14 db BufferFlag? +24 CAudioSFX::Buffer[50] // С этим буфером до конца ещё не разобрался +0 dd* pBankSlot +4 dd BankLookup.WaveOffset +8 dd BankLookup.WaveLenght +14 dd UnkFlag? +18 dw BankID +1A dw BankSlotID +20 dw WaveID +22 db BankLookup.PackID +668 dw InitBufferSlotsNum // количество проинициализированных слотов буфера
Ниже следующий кусок кода из моей программы. Он отражает назначение некоторых структур и переменных, которые используются в вышеперечисленных функциях.
{ === Wave Audio Bank Structure === } TWaveInfo = record HeaderOffset: Cardinal; StartLoop: Integer; SampleRate: Word; UnknownFlag1: Byte; // Pan?? UnknownFlag2: Shortint; // Loops??? end; TWaveBankHeader = record WaveCount: Cardinal; WaveInfoList: array[0..399] of TWaveInfo; end; TWaveBank = record Header: TWaveBankHeader; Data: array of Byte; end; { === SFX PACK Structure === } TSFX_Pack = array of TWaveBank; { === BankLkup.dat Structure === } TWaveBankInfo = record PackFileID: Cardinal; // ($CCCCCC00 or $XX), $XX - File ID Offset: Cardinal; DataSize: Cardinal; end; TWaveBanks = array of TWaveBankInfo; { === PakFiles.dat Structure === } TPackName = array of array[0..51] of Char;
Здесь я хочу показать алгоритм работы опкода 03CF. Некоторые куски кода мне не совсем понятны, их назначение.
03CF: load_in (AUDIO_EVENT_BUFFER:unsigned_byte) audio_event (AUDIO_EVENT:int) AUDIO_EVENT_BUFFER(MAX 4 SLOTS) 1,2,3,4: для звуков (SOUNDs 2000..45400,-1) 3,4: для набора звуков (BANKs 1800..1829) ========================================================================================================================= <gta_sa._opcode_03CF> ========================================================================================================================= 0048519B > > 6A 02 PUSH 2 ; _opcode_03CF; Case 3CF of switch 00483BF2 0048519D . 8BCE MOV ECX,ESI 0048519F . E8 DCEEFDFF CALL <gta_sa.CScriptThread::LoadNumParams> 004851A4 . 8B0D 7C3CA400 MOV ECX,DWORD PTR DS:[<OpcodeParams[1]>] 004851AA . 33D2 XOR EDX,EDX 004851AC . 8A15 783CA400 MOV DL,BYTE PTR DS:[<OpcodeParams[0]>] 004851B2 . FECA DEC DL 004851B4 . 51 PUSH ECX ; 2: int32 AudioEvent 004851B5 . B9 90BCB600 MOV ECX,OFFSET <gta_sa.CAudioEvent> 004851BA . 52 PUSH EDX ; 1: uint8 BufferID 004851BB . E8 D0200800 CALL <gta_sa.CAudioEvent::Load> 004851C0 . 32C0 XOR AL,AL ========================================================================================================================= <gta_sa.CAudioEvent::Load> ========================================================================================================================= 00507290 > $ 81C1 A0020000 ADD ECX,2A0 ; Buffer& = CAudioEvents::Buffer 00507296 .^E9 F54EFEFF JMP gta_sa.004EC190 ......................................................................................................................... 004EC190 > 83EC 0C SUB ESP,0C 004EC193 . 53 PUSH EBX 004EC194 . 8B5C24 14 MOV EBX,DWORD PTR SS:[ESP+14] ; EBX = BufferID 004EC198 . 80FB 04 CMP BL,4 004EC19B . 56 PUSH ESI 004EC19C . 8BF1 MOV ESI,ECX 004EC19E . 0F83 C0000000 JNB gta_sa.004EC264 ; exit if BufferID >= 4 004EC1A4 . 53 PUSH EBX 004EC1A5 . E8 36FEFFFF CALL <gta_sa.CAudioEvents::Buffer::LoadedSlot> 004EC1AA . 84C0 TEST AL,AL 004EC1AC . 0F84 B2000000 JE gta_sa.004EC264 ; exit if prc = false 004EC1B2 . 0FB6C3 MOVZX EAX,BL 004EC1B5 . 55 PUSH EBP 004EC1B6 . 8BC8 MOV ECX,EAX 004EC1B8 . 57 PUSH EDI 004EC1B9 . C1E1 05 SHL ECX,5 ; BufferID * 32 004EC1BC . 03F1 ADD ESI,ECX 004EC1BE . 50 PUSH EAX ; 4: int32 EBufferID = BufferID 004EC1BF . 8DBE AC000000 LEA EDI,DWORD PTR DS:[ESI+AC] 004EC1C5 . 57 PUSH EDI ; 3: int32* pWaveID = *Buffer::Slot[BufferId].WaveID 004EC1C6 . 8DAE A8000000 LEA EBP,DWORD PTR DS:[ESI+A8] 004EC1CC . 8D5424 2C LEA EDX,DWORD PTR SS:[ESP+2C] 004EC1D0 . 55 PUSH EBP ; 2: int32* pBankID = *Buffer::Slot[BufferId].BankID 004EC1D1 . 52 PUSH EDX ; 1: int32* pAudioEvent = *AudioEvent 004EC1D2 . E8 E9DAFEFF CALL <gta_sa.CAudioEvents::Buffer::LoadInfo> 004EC1D7 . 83C4 10 ADD ESP,10 004EC1DA . 84C0 TEST AL,AL 004EC1DC . 0F84 80000000 JE gta_sa.004EC262 ; exit if PROC = false 004EC1E2 . 8B07 MOV EAX,DWORD PTR DS:[EDI] 004EC1E4 . 33C9 XOR ECX,ECX 004EC1E6 . 85C0 TEST EAX,EAX 004EC1E8 . 66:0FB6C3 MOVZX AX,BL 004EC1EC . 7C 1B JL SHORT gta_sa.004EC209 ; jump if WaveID < 0 004EC1EE . 66:8B0F MOV CX,WORD PTR DS:[EDI] 004EC1F1 . 33D2 XOR EDX,EDX 004EC1F3 . 66:8B55 00 MOV DX,WORD PTR SS:[EBP] 004EC1F7 . 83C0 1A ADD EAX,1A 004EC1FA . 50 PUSH EAX ; 3: int16 BankSlotID 004EC1FB . 51 PUSH ECX ; 2: int16 WaveID 004EC1FC . B9 B8F8B500 MOV ECX,<gta_sa.CAudio> 004EC201 . 52 PUSH EDX ; 1: int16 BankID 004EC202 . E8 C9CCFEFF CALL <gta_sa.CAudio->CAudioSFX::LoadWave> 004EC207 . EB 13 JMP SHORT gta_sa.004EC21C 004EC209 > 66:8B4D 00 MOV CX,WORD PTR SS:[EBP] 004EC20D . 83C0 1A ADD EAX,1A 004EC210 . 50 PUSH EAX ; 2: int16 BankSlotID 004EC211 . 51 PUSH ECX ; 1: int16 BankID 004EC212 . B9 B8F8B500 MOV ECX,<gta_sa.CAudio> 004EC217 . E8 84C6FEFF CALL <gta_sa.CAudio->AudioSFX::LoadBankWave> 004EC21C > 8B5424 24 MOV EDX,DWORD PTR SS:[ESP+24] 004EC220 . 8996 A4000000 MOV DWORD PTR DS:[ESI+A4],EDX ; Buffer::Slot[BufferId].AudioEvent = AudioEvent 004EC226 . C786 9C000000 >MOV DWORD PTR DS:[ESI+9C],0 004EC230 . C74424 10 0000>MOV DWORD PTR SS:[ESP+10],C47A0000 004EC238 . 8B4424 10 MOV EAX,DWORD PTR SS:[ESP+10] 004EC23C . 81C6 90000000 ADD ESI,90 ; CurSlot& = Buffer::Slot[BufferId] 004EC242 . C74424 14 0000>MOV DWORD PTR SS:[ESP+14],C47A0000 004EC24A . 8B4C24 14 MOV ECX,DWORD PTR SS:[ESP+14] 004EC24E . 8906 MOV DWORD PTR DS:[ESI],EAX ; CurSlot.ddvar1 = 0xC47A0000 004EC250 . C74424 18 0000>MOV DWORD PTR SS:[ESP+18],C47A0000 004EC258 . 8B5424 18 MOV EDX,DWORD PTR SS:[ESP+18] 004EC25C . 894E 04 MOV DWORD PTR DS:[ESI+4],ECX ; CurSlot.ddvar2 = 0xC47A0000 004EC25F . 8956 08 MOV DWORD PTR DS:[ESI+8],EDX ; CurSlot.ddvar3 = 0xC47A0000 004EC262 > 5F POP EDI 004EC263 . 5D POP EBP 004EC264 > 5E POP ESI 004EC265 . 5B POP EBX 004EC266 . 83C4 0C ADD ESP,0C 004EC269 . C2 0800 RETN 8 ========================================================================================================================= GetAudioEventInfo для 03CF опкода: загружает в буфер информацию о аудио событии. Буфер находится по адресу 0x00B6BFC0 и содержит четыре элемента размером 32 байта. AudioEventBuffer [0x00B6BFC0, 32 bytes, 4 elements] +0 dd ?C4A70000 +4 dd ?C4A70000 +8 dd ?C4A70000 +14 dd AudioEventId +18 dd BankId +20 dd WaveId EBufferID - Extended Buffer Identificator. Он может содержитать не только номер буфера, но и дополнительную информацию. Pascal: function CAudioEvents::Buffer::LoadInfo(var pAudioEvent,pBankID,pWaveID: Integer; int EBufferID): Boolean; cdecl; C/C++: __cdecl int CAudioEvents::Buffer::LoadInfo(int* pAudioEvent,pBankID,pWaveID; int EBufferID); ------------------------- [ESP+8] pAudiEvent [ESP+C] pBankId [ESP+10] pWaveId [ESP+14] EBufferID ------------------------- ========================================================================================================================= 004D9CC0 >/$ 56 PUSH ESI ; (* CAudioEvents::Buffer::LoadInfo *) 004D9CC1 |. 8B7424 08 MOV ESI,DWORD PTR SS:[ESP+8] 004D9CC5 |. 8B06 MOV EAX,DWORD PTR DS:[ESI] 004D9CC7 |. 3D 08070000 CMP EAX,708 ; if pAudioEvent < 1800 then 004D9CCC |. 7D 04 JGE SHORT gta_sa.004D9CD2 ; begin 004D9CCE |. 32C0 XOR AL,AL ; Result := False; 004D9CD0 |. 5E POP ESI ; Exit; 004D9CD1 |. C3 RETN ; end; 004D9CD2 |> 3D D0070000 CMP EAX,7D0 ; if pAudioEvent < 2000 then 004D9CD7 |. 7D 1B JGE SHORT gta_sa.004D9CF4 ; begin 004D9CD9 |. 8B0485 70BC8A00 MOV EAX,DWORD PTR DS:[EAX*4+8ABC70] ; // BankEvent[AudioEvent - 1800] 004D9CE0 |. 8B4C24 0C MOV ECX,DWORD PTR SS:[ESP+C] 004D9CE4 |. 8B5424 10 MOV EDX,DWORD PTR SS:[ESP+10] 004D9CE8 |. 8901 MOV DWORD PTR DS:[ECX],EAX ; pBankID := BankIdEvent[pAudioEvent - 1800]; 004D9CEA |. C702 FFFFFFFF MOV DWORD PTR DS:[EDX],-1 ; pWaveID := -1; 004D9CF0 |. B0 01 MOV AL,1 ; Result := True; 004D9CF2 |. 5E POP ESI ; Exit; 004D9CF3 |. C3 RETN ; end; 004D9CF4 |> 3D FFFF0000 CMP EAX,0FFFF ; if pAudioEvent = -1 then // Для чего??? 004D9CF9 |. 75 3D JNZ SHORT gta_sa.004D9D38 ; begin 004D9CFB |. 8B4424 0C MOV EAX,DWORD PTR SS:[ESP+C] ; // SOUND_BANK_NULL = 291 004D9CFF |. C700 23010000 MOV DWORD PTR DS:[EAX],123 ; pBankID := SOUND_BANK_NULL; 004D9D05 |. 8B4424 14 MOV EAX,DWORD PTR SS:[ESP+14] 004D9D09 |. 85C0 TEST EAX,EAX ; if (EBufferID >= 0) and 004D9D0B |. 7C 1D JL SHORT gta_sa.004D9D2A 004D9D0D |. 83F8 04 CMP EAX,4 ; (EBufferID < 4) then 004D9D10 |. 7D 18 JGE SHORT gta_sa.004D9D2A ; begin 004D9D12 |. 25 01000080 AND EAX,80000001 ; EBufferID := EBufferID and $80000001; 004D9D17 |. 79 05 JNS SHORT gta_sa.004D9D1E ; if EBufferID < 0 then // Зачем? Смысл? 004D9D19 |. 48 DEC EAX ; begin 004D9D1A |. 83C8 FE OR EAX,FFFFFFFE ; EBufferID := (EBufferID - 1) or $FFFFFFFE; 004D9D1D |. 40 INC EAX ; Inc(EBufferID); 004D9D1E |> 8B4C24 10 MOV ECX,DWORD PTR SS:[ESP+10] ; end; 004D9D22 |. D1E0 SHL EAX,1 ; pWaveID := EBufferID * 2; //всегда 0 или 2 004D9D24 |. 8901 MOV DWORD PTR DS:[ECX],EAX ; Result := True; 004D9D26 |. B0 01 MOV AL,1 ; Exit; 004D9D28 |. 5E POP ESI ; end; 004D9D29 |. C3 RETN 004D9D2A |> 8B5424 10 MOV EDX,DWORD PTR SS:[ESP+10] ; 004D9D2E |. C702 00000000 MOV DWORD PTR DS:[EDX],0 ; pWaveID := 0; 004D9D34 |. B0 01 MOV AL,1 ; Result := True; 004D9D36 |. 5E POP ESI ; Exit; 004D9D37 |. C3 RETN ; end 004D9D38 |> 05 30F8FFFF ADD EAX,-7D0 004D9D3D |. 894424 08 MOV DWORD PTR SS:[ESP+8],EAX ; pAudioEvent := pAudioEvent - 2000; 004D9D41 |. DB4424 08 FILD DWORD PTR SS:[ESP+8] 004D9D45 |. 83EC 08 SUB ESP,8 004D9D48 |. D80D 4C8B8500 FMUL DWORD PTR DS:[858B4C] ; // CONST [858B4C] = 0.005 (1/200) 004D9D4E |. DD1C24 FSTP QWORD PTR SS:[ESP] 004D9D51 |. E8 9A7C3400 CALL <gta_sa.floor> 004D9D56 |. 83C4 08 ADD ESP,8 004D9D59 |. E8 E27D3400 CALL <gta_sa.__ftol2> 004D9D5E |. 8B4C24 0C MOV ECX,DWORD PTR SS:[ESP+C] 004D9D62 |. 05 93000000 ADD EAX,93 004D9D67 |. 8901 MOV DWORD PTR DS:[ECX],EAX ; pBankID := Floor(pAudioEvent/200) + 147 004D9D69 |. 8B06 MOV EAX,DWORD PTR DS:[ESI] ; // pBankID := AudioEvent div 200 + 147 004D9D6B |. 2D D0070000 SUB EAX,7D0 ; // 147 - SCRIPT_FIRST_BANK_ID 004D9D70 |. 99 CDQ 004D9D71 |. B9 C8000000 MOV ECX,0C8 004D9D76 |. F7F9 IDIV ECX 004D9D78 |. 8B4424 10 MOV EAX,DWORD PTR SS:[ESP+10] 004D9D7C |. 5E POP ESI 004D9D7D |. 8910 MOV DWORD PTR DS:[EAX],EDX ; pWaveID := pAudioEvent mod 200 004D9D7F |. B0 01 MOV AL,1 ; Result := True; 004D9D81 \. C3 RETN ; Exit; ========================================================================================================================= CAudio->AudioSFX::LoadBankWave (int16 BankID,BankSlotID) ========================================================================================================================= 004D88A0 > $ 8A41 01 MOV AL,BYTE PTR DS:[ECX+1] ; 004D88A3 . 84C0 TEST AL,AL 004D88A5 . 75 0B JNZ SHORT gta_sa.004D88B2 004D88A7 . 8B89 980D0000 MOV ECX,DWORD PTR DS:[ECX+D98] ; CAudioSFX& = *CAudio->AudioSFX 004D88AD . E9 BE7D0000 JMP gta_sa.004E0670 004D88B2 > C2 0800 RETN 8 ......................................................................................................................... 004E0670 > 56 PUSH ESI 004E0671 . 8BF1 MOV ESI,ECX ; ESI = CAudioSFX 004E0673 . 8A46 14 MOV AL,BYTE PTR DS:[ESI+14] 004E0676 . 84C0 TEST AL,AL 004E0678 . 0F84 15010000 JE gta_sa.004E0793 ; exit if CAudioSFX::UnkFlag1 = 0 004E067E . 0FBF46 0E MOVSX EAX,WORD PTR DS:[ESI+E] 004E0682 . 53 PUSH EBX 004E0683 . 8B5C24 0C MOV EBX,DWORD PTR SS:[ESP+C] 004E0687 . 55 PUSH EBP 004E0688 . 0FB7EB MOVZX EBP,BX 004E068B . 3BE8 CMP EBP,EAX 004E068D . 57 PUSH EDI 004E068E . 0F8F FC000000 JG gta_sa.004E0790 ; exit if BankID > CAudioSFX::NumBanks 004E0694 . 8B7C24 18 MOV EDI,DWORD PTR SS:[ESP+18] 004E0698 . 66:85FF TEST DI,DI 004E069B . 0F8C EF000000 JL gta_sa.004E0790 ; exit if BankID < 0 004E06A1 . 66:3B7E 0C CMP DI,WORD PTR DS:[ESI+C] 004E06A5 . 0F8F E5000000 JG gta_sa.004E0790 ; exit if BankSlotID > CAudioSFX::NumBankSlots 004E06AB . 57 PUSH EDI ; 2: int16 BankSlotID 004E06AC . 53 PUSH EBX ; 1: int16 BankID 004E06AD . E8 6EFBFFFF CALL <gta_sa.CAudioSFX::LoadedBankToSlot> ; <|=== LoadedBankToSlot??? === 004E06B2 . 84C0 TEST AL,AL 004E06B4 . 0F85 D6000000 JNZ gta_sa.004E0790 ; exit if proc = true 004E06BA . 33C9 XOR ECX,ECX 004E06BC . 8D46 3E LEA EAX,DWORD PTR DS:[ESI+3E] 004E06BF . 90 NOP ; /=== LoadedBankToBuffer??? === 004E06C0 > 0FBF50 FE MOVSX EDX,WORD PTR DS:[EAX-2] ; |!loop ECX = 0..31 004E06C4 . 3BD5 CMP EDX,EBP ; | 004E06C6 . 75 09 JNZ SHORT gta_sa.004E06D1 ; |jump if Buffer[ECX].BankID <> BankID 004E06C8 . 66:3938 CMP WORD PTR DS:[EAX],DI ; | 004E06CB . 0F84 BF000000 JE gta_sa.004E0790 ; |exit if Buffer[ECX].BankSlotID = BankSlotID 004E06D1 > 41 INC ECX ; | 004E06D2 . 83C0 20 ADD EAX,20 ; | 004E06D5 . 83F9 32 CMP ECX,32 ; | 004E06D8 .^7C E6 JL SHORT gta_sa.004E06C0 ; \jump !loop if ECX < 32 004E06DA . 53 PUSH EBX ; 1: BankID 004E06DB . 8BCE MOV ECX,ESI 004E06DD . E8 CEFAFFFF CALL <gta_sa.CAudioSFX::GetBankLookupAddress>; BankLookup* PROC 004E06E2 . 0FBF8E 6806000>MOVSX ECX,WORD PTR DS:[ESI+668] 004E06E9 . C1E1 05 SHL ECX,5 ; InitBufferSlotsNum*32 004E06EC . 66:895C31 3C MOV WORD PTR DS:[ECX+ESI+3C],BX ; Buffer[InitBufferSlotsNum].BankID = BankID 004E06F1 . 0FBF96 6806000>MOVSX EDX,WORD PTR DS:[ESI+668] 004E06F8 . C1E2 05 SHL EDX,5 004E06FB . 66:897C32 3E MOV WORD PTR DS:[EDX+ESI+3E],DI ; Buffer[InitBufferSlotsNum].BankSlotID = BankSlotID 004E0700 . 0FBF8E 6806000>MOVSX ECX,WORD PTR DS:[ESI+668] 004E0707 . 83C1 02 ADD ECX,2 004E070A . C1E1 05 SHL ECX,5 004E070D . 66:C70431 FFFF MOV WORD PTR DS:[ECX+ESI],0FFFF ; Buffer[InitBufferSlotsNum].Unk1 = -1 004E0713 . 0FBF8E 6806000>MOVSX ECX,WORD PTR DS:[ESI+668] 004E071A . 8B1E MOV EBX,DWORD PTR DS:[ESI] 004E071C . 0FBFD7 MOVSX EDX,DI 004E071F . 69D2 D4120000 IMUL EDX,EDX,12D4 004E0725 . 03D3 ADD EDX,EBX 004E0727 . C1E1 05 SHL ECX,5 004E072A . 895431 24 MOV DWORD PTR DS:[ECX+ESI+24],EDX ; Buffer[InitBufferSlotsNum].pBankSlot = *BankSlot[BankSlotID] 004E072E . 8A08 MOV CL,BYTE PTR DS:[EAX] 004E0730 . 0FBF96 6806000>MOVSX EDX,WORD PTR DS:[ESI+668] 004E0737 . C1E2 05 SHL EDX,5 004E073A . 884C32 42 MOV BYTE PTR DS:[EDX+ESI+42],CL ; Buffer[InitBufferSlotsNum].PackID = BankLookup.PackID 004E073E . 8B48 04 MOV ECX,DWORD PTR DS:[EAX+4] 004E0741 . 0FBF96 6806000>MOVSX EDX,WORD PTR DS:[ESI+668] 004E0748 . C1E2 05 SHL EDX,5 004E074B . 894C32 28 MOV DWORD PTR DS:[EDX+ESI+28],ECX ; Buffer[InitBufferSlotsNum].PackID = BankLookup.WaveDataOffset 004E074F . 0FBF96 6806000>MOVSX EDX,WORD PTR DS:[ESI+668] 004E0756 . 8B40 08 MOV EAX,DWORD PTR DS:[EAX+8] 004E0759 . C1E2 05 SHL EDX,5 004E075C . 894432 2C MOV DWORD PTR DS:[EDX+ESI+2C],EAX ; Buffer[InitBufferSlotsNum].PackID = BankLookup.WaveLenght 004E0760 . 0FBF8E 6806000>MOVSX ECX,WORD PTR DS:[ESI+668] 004E0767 . C1E1 05 SHL ECX,5 004E076A . C74431 38 0100>MOV DWORD PTR DS:[ECX+ESI+38],1 ; Buffer[InitBufferSlotsNum].bUnkFlag1 = 1 004E0772 . 0FBF86 6806000>MOVSX EAX,WORD PTR DS:[ESI+668] 004E0779 . 66:FF86 660600>INC WORD PTR DS:[ESI+666] ; CAudioSFX::InitBankBufNum++ 004E0780 . 40 INC EAX 004E0781 . 99 CDQ 004E0782 . B9 32000000 MOV ECX,32 004E0787 . F7F9 IDIV ECX 004E0789 . 66:8996 680600>MOV WORD PTR DS:[ESI+668],DX ; CAudioSFX::InitBufNum++ %= 50 004E0790 > 5F POP EDI 004E0791 . 5D POP EBP 004E0792 . 5B POP EBX 004E0793 > 5E POP ESI 004E0794 . C2 0800 RETN 8
Ещё мне не совсем понятно назначение файла BankSlot.dat.
Наверное этот файл хранит глобальный буффер, его размер и начальные значения.
Вообще, я так понимаю в игре три буффера для звуковых эффектов.
Первый, и наверное самый главный - это буффер BankSlot. Количество слотов зависит от размера файла. Обычно 45.
Второй - это CAudiSFX::Buffer[]. Имеет 50 слотов.
И третий, наверное для скриптов - это CAudioEvent::Buffer. Он самый маленький имеет всего только 4 слота.
Но фишка в том, что в слот может загружатся как целый банк, так и отдельный файл!
А некоторые загружаются ещё в начале игры. Их не нужно загружать повторно.
Моей программой можно посмотреть EventId, BankId, WaveId и прослушать необходимые звуки.
Думаю, если Seemann согласится встроить SFX плагин, то в SB3 мы сможем прослушивать звуки,
не отвлекаясь от написания скриптов. Думаю, что в мой плагин можно будет добавить функцию,
которая возвращает имя аудио события, если в SB3 не будут именованы аудио-константы.
Ладно хватит. А то уже оффтоп пошёл
А, чуть не забыл.
По файловому адресу 004AB490 идут структуры размером 4 байта и в каждой из них номер банка,
положение который соотвествует скриптовым событиям, начиная с 1800 и до 2000.
Это те аудио события, которые загружают банки, а не звуки
352: 1800 310: 1801 296: 1802 291: 1803,1805,1808,1815,1816 // считается как NULL, -1 указывает тоже на этот банк 242: 1804 222: 1806 209: 1807 167: 1809 163: 1810 160: 1811 265: 1812 304: 1813 158: 1814 292: 1817 171: 1818 198: 1819 226: 1820 293: 1821 319: 1822 345: 1823 351: 1824 266: 1825 183: 1826 153: 1827 298: 1828 339: 1829
Кстати, аудио события, начинающие с 1000 и до 1800, это звуки банков, которые доступны только при загрузке банков.
Они проигрываются только с помощью следующих опкодов:
097A: play_at 0.0 0.0 0.0 loaded_audio_event 1132 097B=2,play_audio_at_object %1d% event %2d%
Но некоторые из этих событий не надо загружать, т. к. они уже либо загружены,
либо загружаются и проигрываются вышеупомянутыми опкодами.
Вот у меня вопрос, если в сейве ко всем ячейки содержащие адреса с 0xA49960 до конца SCM блока прибавить размер добаленного кода в SCM, то сейв загрузится? Я думаю, что да, ведь указатели на текущие потоки не собьются.
Вот скажите мне где находятся в экзешнике (по каким адресам) зашитые скрипты, например, такие как пролетающий самолёт над героем в случайное время, патрулирующий вертолёт в Лос-Сантосе, реакции полиции на нарушения правопорядка и т.д. Хотелось бы их изменить.
Да вот, например, у меня город 3000x3000, а дальше хочу сделать ещё город 3000x3000 (например на севере или на юге, не важно) и мне надо, чтобы была для него отдельная карта, чтобы пути были, но память то не бесконечная! Мне надо, чтобы игрок достигнув одной из "сторон света" мог перейти на следующую локацию не нагружая память! Надо, чтобы старый штат выгрузился и загрузился новый!
Вот эта функция, которую я искал:
LoadGame(char; fileName)) Initializes all data structures and loads fileName (which is gta.dat).
Привет всем! Вот я давно хотел сделать так, чтобы игрок достигнув предела карты мог дальше ходить по местности, выполнять миссии и т. д.
Например, проверяется каким-нибудь опкодом местоположение игрока и если он выходит за пределы карты, то выгружается старый город из памяти и загружается новый. Как это реализовать может поможите? Есть проблема со скриптами: использовать один, один как главный с нескольками или каждый по отдельности. Также как пользоваться координатами для разных городов в опкодах? Ещё я где-то видел, что есть функция которая загружает игру через dat файл. Интересно есть функция которая всё выгружает из памяти?
Pages: 1