Urban Strike (Game Boy)
| Urban Strike |
|---|
|
Developer: Borta
|
Say hello to one of Game Boy's most hideous title screens.
Uncompiled Source Code
Two big chunks of uncompiled code can be found by using a hex editor on the ROM. Note that the formatting seen below matches the formatting seen in the ROM.
0x69E80:
call DO_SEQUENCE
START_INTERIOR_CAMPAIGN:
ld sp, $dfff ; set the stack pointer
call LCD_off
call InitWorld
call PlayGame
;═════════════════════════════════════════════════════════════════════════════
vr_start_wait:
; Waits for the beginning of vertical retrace. Returns immediately if the
; display is turned off. Interrupts must be disabled if this routine is called
; while the display is turned on.
push af
ld a, (LCDC)
and a, %10000000
jr z, .exit
.loop:
ld a, (LY)
cp a, 145 ; 144
jr nz, .loop
.exit:
pop af
ret
;─────────────────────────────────────────────────────────────────────────────
vr_end_wait:
; Waits for the end of vertical retrace. Returns immediately if the display is
; turned off. Interrupts must be disabled if this routine is called while the
; display is turned on.
push af
ld a, (LCDC)
and a, %10000000
jr z, .exit
.loop:
ld a, (LY)
or a, a
jr nz, .loop
.exit:
pop af
ret
;─────────────────────────────────────────────────────────────────────────────
LCD_off:
; Turns off the video display. Assumes interrupts are disabled.
push af
call vr_start_wait
ld a, (LCDC)
and a, %01111100
ld (LCDC), a
pop af
ret
;─────────────────────────────────────────────────────────────────────────────
LCD_on:
; Turns on the video display.
push af
ld a, (LCDC)
or a, %10000011
ld (LCDC), a
pop af
ret
;─────────────────────────────────────────────────────────────────────────────
;LCD_on_bkgr_off:
; Disables the display of the background but leaves the screen on.
; push af
;
; ld a, (LCDC)
; or a, %10000000
; and a, %11111110
; ld (LCDC), a
;
; pop af
;
; ret
;─────────────────────────────────────────────────────────────────────────────
bkgr_off:
; Disables the display of the background.
push af
ld a, (LCDC)
and a, %11111110
ld (LCDC), a
pop af
ret
;─────────────────────────────────────────────────────────────────────────────
bkgr_on:
; Enables the display of the background.
push af
ld a, (LCDC)
or a, %00000001
ld (LCDC), a
pop af
ret
;─────────────────────────────────────────────────────────────────────────────
spr_off:
; Disables the display of sprites.
push af
ld a, (LCDC)
and a, %11111101
ld (LCDC), a
pop af
ret
;─────────────────────────────────────────────────────────────────────────────
spr_on:
; Enables the display of sprites.
push af
ld a, (LCDC)
or a, %00000010
ld (LCDC), a
pop af
ret
;─────────────────────────────────────────────────────────────────────────────
sound_off:
push af
ld a, (sound_flags)
and a, 254
ld (sound_flags), a
xor a, a
ld (NR52), a
pop af
ret
sound_on:
push af
ld a, (sound_flags)
or a, 1
ld (sound_flags), a
ld a, %11111111
ld (NR51), a
ld (NR50), a
ld a, %10001000
ld (NR52), a
pop af
ret
;─────────────────────────────────────────────────────────────────────────────
cls:
; Clears one of the two VRAM display areas. May be called only when the
; display is turned off.
; call with D = area number (0 or 1)
; E = clear value
; push af
; push bc
; push hl
ld bc, 1024
ld hl, $9800
bit 0, d
jr z, .loop
ld h, $9c
.loop:
ld (hl), e
inc hl
dec bc
ld a, c
or a, b
jr nz, .loop
; pop hl
; pop bc
; pop af
ret
;─────────────────────────────────────────────────────────────────────────────
get_buttons:
; Returns with A = status of the buttons.
push bc
ld c, 0
ld a, $20
ld (c), a ; select direction buttons
ld a, (c)
ld a, (c)
ld a, (c)
and a, $0f ; A = 0000dulr
ld b, a ; B = 0000dulr
ld a, $10
ld (c), a ; select other buttons
ld a, (c)
ld a, (c)
ld a, (c)
ld a, (c)
ld a, (c)
ld a, (c)
ld a, (c)
ld a, (c)
ld a, (c)
and a, $0f ; A = 0 0 0 0 sta sel b a
swap a ; A = sta sel b a 0 0 0 0
or a, b ; A = sta sel b a d u l r
cpl
pop bc
ret
;─────────────────────────────────────────────────────────────────────────────
fill_copy_proc:
; call with B = total bytes of data / 2; B must be <= 144
; DE -> second-to-last byte of data
; the correct bank selected
; Before jumping to copy_proc, set SP -> byte after last destination byte, and
; HL = return address.
push af
push bc
push de
push hl
ld hl, copy_proc
.loop:
inc hl
ld a, (de)
inc de
ld (hli), a
ld a, (de)
dec de
dec de
dec de
ld (hli), a
inc hl
dec b
jr nz, .loop
ld a, (jp_addr)
ld e, a
ld a, (jp_addr + 1)
ld d, a
ld a, $11
ld (de), a ; "erase" previous "jp (hl)" instr.
ld a, $e9 ; $e9 = "jp (hl)"
ld (hl), a ; insert "jp (hl)" instruction
ld a, l
ld (jp_addr), a
ld a, h
ld (jp_addr + 1), a
pop hl
pop de
pop bc
pop af
ret
;─────────────────────────────────────────────────────────────────────────────
load_chars:
; call with (dest_addr) -> byte after last destination byte
; May be called only when the display is turned off or during v-blank. If
; (dest_addr + 1) = 0, then load_chars does nothing. load_chars sets
; (dest_addr + 1) = 0.
ld (stack_save), sp
ld sp, hl ; SP = (dest_addr)
ld hl, .back
jp copy_proc
.back:
ld hl, stack_save
ld a, (hli)
ld h, (hl)
ld l, a ; HL = (stack_save)
ld sp, hl ; SP = (stack_save)
ret
;─────────────────────────────────────────────────────────────────────────────
RAMMoveSpriteObject:
; call with A = total sprites in object
; C = number of first sprite (0 - 39)
; D = dy
; E = dx
push af
push bc
push hl
ld b, a ; B = total sprites in object
ld a, c ; A = number of first sprite
add a, a
add a, a ; A = number of first sprite * 4
ld l, a
ld h, $c0 ; HL -> sprite in RAM sprite table
.loop:
ld a, (hl) ; A = sprite y-coordinate
cp a, $e0
jr z, .skip
add a, d
ld (hli), a
ld a, (hl) ; A = sprite x-coordi
0x6EB0B:
ld b, 11
.ENCODE_LOOP:
ld a, (hl)
ld de, PASS_CHAR
add a, e
ld e, a
ld a, d
adc a, 0
ld d, a
ld a, (de)
ld (hli), a
dec b
jr nz, .ENCODE_LOOP
ret
;*******************************************************
;*******************************************************
;*******************************************************
;*******************************************************
;*******************************************************
; password decoding
;*******************************************************
; PASS_DECODE:
;*******************************************************
PASS_DECODE:
; copy PASSWD to PASSWD_TEMP, reduce to 0-31 range
ld hl, PWString
ld de, PWTemp
ld b, 11
.REDUCE_LOOP:
ld a, (hli) ; a = character from p.w. string
push bc
push hl
ld hl, PASS_CHAR + 30 ; 28 ; 31
ld b, 31 ; 29 ; 32
.search:
ld c, (hl)
dec hl
cp a, c
jr z, .match
dec b
jr nz, .search
pop hl
pop bc
jp .FAIL
.match:
dec b
ld a, b
ld (de), a
inc de
pop hl
pop bc
dec b
jr nz, .REDUCE_LOOP
.DECODE:
ld a, (PWTemp_5)
sra a
ld b, a
ld (nibble_2), a
ld a, (PWTemp_10)
sub a, b
ld b, a
ld (nibble_5), a
ld a, (PWTemp_1)
sub a, b
ld b, a
ld (nibble_3), a
ld a, (PWTemp_4)
sub a, b
ld b, a
ld (nibble_0), a
ld a, (PWTemp_7)
sub a, b
ld b, a
ld (nibble_1), a
ld a, (PWTemp_8)
sub a, b
ld b, a
ld (nibble_7), a
ld a, (PWTemp_0)
sub a, b
ld b, a
ld (nibble_4), a
ld a, (PWTemp_9)
sub a, b
ld b, a
ld (nibble_6), a
ld a, (PWTemp_2)
sub a, b
ld b, a
ld (nibble_8), a
.CHECK:
ld hl, nibble
ld de, 0
ld b, 9
.CHECK_LOOP:
ld a, (hl)
add a, d
ld d, a
ld a, (hli)
xor a, e
ld e, a
dec b
jr nz, .CHECK_LOOP
ld a, (PWTemp_3)
ld c, a
ld a, d
; and a, 01Fh
.loop:
cp a, 31
jr c, .ok
sub a, 31
jr .loop
.ok:
cp c
jr NZ, .FAIL
ld a, (PWTemp_6)
ld c, a
ld a, e
sla a
cp c
jr NZ, .FAIL
.UNMANGLE:
ld de, GameScore
ld hl, CRYPTO
STORE_HL_TO TEMPW_2
ld hl, nibble
ld b, 4
.UNMANGLE_LOOP:
ld a, (hli)
ld c, a
ld a, (hli)
sla a
sla a
sla a
sla a
or a, c
push hl
push af
LOAD_HL_FROM TEMPW_2
pop af
xor a, (hl)
inc hl
ld (de), a
inc de
STORE_HL_TO TEMPW_2
pop hl
dec b
jr nz, .UNMANGLE_LOOP
; check level < FINAL_WORLD
ld a, (hl)
cp a, FINAL_WORLD + 3 ; allow view game end (=10) , credits (=11), fail on (=12)
jr NC, .FAIL
ld (CURR_WORLD), a
and a, a
ret
.FAIL:
jr .FAIL
; zero out the current world and game score
xor a
ld hl, GameScore
ld (hli), a
ld (hli), a
ld (hli), a
ld (hli), a
ld (CURR_WORLD), a
scf
ret
cp a, FINAL_WORLD + 3 ; allow view game end (=10) , credits (=11), fail on (=12)
jr NC, .FAIL
ld (CURR_WORLD), a
and a, a
ret
.FAIL:
jr .FAIL
; z
ZIP Archives
Two corrupted ZIP archives that probably contained more source code of the game can be found in the ROM. The last modified dates of the files they contain range between 6 to 10 months before the final US release date.
0x27F8C:
Contains a file named OSTRUCT4.ASM with a last modified date of 1996-05-09 10:49:00 in UTC time that can't be extracted due to the ZIP file's corruption.
0x4FEFE:
Contains two files: one of them is named OSTRUCT.INC, has a last modified date of 1996-01-17 08:36:16 in UTC time and can't be extracted for the same reason of the precedent one. The other file, UDATA.INC, was last modified on 1996-03-13 10:59:30 UTC and can be extracted:
PASS_CHAR:
; db "0123456789ABCDEFGHJKMNPQRTUVWXYZ"
db "0123456789BCDFGHJKLMNPQRSTVWXYZ"
From the commented-out instruction it can be seen that at some point of the development A, E and U were valid password characters before being replaced with L and S in the final game (one character was removed in the final version).
The Strike series
| |
|---|---|
| Amiga | Desert Strike: Return to the Gulf |
| Genesis | Desert Strike: Return to the Gulf • Jungle Strike • Urban Strike |
| Sega Master System | Desert Strike |
| Game Gear | Jungle Strike |
| SNES | Desert Strike: Return to the Gulf • Jungle Strike |
| Game Boy | Desert Strike: Return to the Gulf • Urban Strike |
| Nintendo 64 | Nuclear Strike 64 |
| Game Boy Advance | Desert Strike Advance |
Cleanup > Pages missing date references
Cleanup > Pages missing developer references
Cleanup > Pages missing publisher references
Games > Games by content > Games with uncompiled source code
Games > Games by content > Games with unusual dummy files
Games > Games by developer > Games developed by Borta
Games > Games by platform > Game Boy games
Games > Games by platform > Game Boy games > Super Game Boy games
Games > Games by publisher > Games published by THQ > Games published by T·HQ > Games published by Black Pearl
Games > Games by release date > Games released in 1996
Games > Games by series > Strike series