GDR Forum Index
Podcast Podcast
Dev Dev Logs
Search Search
RSS RSS
Register Register
Log in Log in
Reply to topic GDR Forum Index -> Game Developer's Refuge -> [hacking] graphics ripping Page 1, 2  Next
View previous topic :: View next topic  
Author Message
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1670
Location: Your consciousness.
PostPosted: Sun Apr 23, 2017 5:37 am    Post subject: [hacking] graphics ripping Reply with quote

Looks like I have a new hobby, it all started four days ago with an innocent little thought:

"Hey, I Want to rip the sprites from Epyx 1994 DOS classic Battle Bugs." (and I should have left it at wanting instead of proceeding to actually do it)

So far I only managed to rip the CARDS file which contains unit descriptions cards and some other stuff that is used in-game in the little Fony-TV from the UI. Took me a whole day to figure out they were stored in an ancient 4 bit planar mode (was trying to open that file as RAW data in GIMP and kept looking at oddly shaped non-sensical patterns until it 'clicked' in the head) but once I figured that out, reading the bits and rearranging them with a little custom throwaway C code was straightforward.

all cards:
https://abload.de/img/cards_rippeda3xva.png

unit cards only:
https://abload.de/img/bbugs_unit_cards3izfi.png

Thrilled by that success I tried the same with the BUGS file to rip the sprite animations and I can even see some ant shape bits in there when I recode the bytes as 1bpp into a black and white image...:
(this one contains the converted bits from the player controlled ant and from the enemy ant(I think))
https://abload.de/img/onebug_bits1zvy1o.png

...but no matter how hard I tried, tried packed pixel decoding and planar decoding with all kinds of guesswork offsets, skipping bytes and whatnot and looking at scrambled pixel garbage for two full days without success in that glorious shotgun-stab-in-the-dark-walking-through-fog-mode...

...I finally gave up and started looking into x86 assembly coding and the world of DOS API interrupts and VGA/SVGA programming craptitude. Luckily DOSBOX could be build with a good enough builtin debugger which allows breaking depending on which interrupt gets triggered and with what parameter in the AH register...

...so on the fourth day now trying to rip those BUGS, I have ventured deep into the world of x86 opcodes and reading ancient docs to figure out how the game reads/decodes those sprites. So far, I figured out that the first 178 bytes of the file are just a header containing number of sprites and offsets for their bytes in the file. Next I need to figure out how the individual bytes per bug are actually used because they still don't make sense when trying to create readable pixels from them directly. I feel like I'm getting close (but then again, I felt like that periodically every couple of hours over the past few days :P ).

Fancy desktop shot documenting the progress/controlled chaos in figuring out the BUGS file (containing the sprites as I assume):
https://abload.de/img/20170423_145626_465298drhb.png

I just hope those bastards are not actually encoded directly as x86-code for drawing speed reasons as that would make de-scrambling extra painful.

This shit severely eats into my drawing practice time... and it's causing sleeping problems too... meh. :P
_________________
0xDB
View user's profile Send private message Visit poster's website
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1670
Location: Your consciousness.
PostPosted: Mon Apr 24, 2017 9:29 am    Post subject: Reply with quote

As my mind slowly pieces this crap together, trying to make sense of what it finds, it's digging up more ancient docs like...

...Michael Abrash's Graphics Programming Black Book Special Edition...
...Ralf Browns Interrupt List...
...PC Game Programmers Encyclopedia...

...and they all ooze "important, nay, ESSENTIAL".

I figure this stuff will take some time, need to learn more about this bygone era of infinite pain but look(down there)... it sets some mode of which I don't know what it does yet to 'write unmodified' ... WRITE THE FUCK UNMODIFIED ... I feel this is important and it has a super optmistic feel to it, UNMODIFIED... unmodified must be good.

It sounds simple as in the opposite of complicated. Will keep digging...: https://abload.de/img/20170424_191433_8673325oe3.png (edit: un-inlined huge screenshot which broke page layout for me)
_________________
0xDB


Edited by 0xDB on Tue Apr 25, 2017 8:32 am; edited 1 time
View user's profile Send private message Visit poster's website
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1670
Location: Your consciousness.
PostPosted: Mon Apr 24, 2017 11:00 am    Post subject: Reply with quote

For the moment I'm not debugging in DosBox but just searching for accesses to the VGA registers in the disassembled file and then looking up, decoding line by line what it does there (or what I think it does depending on the bits I find in the VGA and x86 docs).

I think I've found something like a "clear screen" routine here:
Code:
                                          ; subroutine to clear screen ?
0001211B  BACE03            mov dx,0x3ce  ; set dx to Graphics Controller (GC) Index register
0001211E  B80300            mov ax,0x3    ; port 3 (data rotate function select , data 0 : mode = write data unmodified)
00012121  EF                out dx,ax     ;
00012122  B808FF            mov ax,0xff08 ; port 8 (bitmask register), data 1111 1111 (keep all from modification or allow all ?)
00012125  EF                out dx,ax     ;                                           ( allow all makes more sense )
00012126  B80502            mov ax,0x205  ; port 5 (mode register), data 0000 0010 (color plane n(0-3) filled with bit n in write)
00012129  EF                out dx,ax     ;
0001212A  B960EA            mov cx,0xea60 ; cx set to 60000 bytes (800x600 requires 240000 bytes (2 pixel per 8bit) in 4bit
                                          ;                        planar mode = 60000 bytes per plane (4*60000 == 240000)
0001212D  B800A0            mov ax,0xa000 ; screen start address to AX
00012130  8EC0              mov es,ax     ; screen start address now in ES
00012132  BF0000            mov di,0x0    ; di to 0
00012135  8AC3              mov al,bl     ; bl to al (what's in bl though? must have been set before calling this routine)
00012137  FC                cld           ; clear direction flag (?)
00012138  F3AA              rep stosb     ; fill cx bytes at ES:[DI] with al  (0xa000:0x0000..0xea60)
0001213A  CB                retf          ;

_________________
0xDB
View user's profile Send private message Visit poster's website
Sirocco
Moderator

Joined: 19 Aug 2005
Posts: 9461
Location: Not Finland
PostPosted: Mon Apr 24, 2017 11:20 am    Post subject: Reply with quote

Another really, really good hardware reference is the DOS Programmer's Reference.

Anything you want to know about opcodes and register sets for all manner of basic hardware...
_________________
NoOP / Reyn Time -- The $ is screwing everyone these days. (0xDB)
View user's profile Send private message Visit poster's website
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1670
Location: Your consciousness.
PostPosted: Tue Apr 25, 2017 8:28 am    Post subject: Reply with quote

Hm... can't find a working download for that one.

Meanwhile, I have taken another step back and started reading Abrash's other book "Zen of Assembly Language: Volume I, Knowledge". That, and the "Graphics Programming Blackbook Special Edition" appear to be freely available these days, as markdown versions that can be converted to fancy single-page html files with pandoc.
_________________
0xDB
View user's profile Send private message Visit poster's website
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1670
Location: Your consciousness.
PostPosted: Wed Apr 26, 2017 2:51 am    Post subject: Reply with quote

Neat! Just found the older 5.0 Freeware Version of IDA Pro. It runs a bit of analysis on the code and unlike ndisasm which just blindly decodes the opcodes into assembly language, it actually understands the header of the DOS/MZ executable format and uses that to prepare a better navigable version of the code. It even automatically adds very helpful comments on interrupt calls and port writes if it knows what they're being used for:


_________________
0xDB
View user's profile Send private message Visit poster's website
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1670
Location: Your consciousness.
PostPosted: Wed Apr 26, 2017 10:15 am    Post subject: Reply with quote

Had already identified this BUGS byte reading stuff via the DosBox Debugger but it is just so much nicer to have it in IDA which allows assigning names for memory locations(variables and functions) and immediately makes the code much more readable and easier to follow what's going on.
Starting to feel like this little reverse engineering adventure is getting a bit more structured now.

routine_READ_BUG_BY_INDEX
Code:
seg003:32D1 ; Attributes: bp-based frame
seg003:32D1
seg003:32D1 routine_READ_BUG_BY_INDEX proc far      ; CODE XREF: sub_101C4+5P
seg003:32D1                                         ; sub_10242+4FP ...
seg003:32D1
seg003:32D1 RAM_FOR_BUG_BYTES= word ptr -0Ah
seg003:32D1 bytesNeededForBugHigh= word ptr -8
seg003:32D1 bytesNeededForBugLow= word ptr -6
seg003:32D1 fileHandle      = word ptr -4
seg003:32D1 BUG_INDEX       = word ptr -2
seg003:32D1 arg_471E        = word ptr  4724h
seg003:32D1
seg003:32D1                 enter   0Ah, 0
seg003:32D5                 mov     [bp+BUG_INDEX], ax
seg003:32D8                 mov     [bp+RAM_FOR_BUG_BYTES], bx
seg003:32DB                 push    si
seg003:32DC                 call    sub_1577B
seg003:32E1                 pop     si
seg003:32E2                 push    cs
seg003:32E3                 call    near ptr sub_135B1
seg003:32E6                 nop
seg003:32E7                 jnb     short loc_13499
seg003:32E9                 mov     some_error_code, 2
seg003:32EF                 call    sub_157AE
seg003:32F4                 jmp     far ptr loc_1B8C4
seg003:32F9 ; ---------------------------------------------------------------------------
seg003:32F9
seg003:32F9 loc_13499:                              ; CODE XREF: routine_READ_BUG_BY_INDEX+16j
seg003:32F9                 mov     [bp+fileHandle], ax
seg003:32FC                 mov     bx, ax
seg003:32FE                 mov     ah, 3Fh ; '?'
seg003:3300                 mov     cx, 2
seg003:3303                 mov     dx, 4722h
seg003:3306                 int     21h             ; DOS - 2+ - READ FROM FILE WITH HANDLE
seg003:3306                                         ; BX = file handle, CX = number of bytes to read
seg003:3306                                         ; DS:DX -> buffer
seg003:3308                 jb      short loc_134AF
seg003:330A                 cmp     ax, 2
seg003:330D                 jz      short loc_134C6
seg003:330F
seg003:330F loc_134AF:                              ; CODE XREF: routine_READ_BUG_BY_INDEX+37j
seg003:330F                                         ; routine_READ_BUG_BY_INDEX+7Ej ...
seg003:330F                 mov     some_error_code, 3
seg003:3315
seg003:3315 loc_134B5:                              ; CODE XREF: routine_READ_BUG_BY_INDEX+FDj
seg003:3315                 mov     bx, [bp+fileHandle]
seg003:3318                 mov     ah, 3Eh
seg003:331A                 int     21h             ; DOS - 2+ - CLOSE A FILE WITH HANDLE
seg003:331A                                         ; BX = file handle
seg003:331C                 call    sub_157AE
seg003:3321                 jmp     far ptr loc_1B8C4
seg003:3326 ; ---------------------------------------------------------------------------
seg003:3326
seg003:3326 loc_134C6:                              ; CODE XREF: routine_READ_BUG_BY_INDEX+3Cj
seg003:3326                 mov     dx, [bp+BUG_INDEX]
seg003:3329                 cmp     dx, TOTAL_BUGSPRITE_COUNT
seg003:332D                 jb      short loc_134DE
seg003:332F                 mov     bx, [bp+fileHandle]
seg003:3332                 mov     ah, 3Eh
seg003:3334                 int     21h             ; DOS - 2+ - CLOSE A FILE WITH HANDLE
seg003:3334                                         ; BX = file handle
seg003:3336                 call    sub_157AE
seg003:333B                 leave
seg003:333C                 stc
seg003:333D                 retf
seg003:333E ; ---------------------------------------------------------------------------
seg003:333E
seg003:333E loc_134DE:                              ; CODE XREF: routine_READ_BUG_BY_INDEX+5Cj
seg003:333E                 shl     dx, 1
seg003:3340                 shl     dx, 1
seg003:3342                 add     dx, 2
seg003:3345                 xor     cx, cx
seg003:3347                 mov     bx, [bp+fileHandle]
seg003:334A                 mov     ax, 4200h
seg003:334D                 int     21h             ; DOS - 2+ - MOVE FILE READ/WRITE POINTER (LSEEK)
seg003:334D                                         ; AL = method: offset from beginning of file
seg003:334F                 jb      short loc_134AF
seg003:3351                 mov     ah, 3Fh ; '?'
seg003:3353                 mov     bx, [bp+fileHandle]
seg003:3356                 mov     cx, 8
seg003:3359                 mov     dx, 4724h
seg003:335C                 int     21h             ; DOS - 2+ - READ FROM FILE WITH HANDLE
seg003:335C                                         ; BX = file handle, CX = number of bytes to read
seg003:335C                                         ; DS:DX -> buffer
seg003:335E                 jb      short loc_134AF
seg003:3360                 mov     ax, TOTAL_BUGSPRITE_COUNT
seg003:3363                 dec     ax
seg003:3364                 cmp     ax, [bp+BUG_INDEX]
seg003:3367                 jnz     short loc_1351A
seg003:3369                 mov     bx, [bp+fileHandle] ; if read LAST BUG in file ?
seg003:336C                 push    cs
seg003:336D                 call    near ptr sub_1366B ; seek to end of file
seg003:3370                 nop
seg003:3371                 jb      short loc_134AF
seg003:3373                 mov     nextoffset16low, ax ; set offset for "next"(non-existant bug)
seg003:3376                 mov     nextoffset16high, dx ; to end of BUGS file
seg003:337A
seg003:337A loc_1351A:                              ; CODE XREF: routine_READ_BUG_BY_INDEX+96j
seg003:337A                 mov     ax, 4200h
seg003:337D                 mov     bx, [bp+fileHandle]
seg003:3380                 mov     cx, offset16high
seg003:3384                 mov     dx, offset16low
seg003:3388                 int     21h             ; DOS - 2+ - MOVE FILE READ/WRITE POINTER (LSEEK)
seg003:3388                                         ; AL = method: offset from beginning of file
seg003:338A                 jb      short loc_134AF
seg003:338C                 mov     bx, nextoffset16low
seg003:3390                 mov     dx, nextoffset16high
seg003:3394                 sub     bx, offset16low
seg003:3398                 sbb     dx, offset16high
seg003:339C                 mov     [bp+bytesNeededForBugLow], bx
seg003:339F                 mov     [bp+bytesNeededForBugHigh], dx
seg003:33A2                 mov     ax, [bp+RAM_FOR_BUG_BYTES]
seg003:33A5                 or      ax, ax
seg003:33A7                 jnz     short loc_13577 ; already allocated?
seg003:33A9                 add     bx, 0Fh         ; calculate number of 16-byte-paragraphs needed
seg003:33AC                 adc     dx, 0
seg003:33AF                 shr     bx, 1
seg003:33B1                 shr     bx, 1
seg003:33B3                 shr     bx, 1
seg003:33B5                 shr     bx, 1
seg003:33B7                 shl     dx, 1
seg003:33B9                 shl     dx, 1
seg003:33BB                 shl     dx, 1
seg003:33BD                 shl     dx, 1
seg003:33BF                 or      bh, dl
seg003:33C1                 call    sub_14250       ; allocates RAM via DOS (expects 16-bytes-paragraph count)
seg003:33C6                 jnb     short loc_13574 ; at this point, RAM was successfully allocated for BUG
seg003:33C8                 mov     some_error_code, 1
seg003:33CE                 jmp     loc_134B5
seg003:33D1 ; ---------------------------------------------------------------------------
seg003:33D1                 jmp     loc_134AF
seg003:33D4 ; ---------------------------------------------------------------------------
seg003:33D4
seg003:33D4 loc_13574:                              ; CODE XREF: routine_READ_BUG_BY_INDEX+F5j
seg003:33D4                 mov     [bp+RAM_FOR_BUG_BYTES], ax ; at this point, RAM was successfully allocated for BUG
seg003:33D7
seg003:33D7 loc_13577:                              ; CODE XREF: routine_READ_BUG_BY_INDEX+D6j
seg003:33D7                 mov     bx, [bp+fileHandle]
seg003:33DA                 mov     cx, [bp+bytesNeededForBugLow]
seg003:33DD                 mov     dx, [bp+bytesNeededForBugHigh]
seg003:33E0                 push    cs
seg003:33E1                 call    near ptr routine_READ_BUG_BYTES ; ax = pointer to receive bug bytes
seg003:33E1                                         ; bx = file handle
seg003:33E1                                         ; cx = bytesneededcountLow
seg003:33E1                                         ; dx = bytesneededcountHigh
seg003:33E1                                         ;
seg003:33E4                 nop
seg003:33E5                 mov     bx, [bp+fileHandle]
seg003:33E8                 mov     ah, 3Eh
seg003:33EA                 int     21h             ; DOS - 2+ - CLOSE A FILE WITH HANDLE
seg003:33EA                                         ; BX = file handle
seg003:33EC                 call    sub_157AE
seg003:33F1                 mov     ax, [bp+RAM_FOR_BUG_BYTES] ; BUG BYTES were successfully read at this point
seg003:33F4                 mov     bx, [bp+bytesNeededForBugLow]
seg003:33F7                 mov     cx, [bp+bytesNeededForBugHigh]
seg003:33FA                 leave
seg003:33FB                 clc
seg003:33FC                 retf
seg003:33FC routine_READ_BUG_BY_INDEX endp


routine_READ_BUG_BYTES
Code:
seg003:3463 ; ax = pointer to receive bug bytes
seg003:3463 ; bx = file handle
seg003:3463 ; cx = bytesneededcountLow
seg003:3463 ; dx = bytesneededcountHigh
seg003:3463 ;
seg003:3463 ; Attributes: bp-based frame
seg003:3463
seg003:3463 routine_READ_BUG_BYTES proc far         ; CODE XREF: sub_133B9+9Cp
seg003:3463                                         ; routine_READ_BUG_BY_INDEX+110p
seg003:3463
seg003:3463 bytesNeededForBugHigh= word ptr -8
seg003:3463 bytesNeededForBugLow= word ptr -6
seg003:3463 fileHandle      = word ptr -4
seg003:3463 RAM_FOR_BUG_BYTES= word ptr -2
seg003:3463
seg003:3463                 enter   8, 0
seg003:3467                 mov     [bp+RAM_FOR_BUG_BYTES], ax
seg003:346A                 mov     [bp+fileHandle], bx
seg003:346D                 mov     [bp+bytesNeededForBugLow], cx
seg003:3470                 mov     [bp+bytesNeededForBugHigh], dx
seg003:3473                 push    ds
seg003:3474                 cmp     [bp+bytesNeededForBugHigh], 0 ; need to read more
seg003:3474                                         ; than one 64KB segment?
seg003:3478                 jz      short loc_1363F ; jump if need up to one segment only
seg003:347A
seg003:347A loc_1361A:                              ; CODE XREF: routine_READ_BUG_BYTES+3Aj
seg003:347A                 mov     ah, 3Fh ; '?'
seg003:347C                 mov     bx, [bp+fileHandle]
seg003:347F                 mov     cx, 0FFF0h
seg003:3482                 xor     dx, dx
seg003:3484                 mov     ds, [bp+RAM_FOR_BUG_BYTES]
seg003:3487                 int     21h             ; DOS - 2+ - READ FROM FILE WITH HANDLE
seg003:3487                                         ; BX = file handle, CX = number of bytes to read
seg003:3487                                         ; DS:DX -> buffer
seg003:3489                 jb      short loc_13658
seg003:348B                 cmp     ax, 0FFF0h
seg003:348E                 jnz     short loc_13658
seg003:3490                 add     [bp+RAM_FOR_BUG_BYTES], 0FFFh
seg003:3495                 sub     [bp+bytesNeededForBugLow], 0FFF0h
seg003:3499                 sbb     [bp+bytesNeededForBugHigh], 0
seg003:349D                 jg      short loc_1361A
seg003:349F
seg003:349F loc_1363F:                              ; CODE XREF: routine_READ_BUG_BYTES+15j
seg003:349F                 mov     ah, 3Fh ; '?'
seg003:34A1                 mov     bx, [bp+fileHandle]
seg003:34A4                 mov     cx, [bp+bytesNeededForBugLow]
seg003:34A7                 xor     dx, dx
seg003:34A9                 mov     ds, [bp+RAM_FOR_BUG_BYTES]
seg003:34AC                 int     21h             ; DOS - 2+ - READ FROM FILE WITH HANDLE
seg003:34AC                                         ; BX = file handle, CX = number of bytes to read
seg003:34AC                                         ; DS:DX -> buffer
seg003:34AE                 jb      short loc_13658
seg003:34B0                 cmp     ax, [bp+bytesNeededForBugLow]
seg003:34B3                 jnz     short loc_13658
seg003:34B5                 pop     ds
seg003:34B6                 leave
seg003:34B7                 retf
seg003:34B8 ; ---------------------------------------------------------------------------
seg003:34B8
seg003:34B8 loc_13658:                              ; CODE XREF: routine_READ_BUG_BYTES+26j
seg003:34B8                                         ; routine_READ_BUG_BYTES+2Bj ...
seg003:34B8                 pop     ds
seg003:34B9                 mov     some_error_code, 3
seg003:34BF                 mov     bx, [bp+fileHandle]
seg003:34C2                 mov     ah, 3Eh
seg003:34C4                 int     21h             ; DOS - 2+ - CLOSE A FILE WITH HANDLE
seg003:34C4                                         ; BX = file handle
seg003:34C6                 jmp     far ptr loc_1B8C4
seg003:34C6 routine_READ_BUG_BYTES endp

_________________
0xDB
View user's profile Send private message Visit poster's website
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1670
Location: Your consciousness.
PostPosted: Thu Apr 27, 2017 9:48 am    Post subject: Reply with quote

Doh! A day later after much confusion and long hours of following code manually, trying to find out what it does with those BUG bytes, I am sure those last two routines are much more generic in nature and not specifically related to reading BUG sprites only. At one point, the code was using the read bytes to set a palette, at another it initialized a MIDI playback routine with them... :P

So those routines should be called: READ_SOME_DATA_ITEM_BY_INDEX and READ_SOME_DATA_ITEM_BYTES instead.

Journey onward.
_________________
0xDB
View user's profile Send private message Visit poster's website
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1670
Location: Your consciousness.
PostPosted: Thu Apr 27, 2017 12:17 pm    Post subject: Reply with quote

So with these routines correctly identified, suddenly a lot of stuff that previously made no sense at all, now does (also thanks to continued reading of Abrash's Assembler book and cross referencing with Ralf Browns interrupt list).

The game seems to organize most of its data files with a header like this:
2 bytes: number N of data items inside the file
N * 4 bytes : offsets of items

When the game reads something, it does so by its index I in the file.
First it checks if there are even that many items in there, then reads the offsets for I and I+1(or in case of I being the last item in file, invents a 'next' offset at the end of the file).
It computes how much RAM it needs to allocate for the thing by subtracting the first offset from the next offset.
Then it proceeds to read the bytes into that newly allocated RAM.

With that newfound knowledge, I could finally find a place in the code, where it accesses the BUGS file:
Code:

routine_access_bugs_file_0 proc far     ; CODE XREF: sub_13176+1Ep
seg003:2FC3                                         ; sub_1BF60+48P ...
seg003:2FC3                 push    ax
seg003:2FC4                 mov     si, 50h ; 'P'   ; seg004:50h = 'bugs'
seg003:2FC7                 xor     bx, bx
seg003:2FC9                 push    cs
seg003:2FCA                 call    near ptr routine_READ_DATA_ITEM_BY_INDEX_fname_at_seg004_si
seg003:2FCD                 nop
seg003:2FCE                 pop     si
seg003:2FCF                 shl     si, 1
seg003:2FD1                 mov     [si+3E0h], ax
seg003:2FD5                 retf
seg003:2FD5 routine_access_bugs_file_0 endp


That's all for today. Will have to continue digging at that location tomorrow.

here's the corrected generic file item reading routines:
Code:

seg003:32D1 routine_READ_DATA_ITEM_BY_INDEX_fname_at_seg004_si proc far
seg003:32D1                                         ; CODE XREF: routine_READ_A_PALETTE+5P
seg003:32D1                                         ; load_palette_by_index+4FP ...
seg003:32D1
seg003:32D1 RAM_FOR_DATA_ITEM= word ptr -0Ah
seg003:32D1 bytesNeededForDataHigh= word ptr -8
seg003:32D1 bytesNeededForDataLow= word ptr -6
seg003:32D1 fileHandle      = word ptr -4
seg003:32D1 ITEM_INDEX      = word ptr -2
seg003:32D1 arg_471E        = word ptr  4724h
seg003:32D1
seg003:32D1                 enter   0Ah, 0
seg003:32D5                 mov     [bp+ITEM_INDEX], ax
seg003:32D8                 mov     [bp+RAM_FOR_DATA_ITEM], bx
seg003:32DB                 push    si
seg003:32DC                 call    sub_1577B
seg003:32E1                 pop     si
seg003:32E2                 push    cs
seg003:32E3                 call    near ptr open_file_name_at_seg0004_si
seg003:32E6                 nop
seg003:32E7                 jnb     short loc_13499
seg003:32E9                 mov     some_error_code, 2
seg003:32EF                 call    routine_restore_DOS_INT8
seg003:32F4                 jmp     far ptr loc_1B8C4
seg003:32F9 ; ---------------------------------------------------------------------------
seg003:32F9
seg003:32F9 loc_13499:                              ; CODE XREF: routine_READ_DATA_ITEM_BY_INDEX_fname_at_seg004_si+16j
seg003:32F9                 mov     [bp+fileHandle], ax
seg003:32FC                 mov     bx, ax
seg003:32FE                 mov     ah, 3Fh ; '?'
seg003:3300                 mov     cx, 2
seg003:3303                 mov     dx, 4722h       ; dseg:4722 = buffer for TOTAL_DATA_ITEMS_COUNT
seg003:3306                 int     21h             ; DOS - 2+ - READ FROM FILE WITH HANDLE
seg003:3306                                         ; BX = file handle, CX = number of bytes to read
seg003:3306                                         ; DS:DX -> buffer
seg003:3308                 jb      short loc_134AF
seg003:330A                 cmp     ax, 2
seg003:330D                 jz      short loc_134C6
seg003:330F
seg003:330F loc_134AF:                              ; CODE XREF: routine_READ_DATA_ITEM_BY_INDEX_fname_at_seg004_si+37j
seg003:330F                                         ; routine_READ_DATA_ITEM_BY_INDEX_fname_at_seg004_si+7Ej ...
seg003:330F                 mov     some_error_code, 3
seg003:3315
seg003:3315 loc_134B5:                              ; CODE XREF: routine_READ_DATA_ITEM_BY_INDEX_fname_at_seg004_si+FDj
seg003:3315                 mov     bx, [bp+fileHandle]
seg003:3318                 mov     ah, 3Eh
seg003:331A                 int     21h             ; DOS - 2+ - CLOSE A FILE WITH HANDLE
seg003:331A                                         ; BX = file handle
seg003:331C                 call    routine_restore_DOS_INT8
seg003:3321                 jmp     far ptr loc_1B8C4
seg003:3326 ; ---------------------------------------------------------------------------
seg003:3326
seg003:3326 loc_134C6:                              ; CODE XREF: routine_READ_DATA_ITEM_BY_INDEX_fname_at_seg004_si+3Cj
seg003:3326                 mov     dx, [bp+ITEM_INDEX]
seg003:3329                 cmp     dx, TOTAL_DATA_ITEMS_COUNT
seg003:332D                 jb      short loc_134DE
seg003:332F                 mov     bx, [bp+fileHandle]
seg003:3332                 mov     ah, 3Eh
seg003:3334                 int     21h             ; DOS - 2+ - CLOSE A FILE WITH HANDLE
seg003:3334                                         ; BX = file handle
seg003:3336                 call    routine_restore_DOS_INT8
seg003:333B                 leave
seg003:333C                 stc
seg003:333D                 retf
seg003:333E ; ---------------------------------------------------------------------------
seg003:333E
seg003:333E loc_134DE:                              ; CODE XREF: routine_READ_DATA_ITEM_BY_INDEX_fname_at_seg004_si+5Cj
seg003:333E                 shl     dx, 1
seg003:3340                 shl     dx, 1
seg003:3342                 add     dx, 2
seg003:3345                 xor     cx, cx
seg003:3347                 mov     bx, [bp+fileHandle]
seg003:334A                 mov     ax, 4200h
seg003:334D                 int     21h             ; DOS - 2+ - MOVE FILE READ/WRITE POINTER (LSEEK)
seg003:334D                                         ; AL = method: offset from beginning of file
seg003:334F                 jb      short loc_134AF
seg003:3351                 mov     ah, 3Fh ; '?'
seg003:3353                 mov     bx, [bp+fileHandle]
seg003:3356                 mov     cx, 8
seg003:3359                 mov     dx, 4724h       ; dseg:4724 = buffer for two 32bit offsets
seg003:3359                                         ; offset16low,offset16high,nextoffset16low,nextoffset16high
seg003:335C                 int     21h             ; DOS - 2+ - READ FROM FILE WITH HANDLE
seg003:335C                                         ; BX = file handle, CX = number of bytes to read
seg003:335C                                         ; DS:DX -> buffer
seg003:335E                 jb      short loc_134AF
seg003:3360                 mov     ax, TOTAL_DATA_ITEMS_COUNT
seg003:3363                 dec     ax
seg003:3364                 cmp     ax, [bp+ITEM_INDEX]
seg003:3367                 jnz     short loc_1351A
seg003:3369                 mov     bx, [bp+fileHandle] ; if read LAST ITEM in file ?
seg003:336C                 push    cs
seg003:336D                 call    near ptr sub_1366B ; seek to end of file
seg003:3370                 nop
seg003:3371                 jb      short loc_134AF
seg003:3373                 mov     nextoffset16low, ax ; set offset for "next"(non-existant item)
seg003:3376                 mov     nextoffset16high, dx ; to end of DATA file
seg003:337A
seg003:337A loc_1351A:                              ; CODE XREF: routine_READ_DATA_ITEM_BY_INDEX_fname_at_seg004_si+96j
seg003:337A                 mov     ax, 4200h
seg003:337D                 mov     bx, [bp+fileHandle]
seg003:3380                 mov     cx, offset16high
seg003:3384                 mov     dx, offset16low
seg003:3388                 int     21h             ; DOS - 2+ - MOVE FILE READ/WRITE POINTER (LSEEK)
seg003:3388                                         ; AL = method: offset from beginning of file
seg003:338A                 jb      short loc_134AF
seg003:338C                 mov     bx, nextoffset16low
seg003:3390                 mov     dx, nextoffset16high
seg003:3394                 sub     bx, offset16low
seg003:3398                 sbb     dx, offset16high
seg003:339C                 mov     [bp+bytesNeededForDataLow], bx
seg003:339F                 mov     [bp+bytesNeededForDataHigh], dx
seg003:33A2                 mov     ax, [bp+RAM_FOR_DATA_ITEM]
seg003:33A5                 or      ax, ax
seg003:33A7                 jnz     short loc_13577 ; already allocated?
seg003:33A9                 add     bx, 0Fh         ; calculate number of 16-byte-paragraphs needed
seg003:33AC                 adc     dx, 0
seg003:33AF                 shr     bx, 1
seg003:33B1                 shr     bx, 1
seg003:33B3                 shr     bx, 1
seg003:33B5                 shr     bx, 1
seg003:33B7                 shl     dx, 1
seg003:33B9                 shl     dx, 1
seg003:33BB                 shl     dx, 1
seg003:33BD                 shl     dx, 1
seg003:33BF                 or      bh, dl
seg003:33C1                 call    sub_14250       ; allocates RAM via DOS (expects 16-bytes-paragraph count)
seg003:33C6                 jnb     short loc_13574 ; at this point, RAM was successfully allocated for data item
seg003:33C8                 mov     some_error_code, 1
seg003:33CE                 jmp     loc_134B5
seg003:33D1 ; ---------------------------------------------------------------------------
seg003:33D1                 jmp     loc_134AF
seg003:33D4 ; ---------------------------------------------------------------------------
seg003:33D4
seg003:33D4 loc_13574:                              ; CODE XREF: routine_READ_DATA_ITEM_BY_INDEX_fname_at_seg004_si+F5j
seg003:33D4                 mov     [bp+RAM_FOR_DATA_ITEM], ax ; at this point, RAM was successfully allocated for data item
seg003:33D7
seg003:33D7 loc_13577:                              ; CODE XREF: routine_READ_DATA_ITEM_BY_INDEX_fname_at_seg004_si+D6j
seg003:33D7                 mov     bx, [bp+fileHandle]
seg003:33DA                 mov     cx, [bp+bytesNeededForDataLow]
seg003:33DD                 mov     dx, [bp+bytesNeededForDataHigh]
seg003:33E0                 push    cs
seg003:33E1                 call    near ptr routine_READ_DATA_ITEM_BYTES ; ax = pointer to receive bug bytes
seg003:33E1                                         ; bx = file handle
seg003:33E1                                         ; cx = bytesneededcountLow
seg003:33E1                                         ; dx = bytesneededcountHigh
seg003:33E1                                         ;
seg003:33E4                 nop
seg003:33E5                 mov     bx, [bp+fileHandle]
seg003:33E8                 mov     ah, 3Eh
seg003:33EA                 int     21h             ; DOS - 2+ - CLOSE A FILE WITH HANDLE
seg003:33EA                                         ; BX = file handle
seg003:33EC                 call    routine_restore_DOS_INT8
seg003:33F1                 mov     ax, [bp+RAM_FOR_DATA_ITEM] ; DATA BYTES were successfully read at this point
seg003:33F4                 mov     bx, [bp+bytesNeededForDataLow]
seg003:33F7                 mov     cx, [bp+bytesNeededForDataHigh]
seg003:33FA                 leave
seg003:33FB                 clc
seg003:33FC                 retf
seg003:33FC routine_READ_DATA_ITEM_BY_INDEX_fname_at_seg004_si endp


Code:

seg003:3411 open_file_name_at_seg0004_si proc far   ; CODE XREF: sub_133B9+Fp
seg003:3411                                         ; routine_READ_DATA_ITEM_BY_INDEX_fname_at_seg004_si+12p ...
seg003:3411                 mov     seg004_offset_filename_source, si
seg003:3415                 call    copy_string_es_seg004_si_to_dssi
seg003:341A                 mov     dx, 47F2h
seg003:341D                 mov     ax, 3D00h
seg003:3420                 int     21h             ; DOS - 2+ - OPEN DISK FILE WITH HANDLE
seg003:3420                                         ; DS:DX -> ASCIZ filename
seg003:3420                                         ; AL = access mode
seg003:3420                                         ; 0 - read
seg003:3422                 retf
seg003:3422 open_file_name_at_seg0004_si endp


Code:

seg003:3864 copy_string_es_seg004_si_to_dssi proc far
seg003:3864                                         ; CODE XREF: open_file_name_at_seg0004_si+4P
seg003:3864                                         ; sub_135C3+DP ...
seg003:3864                 mov     ax, seg seg004
seg003:3867                 mov     es, ax
seg003:3869                 assume es:seg004
seg003:3869                 mov     di, file_name_buffer
seg003:386D
seg003:386D loc_13A0D:                              ; CODE XREF: copy_string_es_seg004_si_to_dssi+12j
seg003:386D                 mov     al, es:[si]
seg003:3870                 mov     [di], al
seg003:3872                 inc     si
seg003:3873                 inc     di
seg003:3874                 or      al, al
seg003:3876                 jnz     short loc_13A0D
seg003:3878                 retf
seg003:3878 copy_string_es_seg004_si_to_dssi endp


Code:

seg003:3463 ; ax = pointer to receive data bytes
seg003:3463 ; bx = file handle
seg003:3463 ; cx = bytesneededcountLow
seg003:3463 ; dx = bytesneededcountHigh
seg003:3463 ;
seg003:3463 ; Attributes: bp-based frame
seg003:3463
seg003:3463 routine_READ_DATA_ITEM_BYTES proc far   ; CODE XREF: sub_133B9+9Cp
seg003:3463                                         ; routine_READ_DATA_ITEM_BY_INDEX_fname_at_seg004_si+110p
seg003:3463
seg003:3463 bytesNeededForDataHigh= word ptr -8
seg003:3463 bytesNeededForDataLow= word ptr -6
seg003:3463 fileHandle      = word ptr -4
seg003:3463 RAM_FOR_DATA_BYTES= word ptr -2
seg003:3463
seg003:3463                 enter   8, 0
seg003:3467                 mov     [bp+RAM_FOR_DATA_BYTES], ax
seg003:346A                 mov     [bp+fileHandle], bx
seg003:346D                 mov     [bp+bytesNeededForDataLow], cx
seg003:3470                 mov     [bp+bytesNeededForDataHigh], dx
seg003:3473                 push    ds
seg003:3474                 cmp     [bp+bytesNeededForDataHigh], 0 ; need to read more
seg003:3474                                         ; than one 64KB segment?
seg003:3478                 jz      short loc_1363F ; jump if need up to one segment only
seg003:347A
seg003:347A loc_1361A:                              ; CODE XREF: routine_READ_DATA_ITEM_BYTES+3Aj
seg003:347A                 mov     ah, 3Fh ; '?'
seg003:347C                 mov     bx, [bp+fileHandle]
seg003:347F                 mov     cx, 0FFF0h
seg003:3482                 xor     dx, dx
seg003:3484                 mov     ds, [bp+RAM_FOR_DATA_BYTES]
seg003:3487                 int     21h             ; DOS - 2+ - READ FROM FILE WITH HANDLE
seg003:3487                                         ; BX = file handle, CX = number of bytes to read
seg003:3487                                         ; DS:DX -> buffer
seg003:3489                 jb      short loc_13658
seg003:348B                 cmp     ax, 0FFF0h
seg003:348E                 jnz     short loc_13658
seg003:3490                 add     [bp+RAM_FOR_DATA_BYTES], 0FFFh
seg003:3495                 sub     [bp+bytesNeededForDataLow], 0FFF0h
seg003:3499                 sbb     [bp+bytesNeededForDataHigh], 0
seg003:349D                 jg      short loc_1361A
seg003:349F
seg003:349F loc_1363F:                              ; CODE XREF: routine_READ_DATA_ITEM_BYTES+15j
seg003:349F                 mov     ah, 3Fh ; '?'
seg003:34A1                 mov     bx, [bp+fileHandle]
seg003:34A4                 mov     cx, [bp+bytesNeededForDataLow]
seg003:34A7                 xor     dx, dx
seg003:34A9                 mov     ds, [bp+RAM_FOR_DATA_BYTES]
seg003:34AC                 int     21h             ; DOS - 2+ - READ FROM FILE WITH HANDLE
seg003:34AC                                         ; BX = file handle, CX = number of bytes to read
seg003:34AC                                         ; DS:DX -> buffer
seg003:34AE                 jb      short loc_13658
seg003:34B0                 cmp     ax, [bp+bytesNeededForDataLow]
seg003:34B3                 jnz     short loc_13658
seg003:34B5                 pop     ds
seg003:34B6                 leave
seg003:34B7                 retf
seg003:34B8 ; ---------------------------------------------------------------------------
seg003:34B8
seg003:34B8 loc_13658:                              ; CODE XREF: routine_READ_DATA_ITEM_BYTES+26j
seg003:34B8                                         ; routine_READ_DATA_ITEM_BYTES+2Bj ...
seg003:34B8                 pop     ds
seg003:34B9                 mov     some_error_code, 3
seg003:34BF                 mov     bx, [bp+fileHandle]
seg003:34C2                 mov     ah, 3Eh
seg003:34C4                 int     21h             ; DOS - 2+ - CLOSE A FILE WITH HANDLE
seg003:34C4                                         ; BX = file handle
seg003:34C6                 jmp     far ptr loc_1B8C4
seg003:34C6 routine_READ_DATA_ITEM_BYTES endp

_________________
0xDB
View user's profile Send private message Visit poster's website
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1670
Location: Your consciousness.
PostPosted: Fri Apr 28, 2017 12:11 am    Post subject: Reply with quote

The bug reading routine appears to get fed its information from the level reading routine...

Code:

...
seg003:2F50 loc_130F0:                              ; CODE XREF: access_levels_file_1+14j
seg003:2F50                 mov     bx, word_52C4
seg003:2F54                 mov     si, 5Fh ; '_'   ; seg004:5fh = 'levels'
seg003:2F57                 push    cs
seg003:2F58                 call    near ptr routine_READ_DATA_ITEM_BY_INDEX_fname_at_seg004_si
seg003:2F5B                 nop
seg003:2F5C                 mov     es, ax          ; ax points at level bytes now
seg003:2F5E                 xor     si, si
seg003:2F60                 mov     cx, es:[si]     ; es:si = levelbytes:0
seg003:2F63                 or      cx, cx          ; test first 2bytes in levelbytes for 0 (BUG count?)
seg003:2F65                 jz      short locret_13162 ; if 0 skip loading any BUGS
seg003:2F67                 add     si, 2           ; otherwise proceed to levelbytes[2]
seg003:2F6A
seg003:2F6A loop_to_load_bugs:                      ; CODE XREF: access_levels_file_1+64j
seg003:2F6A                 push    cx              ; save BUG count
seg003:2F6B                 push    es              ; save levelbytes pointer
seg003:2F6C                 mov     ax, es:[si]     ; BUG index at levelbytes:bug_info_chunk_i:[0..1]
seg003:2F6F                 add     si, 2
seg003:2F72                 mov     bx, es:[si]     ; levelbytes:bug_info_chunk_i:[2..3]
seg003:2F75                 add     si, 2
seg003:2F78                 mov     cx, es:[si]     ; levelbytes:bug_info_chunk_i:[4..5]
seg003:2F7B                 add     si, 2
seg003:2F7E                 mov     dx, es:[si]     ; levelbytes:bug_info_chunk_i:[6..7]
seg003:2F81                 add     si, 2
seg003:2F84                 mov     di, es:[si]     ; levelbytes:bug_info_chunk_i:[8..9]
seg003:2F87                 add     si, 2
seg003:2F8A                 mov     es, word ptr es:[si] ; levelbytes:bug_info_chunk_i:[10..11]
seg003:2F8D                 add     si, 2           ; next bug_info_chunk at levelbytes + 2 + i * 12
seg003:2F90                 push    si              ; save byte  position for next iteration
seg003:2F91                 mov     si, di
seg003:2F93                 mov     di, es
seg003:2F95                 call    just_calls_routine_load_ax_bug
seg003:2F9A                 pop     si              ; restore byte index for levelbytes
seg003:2F9B                 pop     es              ; restore levelbytes pointer
seg003:2F9C                 pop     cx              ; restore BUG count
seg003:2F9D                 loop    loop_to_load_bugs ; cx-1 , loops until cx = 0
...


...don't know what the bug_info_chunk pieces are used for yet, except the first two bytes which contain the data item index for the BUGS file.

As I explore the code, I keep a textfile open where I keep notes for whatever piece I'm currently trying to make sense of, so I can track and trace where those bytes are put and hopefully later see what they're being used for to give them meaningful names which then in turn make code elsewhere more readable. It's like the fog of war in a strategy game, each little bit of exploration reveals another tiny piece of the big picture.
Code:

levelbytes:
0,1: BUG count (BC)
then BC times
  BUG INFO:
    0,1: BUG index (data item index for BUGS file) -> ax
    2,3: unknown -> bx
    4,5: unknown -> cx
    6,7: unknown -> dx
    8,9: unknown -> di
  10,11: unknown -> es
 
di -> si
es -> di

_________________
0xDB
View user's profile Send private message Visit poster's website
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1670
Location: Your consciousness.
PostPosted: Fri Apr 28, 2017 2:33 am    Post subject: Reply with quote

I've been staring at this piece for quite a while now after finally tracking down the first actual access to the bytes for a BUG read from BUGS...but it isn't 'doing' anything interesting with them yet. :P

Code:

...
seg008:0B2E                 xor     ax, ax
seg008:0B30                 push    ax
seg008:0B31                 push    ax
seg008:0B32                 push    ax
seg008:0B33                 mov     di, [si+438h]   ; di <- bug index
seg008:0B37                 shl     di, 1           ; *2
seg008:0B39                 mov     es, word ptr [di+3E0h] ; es = pointer to BUG BYTES
seg008:0B39                                         ; which where read from BUGS by seg008:0A28
seg008:0B3D                 assume ss:nothing
seg008:0B3D                 mov     di, 0
seg008:0B40                 mov     ax, es:[di]     ; read the first two bug bytes
seg008:0B43                 push    ax              ; push bugbyte[0..1]
seg008:0B44                 push    es              ; push ptr to bugbytes
seg008:0B45                 mov     ax, 348h        ; 840 dec
seg008:0B48                 push    ax              ; push 840
seg008:0B49                 mov     ax, [bp+bug_info_chunk_6and7]
seg008:0B4C                 add     ax, 218h        ; 536 dec + bug_info_chunk_6and7
seg008:0B4F                 xor     ax, 0FFFFh      ; invert
seg008:0B52                 push    ax              ; push inverted 536 + bug_info_chunk_6and7
seg008:0B53                 mov     cx, [bp+bug_info_chunk_4and5]
seg008:0B56                 mov     dx, [bp+bug_info_chunk_6and7]
seg008:0B59                 sub     dx, word_3FBE
seg008:0B5D                 sub     dx, [si+1374h]
seg008:0B61                 push    dx              ; push 'something' about bug_info_chunk_6and7
seg008:0B62                 sub     cx, word_3FBC
seg008:0B66                 push    cx              ; push 'something b' about bug_info_chunk_4and5
seg008:0B67                 call    sub_1807A
...


Just looking at all those mystery calculations almost made me want to give up but after some confusion about all those 'push' statements... (there are many more)... I started putting down a fragmented representation of the stack in my notes, hoping to learn what it's all used for later down.

Code:

2 'something b' about bug_info_chunk_4and5  <-- SP upon call sub_1807A
2 'something' about bug_info_chunk_6and7
2 inverted 536 + bug_info_chunk_6and7
2 840 dec
2 ptr to bugbytes
2 bugbyte[0..1]
... a gazillion more of mystery parameters... (***)
----------------------------
stack grows downwards in RAM (up in this representation)


So yeah with that in the stack it calls yet another mystery subroutine and I need to figure out what it does with the stack.

Already figured it uses BP+arg_x to access the parameters after initializing BP with the unmodified SP from the callee (edit: No wait, since it first pushes BP itself again, and then loads it with SP, the first two bytes in the BP+x addressing inside the routine just see the saved base pointer and then the previously pushed parameters follow).

So... will have to track back some more to find all the (***).

Lost count of how many times the mind has been thinking "I must be close" over the past couple of days.

Code:

...
seg003:7EDA sub_1807A       proc far                ; CODE XREF: sub_11A63+71P
seg003:7EDA                                         ; routine_load_ax_bug+187P ...
seg003:7EDA
seg003:7EDA arg_0           = word ptr  6
seg003:7EDA arg_2           = word ptr  8
seg003:7EDA arg_4           = word ptr  0Ah
seg003:7EDA arg_6           = word ptr  0Ch
seg003:7EDA arg_8           = word ptr  0Eh
seg003:7EDA arg_A           = word ptr  10h
seg003:7EDA arg_C           = word ptr  12h
seg003:7EDA arg_E           = word ptr  14h
seg003:7EDA arg_10          = word ptr  16h
seg003:7EDA
seg003:7EDA                 push    bp
seg003:7EDB                 mov     bp, sp
...

_________________
0xDB


Edited by 0xDB on Fri Apr 28, 2017 3:41 am; edited 1 time
View user's profile Send private message Visit poster's website
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1670
Location: Your consciousness.
PostPosted: Fri Apr 28, 2017 3:39 am    Post subject: Reply with quote

Was wondering why the first local arg_0 is +6 there and not +2... reading up on the behavior of the 'call' instruction solved that. It pushes CS and IP implicitly (at least in 8086 real mode which is what Battle Bugs uses) before jumping, so at seg0003:7EDB the relevant portion of the stack should look like this and I can see exactly where the parameters came from now (now to investigate what they do/mean):
Code:

new BP+0  2 saved BP                                  <-- SP and new BP (for parameters)
+2  2 IP (done via call)
+4  2 CS (done via call)
+6  2 'something b' about bug_info_chunk_4and5  <-- SP upon call    sub_1807A
+8  2 'something' about bug_info_chunk_6and7
+0A 2 inverted 536 + bug_info_chunk_6and7
+0C 2 840 dec
+0E 2 ptr to bugbytes
+10 2 bugbyte[0..1]
+12 2 00 00
+14 2 00 00
+16 2 00 00
----------------------------
stack grows downwards in RAM (up in this representation)

_________________
0xDB
View user's profile Send private message Visit poster's website
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1670
Location: Your consciousness.
PostPosted: Fri Apr 28, 2017 5:18 am    Post subject: Reply with quote

And with renaming the locals in that procedure according to the stack locations used in this particular call, shit does not make much more sense than before.

The fact that this procedure gets called from all over the place in the rest of the code, makes me think it is another one of the generic routines, not specifically related to bug graphic data but perhaps to all sorts of graphic data.

It scans, word by word, some area in the current data segment for a magic value xx80h and then somehow uses the found location as a base for various address calculations in the same data segment where it then writes down some of the passed parameters, sometimes the same parameter twice in different locations.

The hardcoded offsets seem to suggest that all it does there is fill some structs... likely some bookkeeping information about the loaded stuff (about bugs in this instance)... so it still is not 'using' the bytes read from BUGS.

Mind: "I must be getting close though." :P

Code:

seg003:7EDA sub_1807A       proc far                ; CODE XREF: sub_11A63+71P
seg003:7EDA                                         ; routine_load_ax_bug+187P ...
seg003:7EDA
seg003:7EDA modified_bug_info_chunk_4and5= word ptr  6
seg003:7EDA modified_bug_info_chunk_6and7= word ptr  8
seg003:7EDA bug_info_chunk_6and7_pl536dec_inverted= word ptr  0Ah
seg003:7EDA decimal_840     = word ptr  0Ch
seg003:7EDA ptr_bug_bytes   = word ptr  0Eh
seg003:7EDA bugbytes0_and_1 = word ptr  10h
seg003:7EDA arg_C_00        = word ptr  12h
seg003:7EDA arg_E_00        = word ptr  14h
seg003:7EDA arg_10_00       = word ptr  16h
seg003:7EDA
seg003:7EDA                 push    bp
seg003:7EDB                 mov     bp, sp
seg003:7EDD                 cld                     ; df -->
seg003:7EDE                 mov     si, 8E46h
seg003:7EE1                 mov     cx, 1CCh        ; 460 dec
seg003:7EE4
seg003:7EE4 find_80xx:                              ; CODE XREF: sub_1807A+Fj
seg003:7EE4                 lodsw                   ; loads word into ax from ds:si, si+=2
seg003:7EE5                 test    al, 80h
seg003:7EE7                 jz      short loc_18090 ; if ds:si == 80h proceed
seg003:7EE9                 loop    find_80xx
seg003:7EEB                 pop     bp
seg003:7EEC                 stc
seg003:7EED                 retf    12h             ; return and discard 18 bytes from stack
seg003:7EF0 ; ---------------------------------------------------------------------------
seg003:7EF0
seg003:7EF0 loc_18090:                              ; CODE XREF: sub_1807A+Dj
seg003:7EF0                 mov     bx, 1CCh
seg003:7EF3                 sub     bx, cx
seg003:7EF5                 shl     bx, 1
seg003:7EF7                 mov     cx, [bp+modified_bug_info_chunk_4and5]
seg003:7EFA                 mov     [bx-6E22h], cx
seg003:7EFE                 mov     dx, [bp+modified_bug_info_chunk_6and7]
seg003:7F01                 mov     [bx-6A8Ah], dx
seg003:7F05                 mov     ax, [bp+bug_info_chunk_6and7_pl536dec_inverted]
seg003:7F08                 mov     [bx-66F2h], ax
seg003:7F0C                 mov     [bx-635Ah], ax
seg003:7F10                 mov     ax, [bp+decimal_840]
seg003:7F13                 or      ax, 80h         ; ax ends up as 3c8 = 968 dec
seg003:7F16                 mov     [bx-71BAh], ax
seg003:7F1A                 mov     ax, [bp+ptr_bug_bytes]
seg003:7F1D                 mov     [bx-54FAh], ax
seg003:7F21                 mov     [bx-4DCAh], ax
seg003:7F25                 mov     si, [bp+bugbytes0_and_1]
seg003:7F28                 mov     [bx-5162h], si
seg003:7F2C                 mov     [bx-4A32h], si
seg003:7F30                 mov     ax, [bp+arg_C_00]
seg003:7F33                 mov     [bx-144Ah], ax
seg003:7F37                 mov     ax, [bp+arg_E_00]
seg003:7F3A                 mov     [bx-10B2h], ax
seg003:7F3E                 mov     ax, [bp+arg_10_00]
seg003:7F41                 mov     [bx-0D1Ah], ax
seg003:7F45                 call    sub_18140
seg003:7F48                 pop     bp
seg003:7F49                 clc
seg003:7F4A                 retf    12h             ; return and discard 18 bytes from stack
seg003:7F4A sub_1807A       endp

_________________
0xDB
View user's profile Send private message Visit poster's website
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1670
Location: Your consciousness.
PostPosted: Fri Apr 28, 2017 6:38 am    Post subject: Reply with quote

Ok... mind is royally grilled for the day. Defeated for the moment... but I will be back!

Mystery numbers are mysterious...

_________________
0xDB
View user's profile Send private message Visit poster's website
PoV
Moderator

Joined: 21 Aug 2005
Posts: 10904
Location: Canadia
PostPosted: Fri Apr 28, 2017 9:33 am    Post subject: Reply with quote

This is a neat project. :)
_________________
Mike Kasprzak
'eh whatever. I used to make AAA and Indie games | Ludum Dare | Blog | Tweetar
View user's profile Send private message
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1670
Location: Your consciousness.
PostPosted: Sat Apr 29, 2017 1:42 am    Post subject: Reply with quote

Yeah, it's like a good puzzle game. :)

I figured it was pointless for the moment to try to follow all those dynamic RAM allocations and tracking where they would be used again without first gathering more knowledge, so I went back and analyzed some bits and pieces around where the code calls the video interrupts to set screen modes and together with some screenshots analyzation tried to make sense of it, identifying those variables in hope of seeing them pop up later in some drawing routines.

That's all for today.



Code:

seg003:3533
seg003:3533 ; --------------- S U B R O U T I N E ---------------------------------------
seg003:3533
seg003:3533
seg003:3533 sub_136D3       proc far                ; CODE XREF: start+D4P
seg003:3533                                         ; sub_1F0BC+3CABP ...
seg003:3533                 cmp     use_mode_102h_800x600_flag, 0
seg003:3538                 jz      short loc_136E0
seg003:353A                 call    init_video_mode800x600
seg003:353D                 jmp     short loc_136E3
seg003:353D ; ---------------------------------------------------------------------------
seg003:353F                 align 2
seg003:3540
seg003:3540 loc_136E0:                              ; CODE XREF: sub_136D3+5j
seg003:3540                 call    init_video_mode640x480
seg003:3543
seg003:3543 loc_136E3:                              ; CODE XREF: sub_136D3+Aj
seg003:3543                 mov     consta_0, 0
seg003:3548                 mov     constb_0, 0
seg003:354D                 mov     al, 48h ; 'H'
seg003:354F                 mul     const_0Bh
seg003:3553                 mov     tmp_72x11_792_dec, ax
seg003:3556                 mov     al, 18h         ; 24
seg003:3558                 mul     _14dec_inLowRes_17dec_inHighRes
seg003:355C                 mov     _dec336_inLowRes_408_inHighRes, ax
seg003:355F                 mov     ax, _neg72dec_inLowRes_0_inHighRes
seg003:3562                 add     ax, tmp_72x11_792_dec
seg003:3566                 sub     ax, 48h ; 'H'
seg003:3569                 mov     _dec648_inLowRes_720_inHighRes, ax
seg003:356C                 mov     ax, _neg24dec_inLowRes_0_inHighRes_a
seg003:356F                 add     ax, _dec336_inLowRes_408_inHighRes
seg003:3573                 sub     ax, 18h
seg003:3576                 mov     _dec288_inLowRes_384_inHighRes, ax
seg003:3579                 retf
seg003:3579 sub_136D3       endp
seg003:3579
seg003:357A
seg003:357A ; --------------- S U B R O U T I N E ---------------------------------------
seg003:357A
seg003:357A
seg003:357A init_video_mode640x480 proc near        ; CODE XREF: sub_136D3:loc_136E0p
seg003:357A                 mov     screen_width_pixels, 280h
seg003:3580                 mov     in_game_used_screen_width_pixels, 280h
seg003:3586                 mov     screen_bytes_per_line_per_plane, 50h ; 'P'
seg003:358C                 mov     screen_height_pixels, 1E0h
seg003:3592                 mov     const_0Bh, 0Bh
seg003:3597                 mov     _14dec_inLowRes_17dec_inHighRes, 0Eh
seg003:359C                 mov     _neg72dec_inLowRes_0_inHighRes, 0FFB8h ; -72
seg003:35A2                 mov     _neg24dec_inLowRes_0_inHighRes_a, 0FFE8h ; -24
seg003:35A8                 mov     in_game_main_view_height_pixels, 120h
seg003:35AE                 mov     _neg9dec_inLowRes_0_inHighRes, 0FFF7h ; -9
seg003:35B4                 mov     _dec89_inLowRes_99_inHighRes, 59h ; 'Y'
seg003:35BA                 mov     _neg24dec_inLowRes_0_inHighRes_b, 0FFE8h ; -24
seg003:35C0                 mov     _dec311_inLowRes_407_inHighRes, 137h
seg003:35C6                 mov     al, 12h
seg003:35C8                 call    set_VGA_mode_al
seg003:35CD                 call    blacken_VGA_palette
seg003:35D2                 mov     bx, 280h
seg003:35D5                 mov     dx, 1E0h
seg003:35D8                 call    remember_screen_dims
seg003:35DD                 mov     ax, 120h
seg003:35E0                 mov     ch, 18h
seg003:35E2                 mov     cl, 9
seg003:35E4                 mov     bx, 64h ; 'd'
seg003:35E7                 retn
seg003:35E7 init_video_mode640x480 endp
seg003:35E7
seg003:35E8
seg003:35E8 ; --------------- S U B R O U T I N E ---------------------------------------
seg003:35E8
seg003:35E8
seg003:35E8 init_video_mode800x600 proc near        ; CODE XREF: sub_136D3+7p
seg003:35E8                 mov     screen_width_pixels, 320h
seg003:35EE                 mov     in_game_used_screen_width_pixels, 318h
seg003:35F4                 mov     screen_bytes_per_line_per_plane, 64h ; 'd'
seg003:35FA                 mov     screen_height_pixels, 258h
seg003:3600                 mov     const_0Bh, 0Bh
seg003:3605                 mov     _14dec_inLowRes_17dec_inHighRes, 11h
seg003:360A                 mov     _neg72dec_inLowRes_0_inHighRes, 0
seg003:3610                 mov     _neg24dec_inLowRes_0_inHighRes_a, 0
seg003:3616                 mov     in_game_main_view_height_pixels, 198h
seg003:361C                 mov     _neg9dec_inLowRes_0_inHighRes, 0
seg003:3622                 mov     _dec89_inLowRes_99_inHighRes, 63h ; 'c'
seg003:3628                 mov     _neg24dec_inLowRes_0_inHighRes_b, 0
seg003:362E                 mov     _dec311_inLowRes_407_inHighRes, 197h
seg003:3634                 mov     ax, use_mode_102h_800x600_flag
seg003:3637                 call    set_SVGA_mode_102h
seg003:363C                 call    blacken_VGA_palette
seg003:3641                 mov     bx, 320h
seg003:3644                 mov     dx, 258h
seg003:3647                 call    remember_screen_dims
seg003:364C                 retn
seg003:364C init_video_mode800x600 endp

_________________
0xDB
View user's profile Send private message Visit poster's website
Sirocco
Moderator

Joined: 19 Aug 2005
Posts: 9461
Location: Not Finland
PostPosted: Sat Apr 29, 2017 5:46 am    Post subject: Reply with quote

Holy fucking shit.

I go away for a few days, and the entire thread explodes with opcodes :D

Makes my head hurt just thinking about it too... heh.
_________________
NoOP / Reyn Time -- The $ is screwing everyone these days. (0xDB)
View user's profile Send private message Visit poster's website
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1670
Location: Your consciousness.
PostPosted: Mon May 01, 2017 1:58 pm    Post subject: Reply with quote

Aye, this stuff can be brain-melting. I'm currently wading through the code at the entry address, evaluating line by line, following it down into every subroutine, naming more locations (often like 'something_about_data_item_bytes0and1' or 'couldbe_this_and_that') just so that I can try to make sense of it later instead of just seeing numbers everywhere without knowing whether I've met that address before.
_________________
0xDB
View user's profile Send private message Visit poster's website
Sirocco
Moderator

Joined: 19 Aug 2005
Posts: 9461
Location: Not Finland
PostPosted: Tue May 02, 2017 4:49 am    Post subject: Reply with quote

I also find it pretty wild that I totally missed out on this game. It came out in 1994 and got a US release, but somehow flew under my radar :/
_________________
NoOP / Reyn Time -- The $ is screwing everyone these days. (0xDB)
View user's profile Send private message Visit poster's website
PoV
Moderator

Joined: 21 Aug 2005
Posts: 10904
Location: Canadia
PostPosted: Tue May 02, 2017 8:19 am    Post subject: Reply with quote

I also completely missed this game, but to be fair I didn't have access to much PC stuff back then (I was 14). I had a single PC Zone magazine with Cannon Fodder on a Coverdisk though. I thought that was cool.
_________________
Mike Kasprzak
'eh whatever. I used to make AAA and Indie games | Ludum Dare | Blog | Tweetar
View user's profile Send private message
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1670
Location: Your consciousness.
PostPosted: Tue May 02, 2017 11:59 am    Post subject: Reply with quote

Battle Bugs, Wolfenstein3D and Stunts(aka 4D Sports Driving) were the games that made me want to upgrade from C64/Amiga500 to PC Gaming. Don't recall exactly but probably did not get one until mid 95 or something and it still had Windows 3.x on it. A friend of mine had one first and we'd often meet after school to break our heads over some of the more challenging Battle Bugs missions and back in school, instead of paying attention we drew tons of Battle Bugs scenes in our school books... sadly all that art is lost. :D

Still trying to make sense of it but I feel like I will have to end up analyzing almost all of it to even get close to making sense of the graphics loading stuff.

Today I spent a couple of hours identifying and then naming/documenting where it initializes EMM stuff, which was extra fun because apparently segments can be resized at runtime, so at first I could not find ds:SOMETHINGs... all the SOMETHINGs for the EMM stuff were located beyond the segment as it must have appeared at compiletime.

deceptive data segment is deceptive:
Code:

dseg:FEBA this_is_not_the_true_end_of_dseg_it_gets_resized_by_init: ; TEARS! :P
dseg:FEBA                 align 8
dseg:FEBA dseg            ends ; ...not. ^_^
dseg:FEBA
seg001:0000 ; ---------------------------------------------------------------------------
seg001:0000
seg001:0000 ; Segment type: Regular
seg001:0000 seg001          segment byte public 'UNK' use16
seg001:0000                 assume cs:seg001
seg001:0000                 assume es:nothing, ss:nothing, ds:dseg, fs:nothing, gs:nothing
seg001:0000 emm_page_frame_segment dw 0             ; DATA XREF: load_check_emm_driver_and_map_logical_3_2_1_0_to_physical3_2_1_0:EMM_not_available_or_not_readyw
seg001:0000                                         ; load_check_emm_driver_and_map_logical_3_2_1_0_to_physical3_2_1_0+6Ew ...
seg001:0002 emm_pages_unallocated dw 0              ; DATA XREF: load_check_emm_driver_and_map_logical_3_2_1_0_to_physical3_2_1_0+7Aw
seg001:0004 emm_pages_requested_is_0Ch dw 0         ; DATA XREF: load_check_emm_driver_and_map_logical_3_2_1_0_to_physical3_2_1_0w
seg001:0004                                         ; load_check_emm_driver_and_map_logical_3_2_1_0_to_physical3_2_1_0+7Er ...
seg001:0006 emm_handle_to_allocated_pages dw 0      ; DATA XREF: emm_map_physicalpages3_2_1_0_to_logicalpages_bxMUL4ADD3_etc_+15r
seg001:0006                                         ; load_check_emm_driver_and_map_logical_3_2_1_0_to_physical3_2_1_0+5w ...
seg001:0008 emm_currently_mapped_logical_pages_group dw 0
seg001:0008                                         ; DATA XREF: emm_map_physicalpages3_2_1_0_to_logicalpages_bxMUL4ADD3_etc_r
seg001:0008                                         ; emm_map_physicalpages3_2_1_0_to_logicalpages_bxMUL4ADD3_etc_+6w ...


EMM STUFF in init:
Code:

seg003:A720 ; --------------- S U B R O U T I N E ---------------------------------------
seg003:A720
seg003:A720
seg003:A720 emm_map_physicalpages3_2_1_0_to_logicalpages_bxMUL4ADD3_etc_ proc far
seg003:A720                                         ; CODE XREF: access_soundfx_file+1DP
seg003:A720                                         ; sub_15A37+21P ...
seg003:A720                 cmp     bx, ds:0FEC8h
seg003:A724                 jz      short locret_1A8E8
seg003:A726                 mov     ds:0FEC8h, bx
seg003:A72A                 shl     bx, 1
seg003:A72C                 shl     bx, 1
seg003:A72E                 add     bl, 3           ; bx = bx * 4 + 3
seg003:A731                 mov     al, 3
seg003:A733
seg003:A733 loc_1A8D3:                              ; CODE XREF: emm_map_physicalpages3_2_1_0_to_logicalpages_bxMUL4ADD3_etc_+26j
seg003:A733                 mov     ah, 44h ; 'D'
seg003:A735                 mov     dx, ds:0FEC6h
seg003:A739                 push    ax
seg003:A73A                 push    bx
seg003:A73B                 int     67h             ;  - LIM EMS - MAP MEMORY
seg003:A73B                                         ; AL = physical page number (0-3)
seg003:A73B                                         ; BX = logical page number, DX = handle
seg003:A73B                                         ; Return: AH = status
seg003:A73D                 or      ah, ah
seg003:A73F                 pop     bx
seg003:A740                 pop     ax
seg003:A741                 jnz     short locret_1A8E8
seg003:A743                 dec     bx              ; proceed to next lower logical page
seg003:A744                 dec     al              ; proceed to next lower physical page
seg003:A746                 jge     short loc_1A8D3
seg003:A748
seg003:A748 locret_1A8E8:                           ; CODE XREF: emm_map_physicalpages3_2_1_0_to_logicalpages_bxMUL4ADD3_etc_+4j
seg003:A748                                         ; emm_map_physicalpages3_2_1_0_to_logicalpages_bxMUL4ADD3_etc_+21j
seg003:A748                 retf
seg003:A748 emm_map_physicalpages3_2_1_0_to_logicalpages_bxMUL4ADD3_etc_ endp
seg003:A748
seg003:A749
seg003:A749 ; --------------- S U B R O U T I N E ---------------------------------------
seg003:A749
seg003:A749
seg003:A749 load_check_emm_driver_and_map_logical_3_2_1_0_to_physical3_2_1_0 proc far
seg003:A749                                         ; CODE XREF: start:loc_1B5D4P
seg003:A749                 mov     ds:0FEC4h, ax
seg003:A74C                 xor     dx, dx
seg003:A74E                 mov     ds:0FEC6h, dx
seg003:A752                 dec     dx
seg003:A753                 mov     ds:0FEC8h, dx   ; init this to -1
seg003:A757                 cmp     ax, 4
seg003:A75A                 jb      short EMM_not_available_or_not_ready
seg003:A75C                 push    ds
seg003:A75D                 mov     dx, 0A7F9h
seg003:A760                 mov     ax, cs
seg003:A762                 mov     ds, ax
seg003:A764                 assume ds:seg003
seg003:A764                 mov     ax, 3D00h       ; seg003:0a7f9 constains zt-string 'EMMXXXX'
seg003:A767                 int     21h             ; DOS - 2+ - OPEN DISK FILE WITH HANDLE
seg003:A767                                         ; DS:DX -> ASCIZ filename
seg003:A767                                         ; AL = access mode
seg003:A767                                         ; 0 - read
seg003:A769                 pop     ds
seg003:A76A                 assume ds:dseg
seg003:A76A                 jb      short EMM_not_available_or_not_ready
seg003:A76C                 mov     bx, ax          ; the returned file handle from open put into bx
seg003:A76E                 mov     ax, 4400h
seg003:A771                 push    bx
seg003:A772                 int     21h             ; DOS - 2+ - IOCTL - GET DEVICE INFORMATION
seg003:A772                                         ; BX = file or device handle
seg003:A774                 pop     bx
seg003:A775                 jb      short EMMXXXX_file_not_opened
seg003:A777                 test    dx, 80h
seg003:A77B                 jnz     short loc_1A92A
seg003:A77D
seg003:A77D EMMXXXX_file_not_opened:                ; CODE XREF: load_check_emm_driver_and_map_logical_3_2_1_0_to_physical3_2_1_0+2Cj
seg003:A77D                                         ; load_check_emm_driver_and_map_logical_3_2_1_0_to_physical3_2_1_0+48j
seg003:A77D                 mov     ah, 3Eh
seg003:A77F                 int     21h             ; DOS - 2+ - CLOSE A FILE WITH HANDLE
seg003:A77F                                         ; BX = file handle
seg003:A781
seg003:A781 EMM_not_available_or_not_ready:         ; CODE XREF: load_check_emm_driver_and_map_logical_3_2_1_0_to_physical3_2_1_0+11j
seg003:A781                                         ; load_check_emm_driver_and_map_logical_3_2_1_0_to_physical3_2_1_0+21j ...
seg003:A781                 mov     word ptr ds:0FEC0h, 0
seg003:A787                 jmp     short emm_check_return
seg003:A787 ; ---------------------------------------------------------------------------
seg003:A789                 align 2
seg003:A78A
seg003:A78A loc_1A92A:                              ; CODE XREF: load_check_emm_driver_and_map_logical_3_2_1_0_to_physical3_2_1_0+32j
seg003:A78A                 mov     ax, 4407h
seg003:A78D                 push    bx
seg003:A78E                 int     21h             ; DOS - 2+ - IOCTL - get output status
seg003:A78E                                         ; cf clear if success
seg003:A78E                                         ; al = status 00 not ready, ff ready
seg003:A790                 pop     bx
seg003:A791                 jb      short EMMXXXX_file_not_opened
seg003:A793                 or      al, al
seg003:A795                 jz      short EMM_not_available_or_not_ready
seg003:A797                 mov     ah, 3Eh
seg003:A799                 int     21h             ; DOS - 2+ - CLOSE A FILE WITH HANDLE
seg003:A799                                         ; BX = file handle
seg003:A79B                 mov     ah, 40h ; '@'
seg003:A79D                 int     67h             ;  - LIM EMS - GET MANAGER STATUS
seg003:A79D                                         ; Return: AH = status
seg003:A79F                 or      ah, ah
seg003:A7A1                 jnz     short EMM_not_available_or_not_ready
seg003:A7A3                 mov     ah, 46h ; 'F'
seg003:A7A5                 int     67h             ;  - LIM EMS - GET EMM VERSION
seg003:A7A5                                         ; Return: AH = status
seg003:A7A7                 or      ah, ah
seg003:A7A9                 jnz     short EMM_not_available_or_not_ready
seg003:A7AB                 cmp     al, 30h ; '0'
seg003:A7AD                 jb      short EMM_not_available_or_not_ready
seg003:A7AF                 mov     ah, 41h ; 'A'
seg003:A7B1                 int     67h             ;  - LIM EMS - GET PAGE FRAME SEGMENT
seg003:A7B1                                         ; Return: AH = 00h function successful,
seg003:A7B1                                         ; BX = segment of page frame
seg003:A7B1                                         ; AH = error code
seg003:A7B3                 or      ah, ah
seg003:A7B5                 jnz     short EMM_not_available_or_not_ready
seg003:A7B7                 mov     ds:0FEC0h, bx
seg003:A7BB                 mov     ah, 42h ; 'B'
seg003:A7BD                 int     67h             ;  - LIM EMS - GET NUMBER OF PAGES
seg003:A7BD                                         ; Return: AH = 00h function successful,
seg003:A7BD                                         ; BX = number of unallocated pages
seg003:A7BD                                         ; DX = total number of pages
seg003:A7BD                                         ; AH = error code
seg003:A7BF                 or      ah, ah
seg003:A7C1                 jnz     short EMM_not_available_or_not_ready
seg003:A7C3                 mov     ds:0FEC2h, bx
seg003:A7C7                 cmp     bx, ds:0FEC4h
seg003:A7CB                 jb      short EMM_not_available_or_not_ready
seg003:A7CD                 mov     ah, 43h ; 'C'
seg003:A7CF                 mov     bx, ds:0FEC4h
seg003:A7D3                 int     67h             ;  - LIM EMS - GET HANDLE AND ALLOCATE MEMORY
seg003:A7D3                                         ; BX = number of logical pages to allocate
seg003:A7D3                                         ; Return: AH = status, DX: handle if ah==00
seg003:A7D5                 or      ah, ah
seg003:A7D7                 jnz     short EMM_not_available_or_not_ready
seg003:A7D9                 mov     ds:0FEC6h, dx   ; save handle to allocated emm pages
seg003:A7DD                 mov     ah, 4Ch ; 'L'
seg003:A7DF                 int     67h             ;  - LIM EMS - GET PAGES OWNED BY HANDLE
seg003:A7DF                                         ; DX = EMM handle
seg003:A7DF                                         ; Return: AH = status
seg003:A7DF                                         ; BX = number of owned pages if ah==00
seg003:A7E1                 or      ah, ah
seg003:A7E3                 jz      short emm_init_succeeded
seg003:A7E5
seg003:A7E5 loc_1A985:                              ; CODE XREF: load_check_emm_driver_and_map_logical_3_2_1_0_to_physical3_2_1_0+A7j
seg003:A7E5                 push    cs
seg003:A7E6                 call    near ptr cleanup_emm_stuff
seg003:A7E9                 nop
seg003:A7EA                 jmp     short EMM_not_available_or_not_ready
seg003:A7EC ; ---------------------------------------------------------------------------
seg003:A7EC
seg003:A7EC emm_init_succeeded:                     ; CODE XREF: load_check_emm_driver_and_map_logical_3_2_1_0_to_physical3_2_1_0+9Aj
seg003:A7EC                 cmp     bx, ds:0FEC4h   ; make sure one last time the number of owned pages
seg003:A7EC                                         ; are equal to the number of requested pages
seg003:A7F0                 jnz     short loc_1A985
seg003:A7F2                 xor     bx, bx
seg003:A7F4                 push    cs
seg003:A7F5                 call    near ptr emm_map_physicalpages3_2_1_0_to_logicalpages_bxMUL4ADD3_etc_
seg003:A7F8
seg003:A7F8 emm_check_return:                       ; CODE XREF: load_check_emm_driver_and_map_logical_3_2_1_0_to_physical3_2_1_0+3Ej
seg003:A7F8                 retf
seg003:A7F8 load_check_emm_driver_and_map_logical_3_2_1_0_to_physical3_2_1_0 endp
seg003:A7F8
seg003:A7F8 ; ---------------------------------------------------------------------------
seg003:A7F9 zstr_emmxxxx_file_name db  45h ; E
seg003:A7FA                 db  4Dh ; M
seg003:A7FB                 db  4Dh ; M
seg003:A7FC                 db  58h ; X
seg003:A7FD                 db  58h ; X
seg003:A7FE                 db  58h ; X
seg003:A7FF                 db  58h ; X
seg003:A800                 db  30h ; 0
seg003:A801                 db    0
seg003:A802
seg003:A802 ; --------------- S U B R O U T I N E ---------------------------------------
seg003:A802
seg003:A802
seg003:A802 cleanup_emm_stuff proc far              ; CODE XREF: load_check_emm_driver_and_map_logical_3_2_1_0_to_physical3_2_1_0+9Dp
seg003:A802                                         ; start+38BP
seg003:A802                 cmp     word ptr ds:0FEC0h, 0
seg003:A807                 jz      short loc_1A9D1
seg003:A809                 cmp     word ptr ds:0FEC6h, 0
seg003:A80E                 jz      short loc_1A9D1
seg003:A810                 xor     bx, bx
seg003:A812                 push    cs
seg003:A813                 call    near ptr emm_map_physicalpages3_2_1_0_to_logicalpages_bxMUL4ADD3_etc_
seg003:A816                 mov     cx, 3
seg003:A819
seg003:A819 loc_1A9B9:                              ; CODE XREF: cleanup_emm_stuff+25j
seg003:A819                 mov     ah, 45h ; 'E'
seg003:A81B                 mov     dx, ds:0FEC6h
seg003:A81F                 push    cx
seg003:A820                 int     67h             ;  - LIM EMS - RELEASE HANDLE AND MEMORY
seg003:A820                                         ; DX = EMM handle
seg003:A820                                         ; Return: AH = status
seg003:A822                 pop     cx
seg003:A823                 or      ah, ah
seg003:A825                 jz      short loc_1A9CB
seg003:A827                 loop    loc_1A9B9
seg003:A829                 stc
seg003:A82A                 retf
seg003:A82B ; ---------------------------------------------------------------------------
seg003:A82B
seg003:A82B loc_1A9CB:                              ; CODE XREF: cleanup_emm_stuff+23j
seg003:A82B                 mov     word ptr ds:0FEC6h, 0
seg003:A831
seg003:A831 loc_1A9D1:                              ; CODE XREF: cleanup_emm_stuff+5j
seg003:A831                                         ; cleanup_emm_stuff+Cj
seg003:A831                 clc
seg003:A832                 retf
seg003:A832 cleanup_emm_stuff endp

_________________
0xDB
View user's profile Send private message Visit poster's website
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1670
Location: Your consciousness.
PostPosted: Wed May 03, 2017 12:29 am    Post subject: Reply with quote

Five blue stray dogs times salted paintbrush divided by slightly less than a handful of unusally noisy snails.

That's to illustrate how much sense most of the code makes before analyzation. Yesterday, I stared at a blotch of soap in my hand for a solid minute while the mind tried to decipher its value and meaning. I think it even started to make sense before it snapped out of it and realized there was nothing to decode there.
_________________
0xDB
View user's profile Send private message Visit poster's website
Diablo
Contributor

Joined: 19 Nov 2015
Posts: 350
Location: :( :(
PostPosted: Wed May 03, 2017 5:47 am    Post subject: Reply with quote

Have you thought about going back to trying to parse the files like you did with the cards? Could you find a few open-source games from the same time period and see how they might have approached loading sprite sheets? Maybe you could find a common theme to the logic of the time that would help in unpacking the data in the bugs game.
View user's profile Send private message Visit poster's website
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1670
Location: Your consciousness.
PostPosted: Wed May 03, 2017 12:34 pm    Post subject: Reply with quote

Yeah, spent countless hours staring at glorious pixel garbage with that approach. Looking at open source DOS games from the era is an interesting idea, would not know where to start looking though and I think the chance to accidentally stumble upon a game that uses the exact same encoding is very low.

As long as I keep identifying a couple of routines a day and naming more and more locations, I should figure this out eventually. Today I found some timer related stuff and sound/midi loading and conversion to output hardware routines and I feel like I have a good grasp of how the game utilizes the EMM pages it allocates and where it stores control information about that. The more variables I identify for other stuff, the closer I will get to finding the graphics/sprites related things.
_________________
0xDB
View user's profile Send private message Visit poster's website
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1670
Location: Your consciousness.
PostPosted: Thu May 04, 2017 3:16 am    Post subject: Reply with quote

An excerpt of how far I have identified stuff in the startup routine...

Code:

...
seg008:0000                 public start
seg008:0000 start           proc near
seg008:0000                 mov     ax, seg dseg
seg008:0003
seg008:0003 loc_1B583:
seg008:0003                 mov     ds, ax
seg008:0005                 assume ds:dseg
seg008:0005
seg008:0005 loc_1B585:
seg008:0005                 mov     di, 4772h
seg008:0008
seg008:0008 loc_1B588:
seg008:0008                 call    cp_40h_bytes_0000_0080h_to_dseg_4772h
seg008:000D
seg008:000D loc_1B58D:
seg008:000D                 mov     di, 47F2h
seg008:0010                 call    sub_1A864
seg008:0015
seg008:0015 loc_1B595:
seg008:0015                 mov     file_name_buffer, di
seg008:0019                 push    es
seg008:001A                 call    save_dos_interrupt_vector00
seg008:001F                 mov     dx, 344h        ; cs:344h points to cleanup section
seg008:0022
seg008:0022 loc_1B5A2:                              ; sets termination handler to clean up section
seg008:0022                 call    set_dos_int_vector_22_to_cs_dx
seg008:0027                 mov     dx, 344h        ; cs:344h points to clean up section
seg008:002A                 call    set_dos_int_vector_24_to_cs_dx ; sets critical error handler to clean up section
seg008:002F
seg008:002F loc_1B5AF:
seg008:002F                 mov     dx, 344h
seg008:0032
seg008:0032 loc_1B5B2:
seg008:0032                 call    set_dos_interrupt_vector00
seg008:0037                 pop     es
seg008:0038                 mov     saved_video_mode, 0FFh
seg008:003D                 mov     bx, seg seg011
seg008:0040                 nop
seg008:0041                 call    dos_adjust_memory_block_size_to_seg011_minus_es
seg008:0046
seg008:0046 loc_1B5C6:
seg008:0046                 call    zero_mem_dseg_03e0to4772
seg008:004B
seg008:004B loc_1B5CB:
seg008:004B                 mov     const_240dec_after_init, 0FFFFh
seg008:0051                 mov     ax, 0Ch         ; requested number of pages to allocate by emm
seg008:0054
seg008:0054 loc_1B5D4:
seg008:0054                 call    load_check_emm_driver_and_map_logical_3_2_1_0_to_physical3_2_1_0
seg008:0059
seg008:0059 loc_1B5D9:
seg008:0059                 call    read_bbconfig_dat
seg008:005E                 call    init_and_hide_mouse_cursor
seg008:0063
seg008:0063 loc_1B5E3:
seg008:0063                 mov     num_mouse_buttons, bx
seg008:0067                 mov     ax, bx
seg008:0069                 mov     bh, 0Ch
seg008:006B                 mov     cx, 0E0Dh
seg008:006E                 call    calls_init_some_globals
seg008:0073                 call    store_video_mode_and_font_info
seg008:0078
seg008:0078 loc_1B5F8:
seg008:0078                 cmp     bbconfig_related_A, 0
seg008:007D                 jnz     short loc_1B607
seg008:007F
seg008:007F loc_1B5FF:
seg008:007F                 call    check_mode_102h_availability
seg008:0084                 mov     use_mode_102h_800x600_flag, ax
seg008:0087
seg008:0087 loc_1B607:                              ; CODE XREF: start+7Dj
seg008:0087                 call    access_drivers_file
seg008:008C                 call    save_dosint8_and_dseg
seg008:0091                 call    dos_extender_get_linear_base_address_cs
seg008:0096                 call    load_soundfx_indices2_1_0_to_emm_pages_11to0_4pages_per_sfx_item_and_convert_to_hardware_format
seg008:009B                 call    something_about_records_bin
seg008:00A0                 xor     ax, ax
seg008:00A2                 mov     records_bin_related_a, ax
seg008:00A5                 mov     word_472C, ax
seg008:00A8                 inc     ax
seg008:00A9                 mov     records_bin_related_c, ax
seg008:00AC                 mov     records_bin_related_b, 0FFh
seg008:00B2
seg008:00B2 loc_1B632:                              ; CODE XREF: sub_23385:loc_233DEj
seg008:00B2                 call    something_about_timer0_and_int8h
seg008:00B7                 call    calls_set_vga_write_mode_rotate_mode_bitmask_and_planes
seg008:00BC                 mov     bx, 280h        ; 640 dec
seg008:00BF                 mov     dx, 1E0h        ; 480 dec
seg008:00C2                 cmp     use_mode_102h_800x600_flag, 0
seg008:00C7                 jz      short loc_1B64F
seg008:00C9                 mov     bx, 320h        ; 800 dec
seg008:00CC                 mov     dx, 258h        ; 600 dec
seg008:00CF
seg008:00CF loc_1B64F:                              ; CODE XREF: start+C7j
seg008:00CF                 call    far ptr clear_some_stuff_and_prep_screen
seg008:00D4                 call    initialize_video_mode
...


...and a (much longer) excerpt of what's left to identify (some names pop up here and there already) so a vague image of the top-level structure of the program without all the routines deep down already starts to form.

Code:

seg008:00D9                 call    sub_2B2C6
seg008:00DC                 call    sub_13813
seg008:00E1                 xor     ax, ax
seg008:00E3                 mov     word_4760, ax
seg008:00E6                 mov     word_4730, ax
seg008:00E9                 mov     word_4746, ax
seg008:00EC                 mov     word_4748, ax
seg008:00EF                 dec     ax
seg008:00F0                 mov     word_4632, ax
seg008:00F3                 mov     word_44FC, ax
seg008:00F6                 mov     word_4698, ax
seg008:00F9                 mov     word_3E7A, ax
seg008:00FC                 mov     word_4678, ax
seg008:00FF                 mov     word_46D6, ax
seg008:0102                 mov     word_46D8, ax
seg008:0105                 call    read_gfx_file_item_index17h_and_permstr_file
seg008:010A                 call    do_something_with_gfx_item_17h
seg008:010F                 cmp     num_mouse_buttons, 0
seg008:0114                 jnz     short loc_1B69F
seg008:0116
seg008:0116 loc_1B696:
seg008:0116                 mov     some_error_code, 4
seg008:011C                 jmp     some_init_problem
seg008:011F ; ---------------------------------------------------------------------------
seg008:011F
seg008:011F loc_1B69F:                              ; CODE XREF: start+114j
seg008:011F                 mov     ax, use_mode_102h_800x600_flag
seg008:0122                 call    check_conv_mem_depending_on_video_mode
seg008:0127                 jnb     short loc_1B6B2
seg008:0129                 mov     some_error_code, 1
seg008:012F                 jmp     some_init_problem
seg008:0132 ; ---------------------------------------------------------------------------
seg008:0132
seg008:0132 loc_1B6B2:                              ; CODE XREF: start+127j
seg008:0132                 test    word_4762, 40h
seg008:0138                 jnz     short loc_1B6E3
seg008:013A                 call    routine_restore_DOS_INT8
seg008:013F                 test    word_4762, 400h
seg008:0145                 jnz     short loc_1B6CC
seg008:0147                 call    sub_10675
seg008:014C
seg008:014C loc_1B6CC:                              ; CODE XREF: start+145j
seg008:014C                 call    sub_10A16
seg008:0151                 and     word_4762, 0FBBFh
seg008:0157                 or      ax, ax
seg008:0159                 jz      short loc_1B6DE
seg008:015B                 jmp     loc_1B7A2
seg008:015E ; ---------------------------------------------------------------------------
seg008:015E
seg008:015E loc_1B6DE:                              ; CODE XREF: start+159j
seg008:015E                 call    something_about_timer0_and_int8h
seg008:0163
seg008:0163 loc_1B6E3:                              ; CODE XREF: start+138j
seg008:0163                 cmp     records_bin_related_c, 1
seg008:0168                 jnz     short loc_1B6F7
seg008:016A                 test    word_4762, 800h
seg008:0170                 jnz     short loc_1B6F7
seg008:0172                 call    sub_1157E
seg008:0177
seg008:0177 loc_1B6F7:                              ; CODE XREF: start+168j
seg008:0177                                         ; start+170j
seg008:0177                 and     word_4762, 0F7FFh
seg008:017D                 cmp     use_mode_102h_800x600_flag, 0
seg008:0182                 jnz     short loc_1B713
seg008:0184                 mov     ax, 120h        ; 288
seg008:0187                 mov     ch, 18h         ; 24
seg008:0189                 mov     cl, 9
seg008:018B                 mov     bx, 64h ; 'd'   ; 100
seg008:018E                 call    sub_18F3F
seg008:0193
seg008:0193 loc_1B713:                              ; CODE XREF: start+182j
seg008:0193                 call    sub_26D90
seg008:0196
seg008:0196 loc_1B716:
seg008:0196                 call    sub_13377
seg008:019B                 call    sub_14B80
seg008:01A0                 xor     ax, ax
seg008:01A2                 call    access_tiles_and_levels_files
seg008:01A5                 jnb     short loc_1B72A
seg008:01A7                 jmp     some_init_problem
seg008:01AA ; ---------------------------------------------------------------------------
seg008:01AA
seg008:01AA loc_1B72A:                              ; CODE XREF: start+1A5j
seg008:01AA                 xor     ax, ax
seg008:01AC                 xor     bx, bx
seg008:01AE                 les     si, dword_3FAE
seg008:01B2                 add     si, 37h ; '7'
seg008:01B5                 mov     al, es:[si]
seg008:01B8                 inc     si
seg008:01B9                 mov     bl, es:[si]
seg008:01BC                 call    sub_14BE0
seg008:01C1                 call    blacken_VGA_palette
seg008:01C6                 cmp     records_bin_related_c, 1
seg008:01CB                 jz      short loc_1B762
seg008:01CD                 mov     ax, word_473E
seg008:01D0                 mov     word_4AAA, ax
seg008:01D3                 mov     ax, word_4740
seg008:01D6                 mov     word_4AAC, ax
seg008:01D9                 mov     word_4762, 20h ; ' '
seg008:01DF
seg008:01DF loc_1B75F:
seg008:01DF                 jmp     short loc_1B776
seg008:01DF ; ---------------------------------------------------------------------------
seg008:01E1                 align 2
seg008:01E2
seg008:01E2 loc_1B762:                              ; CODE XREF: start+1CBj
seg008:01E2                 mov     dx, word_473C
seg008:01E6                 mov     word_4AAA, dx
seg008:01EA                 mov     word_4762, 0
seg008:01F0                 or      word_4760, 8000h
seg008:01F6
seg008:01F6 loc_1B776:                              ; CODE XREF: start:loc_1B75Fj
seg008:01F6                 call    access_levels_file_4
seg008:01FB                 call    sub_13F1B
seg008:0200                 call    access_levels_file_1
seg008:0205                 call    sub_2502E
seg008:0208                 call    sub_20055
seg008:020B                 call    sub_28610
seg008:020E                 mov     bx, const_240dec_after_init
seg008:0212                 call    sub_1873A
seg008:0217                 call    routine_restore_DOS_INT8
seg008:021C                 or      word_4762, 4000h
seg008:0222
seg008:0222 loc_1B7A2:                              ; CODE XREF: start+15Bj
seg008:0222                 call    sub_1F089
seg008:0225                 call    sub_13A19
seg008:022A                 call    sub_22C76
seg008:022D                 mov     word_4738, 0
seg008:0233
seg008:0233 loc_1B7B3:
seg008:0233                 test    word_4762, 4000h
seg008:0239                 jz      short loc_1B7D0
seg008:023B                 and     word_4762, 0BFFFh
seg008:0241                 mov     ax, word_472C
seg008:0244                 or      ax, records_bin_related_b
seg008:0248                 jnz     short loc_1B7D0
seg008:024A                 mov     ax, 15h
seg008:024D                 call    sub_22B95
seg008:0250
seg008:0250 loc_1B7D0:                              ; CODE XREF: start+239j
seg008:0250                                         ; start+248j
seg008:0250                 test    word_4762, 20h
seg008:0256                 jnz     short loc_1B7DE
seg008:0258
seg008:0258 loc_1B7D8:
seg008:0258                 call    sub_22A41
seg008:025B                 jmp     short loc_1B83E
seg008:025B ; ---------------------------------------------------------------------------
seg008:025D                 align 2
seg008:025E
seg008:025E loc_1B7DE:                              ; CODE XREF: start+256j
seg008:025E                 mov     ax, 9
seg008:0261
seg008:0261 loc_1B7E1:                              ; CODE XREF: start+2B1j
seg008:0261                 call    sub_22B95
seg008:0264                 call    sub_22A41
seg008:0267                 call    get_some_timing_tick
seg008:026C
seg008:026C loc_1B7EC:
seg008:026C                 mov     timing_tick_a, dx
seg008:0270
seg008:0270 loc_1B7F0:                              ; CODE XREF: start+28Dj
seg008:0270                 call    sub_1BABF
seg008:0273                 call    sub_1F0BC
seg008:0276                 call    sub_1F219
seg008:0279                 call    sub_206B5
seg008:027C                 call    sub_1BAF2
seg008:027F
seg008:027F loc_1B7FF:
seg008:027F                 call    get_some_timing_tick
seg008:0284                 call    sub_2620E
seg008:0287                 test    word_4762, 20h
seg008:028D                 jnz     short loc_1B7F0
seg008:028F                 xor     word_4730, 1
seg008:0294                 jz      short loc_1B833
seg008:0296                 or      word_4762, 20h
seg008:029B                 call    sub_2143E
seg008:029E                 mov     si, word_46D6
seg008:02A2                 or      si, si
seg008:02A4                 jl      short loc_1B829
seg008:02A6                 call    sub_26400
seg008:02A9
seg008:02A9 loc_1B829:                              ; CODE XREF: start+2A4j
seg008:02A9                 call    sub_14260
seg008:02AE                 mov     ax, 0Ah
seg008:02B1                 jmp     short loc_1B7E1
seg008:02B3 ; ---------------------------------------------------------------------------
seg008:02B3
seg008:02B3 loc_1B833:                              ; CODE XREF: start+294j
seg008:02B3                 call    sub_14323
seg008:02B8                 mov     ax, 0Bh
seg008:02BB                 call    sub_22B95
seg008:02BE
seg008:02BE loc_1B83E:                              ; CODE XREF: start+25Bj
seg008:02BE                 call    get_some_timing_tick
seg008:02C3                 mov     timing_tick_a, dx
seg008:02C7                 call    sub_14FB5
seg008:02CC
seg008:02CC loc_1B84C:                              ; CODE XREF: start:loc_1B8ADj
seg008:02CC                                         ; start+342j
seg008:02CC                 call    sub_1BABF
seg008:02CF                 call    sub_1F0BC
seg008:02D2                 call    sub_1F219
seg008:02D5                 call    sub_206B5
seg008:02D8                 call    sub_1BAF2
seg008:02DB                 call    sub_26CA7
seg008:02DE                 call    sub_2A69C
seg008:02E1                 call    get_some_timing_tick
seg008:02E6                 call    sub_2620E
seg008:02E9                 test    word_4760, 0FF7Fh
seg008:02EF                 jnz     short loc_1B8AF
seg008:02F1                 test    word_4762, 31Bh
seg008:02F7                 jnz     short loc_1B8AF
seg008:02F9                 inc     word_474C
seg008:02FD                 or      word_4762, 4
seg008:0302                 call    sub_1C822
seg008:0305                 call    sub_26F4E
seg008:0308                 call    sub_275DD
seg008:030B                 call    sub_265D1
seg008:030E                 call    sub_23FF9
seg008:0311                 test    word_474C, 0Fh
seg008:0317
seg008:0317 loc_1B897:
seg008:0317                 jnz     short loc_1B8A3
seg008:0319                 call    sub_14FB5
seg008:031E
seg008:031E loc_1B89E:
seg008:031E                 call    sub_1B963
seg008:0321                 jb      short loc_1B8AF
seg008:0323
seg008:0323 loc_1B8A3:                              ; CODE XREF: start:loc_1B897j
seg008:0323                 cmp     records_bin_related_c, 1
seg008:0328                 jnz     short loc_1B8AD
seg008:032A                 call    sub_28737
seg008:032D
seg008:032D loc_1B8AD:                              ; CODE XREF: start+328j
seg008:032D                                         ; start+339j
seg008:032D                 jmp     short loc_1B84C
seg008:032F ; ---------------------------------------------------------------------------
seg008:032F
seg008:032F loc_1B8AF:                              ; CODE XREF: start+2EFj
seg008:032F                                         ; start+2F7j ...
seg008:032F                 inc     word_474E
seg008:0333                 test    word_4762, 8
seg008:0339                 jz      short loc_1B8AD
seg008:033B                 inc     word_474C
seg008:033F                 call    sub_1C822
seg008:0342                 jmp     short loc_1B84C
seg008:0344 ; ---------------------------------------------------------------------------
seg008:0344
seg008:0344 some_init_problem:                      ; CODE XREF: seg003:079CJ
seg008:0344                                         ; sub_127A3+17J ...
seg008:0344                 mov     ax, seg dseg
seg008:0347                 mov     ds, ax
seg008:0349                 call    sub_12FDF
seg008:034E                 mov     ax, some_error_code
seg008:0351                 or      ax, div_by_zero_happened
seg008:0355                 jnz     short loc_1B8E6
seg008:0357                 call    sub_125DF
seg008:035C                 call    sub_12603
seg008:0361                 call    free_records_bin_buffer
seg008:0366
seg008:0366 loc_1B8E6:                              ; CODE XREF: start+355j
seg008:0366                 call    sub_1555B
seg008:036B                 call    sub_1556D
seg008:0370                 call    sub_156E5
seg008:0375                 call    sub_105A4
seg008:037A                 call    restore_video_mode_and_font_info
seg008:037F                 call    sub_22C76
seg008:0382                 call    load_ax_with_EMM_page_frame_segment
seg008:0387                 or      ax, ax
seg008:0389                 jz      short loc_1B912
seg008:038B                 call    cleanup_emm_stuff
seg008:0390                 jnb     short $+2
seg008:0392
seg008:0392 loc_1B912:                              ; CODE XREF: start+389j
seg008:0392                 cmp     div_by_zero_happened, 0
seg008:0397                 jz      short loc_1B91F
seg008:0399                 mov     bx, 5
seg008:039C                 jmp     short loc_1B940
seg008:039C ; ---------------------------------------------------------------------------
seg008:039E                 db 90h
seg008:039F ; ---------------------------------------------------------------------------
seg008:039F
seg008:039F loc_1B91F:                              ; CODE XREF: start+397j
seg008:039F                 mov     bx, some_error_code
seg008:03A3                 cmp     bx, 2
seg008:03A6                 jnz     short loc_1B940
seg008:03A8                 push    seg004_offset_filename_source
seg008:03AC                 mov     ax, 19h
seg008:03AF                 call    sub_14219
seg008:03B4                 pop     di
seg008:03B5                 call    sub_14234
seg008:03BA                 mov     ax, 20h ; ' '
seg008:03BD
seg008:03BD loc_1B93D:
seg008:03BD                 jmp     short loc_1B947
seg008:03BD ; ---------------------------------------------------------------------------
seg008:03BF                 align 2
seg008:03C0
seg008:03C0 loc_1B940:                              ; CODE XREF: start+39Cj
seg008:03C0                                         ; start+3A6j
seg008:03C0                 shl     bx, 1
seg008:03C2                 mov     ax, cs:[bx+3D7h]
seg008:03C7
seg008:03C7 loc_1B947:                              ; CODE XREF: start:loc_1B93Dj
seg008:03C7                 call    sub_14219
seg008:03CC                 call    sub_1AB88
seg008:03D1                 mov     ah, 4Ch ; 'L'
seg008:03D3                 mov     al, 0
seg008:03D5                 int     21h             ; DOS - 2+ - QUIT WITH EXIT CODE (EXIT)
seg008:03D5 start           endp                    ; AL = exit code


There is some familiar bit fiddleing going on in the graphics related stuff... I don't know why exactly I expected this for VGA to be less chaotic than on the C64 graphics chip. :D

Code:

seg003:7E30 clear_some_stuff_and_prep_screen proc near ; CODE XREF: start:loc_1B64FP
seg003:7E30                 mov     cx, ds
seg003:7E32                 mov     es, cx
seg003:7E34                 cld
seg003:7E35                 mov     di, 8DC0h
seg003:7E38                 mov     cx, 6FEEh       ; 28654
seg003:7E3B                 xor     al, al
seg003:7E3D                 rep stosb               ; set zeroes in range ds:8dc0 to ds:fdad  ...
seg003:7E3F                 push    cs
seg003:7E40                 call    near ptr remember_screen_dims
seg003:7E43                 nop
seg003:7E44                 mov     ax, 0FFFFh      ; -1
seg003:7E47                 mov     graphics_related_a, ax
seg003:7E4A                 mov     graphics_related_b, ax
seg003:7E4D                 mov     graphics_related_c, ax
seg003:7E50                 mov     di, 0FDAEh      ; ... fdae (one after the zeroed buffer from above)
seg003:7E53                 xor     bx, bx          ; bh = 0, bl = 0
seg003:7E55
seg003:7E55 outer_loop:                             ; CODE XREF: clear_some_stuff_and_prep_screen+33j
seg003:7E55                 mov     ah, bl
seg003:7E57                 mov     cx, 8
seg003:7E5A
seg003:7E5A inner_loop:                             ; CODE XREF: clear_some_stuff_and_prep_screen+2Ej
seg003:7E5A                 rcl     ah, 1
seg003:7E5C                 rcr     al, 1
seg003:7E5E                 loop    inner_loop      ; these 8 iterations of rcl and rcr
seg003:7E5E                                         ; mirror ah into al and al into ah
seg003:7E5E                                         ; why?
seg003:7E60                 stosb
seg003:7E61                 inc     bl              ; will wrap after ff
seg003:7E63                 jnz     short outer_loop
seg003:7E65                 mov     bx, screen_width_in_pixels_div8
seg003:7E69                 push    cs
seg003:7E6A                 call    near ptr prepare_screen_no_split_start_address_0
seg003:7E6D                 nop
seg003:7E6E                 xor     ax, ax
seg003:7E70                 int     1Ah             ; CLOCK - GET TIME OF DAY
seg003:7E70                                         ; Return: CX:DX = clock count
seg003:7E70                                         ; AL = 00h if clock was read or written
seg003:7E70                                         ; (via AH=0,1) since the previous midnight
seg003:7E70                                         ; Otherwise, AL > 0
seg003:7E72                 mov     clock_count_related, dx
seg003:7E72 clear_some_stuff_and_prep_screen endp


seg003:7E81 prepare_screen_no_split_start_address_0 proc far
seg003:7E81                                         ; CODE XREF: clear_some_stuff_and_prep_screen+3Ap
seg003:7E81                                         ; sub_1EFCB+53P ...
seg003:7E81                 mov     VGA_RAM_START, 0A000h
seg003:7E87                 xor     ax, ax
seg003:7E89                 mov     is_0_or_288, ax ; ax is 0
seg003:7E8C                 mov     is_0dec_or_24dec, ax ; ax is 0
seg003:7E8F                 mov     also_0_or_24_decimal, ax ; ax is 0
seg003:7E92                 mov     is_0dec_or_9dec, ax ; ax is 0
seg003:7E95                 mov     dx, 3DAh
seg003:7E98
seg003:7E98 wait_for_vsync_pulse_end:               ; CODE XREF: prepare_screen_no_split_start_address_0+1Aj
seg003:7E98                 in      al, dx          ; Video status bits:
seg003:7E98                                         ; 0: retrace.  1=display is in vert or horiz retrace.
seg003:7E98                                         ; 1: 1=light pen is triggered; 0=armed
seg003:7E98                                         ; 2: 1=light pen switch is open; 0=closed
seg003:7E98                                         ; 3: 1=vertical sync pulse is occurring.
seg003:7E99                 test    al, 8           ; test bit 3
seg003:7E9B                 jnz     short wait_for_vsync_pulse_end
seg003:7E9D
seg003:7E9D wait_for_vsync_pulse_start:             ; CODE XREF: prepare_screen_no_split_start_address_0+1Fj
seg003:7E9D                 in      al, dx          ; Video status bits:
seg003:7E9D                                         ; 0: retrace.  1=display is in vert or horiz retrace.
seg003:7E9D                                         ; 1: 1=light pen is triggered; 0=armed
seg003:7E9D                                         ; 2: 1=light pen switch is open; 0=closed
seg003:7E9D                                         ; 3: 1=vertical sync pulse is occurring.
seg003:7E9E                 test    al, 8           ; test bit 3
seg003:7EA0                 jz      short wait_for_vsync_pulse_start
seg003:7EA2                 mov     screen_width_in_pixels_div8, bx ; bx was also previously loaded from there
seg003:7EA2                                         ; so is just written back now
seg003:7EA6                 shr     bx, 1           ; screen width / 16
seg003:7EA8                 mov     dx, 3D4h
seg003:7EAB                 mov     al, 13h
seg003:7EAD                 mov     ah, bl
seg003:7EAF                 out     dx, ax          ; Video: CRT cntrlr addr
seg003:7EAF                                         ; offset register 13h to bl (address difference between
seg003:7EAF                                         ; two scanlines)
seg003:7EAF                                         ; Offset = Width / ( PixelsPerAddress * MemoryAddressSize * 2 )
seg003:7EAF                                         ; in case of 800, this is set to 50 here
seg003:7EAF                                         ; memory is accessed 32bits at a time by VGA
seg003:7EAF                                         ; in 4 bit per pixel there are 2 pixels per address
seg003:7EAF                                         ; (at least in packed mode there would be)
seg003:7EAF                                         ; so 2 * 4 * 2 = 16
seg003:7EB0                 mov     bx, 3FFh        ; means = no split screen operation
seg003:7EB3                 call    set_line_compare_register_to_bx
seg003:7EB6                 cli                     ; disable interrupts (on C64 this would ENABLE them :P)
seg003:7EB7                 xor     ah, ah
seg003:7EB9                 mov     al, 0Ch
seg003:7EBB                 out     dx, ax          ; screen start address high to 0
seg003:7EBC                 inc     al
seg003:7EBE                 out     dx, ax          ; screen start address low to 0
seg003:7EBF                 sti                     ; enable interrupts
seg003:7EC0                 retf
seg003:7EC0 prepare_screen_no_split_start_address_0 endp


seg003:8E13 set_line_compare_register_to_bx proc near
seg003:8E13                                         ; CODE XREF: prepare_screen_no_split_start_address_0+32p
seg003:8E13                                         ; sub_18F3F+3Bp
seg003:8E13                 mov     al, 18h         ; line compare register
seg003:8E13                                         ; this subroutine assumes: dx = 3d4
seg003:8E13                                         ; which is the CRT Controller Index select register)
seg003:8E15                 mov     ah, bl
seg003:8E17                 out     dx, ax          ; bits 7..0 of line compare to ff
seg003:8E18                 mov     ah, bh
seg003:8E1A                 and     ah, 1           ; take bit 0 of ah
seg003:8E1D                 shl     ah, 1
seg003:8E1F                 shl     ah, 1
seg003:8E21                 shl     ah, 1
seg003:8E23                 shl     ah, 1           ; ah = ah * 16
seg003:8E25                 mov     al, 7           ; overflow register (bit 4 is line compare bit 8)
seg003:8E27                 out     dx, al
seg003:8E28                 inc     dx              ; up to data register 3d5
seg003:8E29                 in      al, dx          ; read overflow register into al
seg003:8E2A                 and     al, 0EFh        ; clear bit 4
seg003:8E2C                 or      al, ah          ; insert bit 4 from calculation above
seg003:8E2E                 mov     ah, al
seg003:8E30                 mov     al, 7           ; overflow register
seg003:8E32                 dec     dx              ; down to index select register 3d4
seg003:8E33                 out     dx, ax          ; write overflow register with previous values
seg003:8E33                                         ; preserved, only bit 4 (bit 8 for line compare)
seg003:8E33                                         ; exchanged with what was calculated above
seg003:8E34                 mov     ah, bh
seg003:8E36                 and     ah, 2           ; take bit 1 of ah
seg003:8E39                 shl     ah, 1
seg003:8E3B                 shl     ah, 1
seg003:8E3D                 shl     ah, 1
seg003:8E3F                 shl     ah, 1
seg003:8E41                 shl     ah, 1           ; ah = ah * 32
seg003:8E43                 mov     al, 9           ; max scan line register (bit 6 is line compare bit 9)
seg003:8E45                 out     dx, al
seg003:8E46
seg003:8E46 loc_18FE6:                              ; up to data register 3d5
seg003:8E46                 inc     dx
seg003:8E47                 in      al, dx          ; read max scan line register
seg003:8E48                 and     al, 0BFh        ; clear bit 6
seg003:8E4A                 or      al, ah          ; insert bit 6 from calculation above
seg003:8E4C                 mov     ah, al
seg003:8E4E                 mov     al, 9           ; max scan line register
seg003:8E50                 dec     dx              ; down to index select regsiter 3d4
seg003:8E51                 out     dx, ax          ; write max scan line register with previous values
seg003:8E51                                         ; preserved, only bit 6 (bit 9 for line compare)
seg003:8E51                                         ; exchanged with what was calculated above
seg003:8E52                 retn
seg003:8E52 set_line_compare_register_to_bx endp


Will keep digging.
_________________
0xDB
View user's profile Send private message Visit poster's website
Reply to topic GDR Forum Index -> Game Developer's Refuge -> [hacking] graphics ripping Page 1, 2  Next
Game Developer's Refuge
is proudly hosted by,

HostGator

All trademarks and copyrights on this page are owned by their respective owners. All comments owned by their respective posters.
phpBB code © 2001, 2005 phpBB Group. Other message board code © Kevin Reems.