; SHT 1.1 ScreenShot. Take a picture of the mobile screen
; Firmware : S45iv4
; Author: fcotrina
; Created: 12.01.2005
; Based in Windows ScreenShot and patch CL=CallLogging
; With some ideas taken from lalo.lerry and RizaPN
; Big thanks to Redkin and NCTN.
; How to run it? Follow these steps:
; Press 'left sidekey', to take the screenshot
; Open any file in explorer.
; A new file named scr????.BMP has been created in A:\
; You can view it, send it, or transfer to a computer
; Every time a new file is created with a random secuence number
; Rename the file if you want to keep it. Otherwise it might get overwritten
; known bugs:
; -The picture is taken after the key has been pressed, so the picture
; might change due to that key press
; -You need to open another file in between. I had to delay creating the
; file because S45i allows to create file only in some specific routines
; -If the random name is already an existing file, data is appended. Probably
; I should use a secuential number, or 2 random numbers, or date_time
; -If you take several screenshots, only saves the last one, unless you
; open any file in between. This is not a bug. I want it to be like this
; -it uses free RAM from 0000:1000 . If any other patch uses it, they collide

#include C166.inc

base 0A00000h

org 0CCB2D4h
; original code called when a key is pressed
;CCB2D4: D7 40 03 02 : extp #203h, #1
;CCB2D8: D4 FE 5E 2E : mov r15, [r14+#2E5Eh]
calls new_key_pressed ; my new code
nop ; I replace 4 instructions: 8 bytes
nop

org 0DA2C98h
; original code called when a file is open
; DA2C98: 88 90 : mov [-r0], r9
; DA2C9A: 88 80 : mov [-r0], r8
calls new_file_open ; my new code
after_open_file: ; need to know where to jump back.

;******************************
; When key 'left sidekey' is pressed, copy screen into 00:1000
; That key is on the left part of the screen. Yes, that long key.
; Press the top part of it.
org 0AEB000h ; there is unused ROM here. If not, use 0C94F0 or 5EFA00

new_key_pressed:
mov [-r0], r5
mov [-r0], r11
mov [-r0], r12
mov [-r0], r14

mov r5, r12 ; pressed key is stored in r12
cmp r5, #000Eh ; is left_sidekey?
jmpr cc_NZ, exit_no_left_sidekey

mov r14, #1FD4h ; screen is taken from 0041:1FD4
mov r12, #q(free_RAM_screen) ; target
mov r11, #0410h ; size

; copy 410h bytes from 0041:1FD4 to 0000:1000
; probably there is a memcpy routine somewhere, but I don't know where
another_r11:
extp #41h, #1h
mov r5, [r14] ; can be check with at+cgsn:00,1000 at+cgsn:01,1FD4
add r14, #02h
extp #0h, #1h
mov [r12] , r5
add r12, #02h
sub r11, #02h
jmpr cc_NZ, another_r11


; flag that there is a file pending to be saved
mov r5, #'A:'
extp #0h, #1h
mov q(free_RAM_name), r5

exit_no_left_sidekey:
mov r14, [r0+]
mov r12, [r0+]
mov r11, [r0+]
mov r5, [r0+]

; do now the original code
extp #203h, #1
mov r15, [r14+#2E5Eh]

rets

;******************************

new_file_open:
mov [-r0], r9 ; original code in 0DA2C98h
mov [-r0], r8 ; also original

;base 0100000h
;org 0100900h
save_screen:
mov [-r0], r4
mov [-r0], r6
mov [-r0], r12
mov [-r0], r13
mov [-r0], r14
mov [-r0], r15

extp #0h, #1h
mov r4, q(free_RAM_name)
cmp r4, #'A:'
jmpr cc_NZ, exit ; no screenshot taken yet

; copy file name to 0000:1000 and give it a unique name
mov r15, #p(file_name) ; file name segment
mov r14, #q(file_name) ; file name offset
mov r13, #0h
mov r12, #q(free_RAM_name)
calls 0FF40A0h ; copy string r15:r14 -> r13:r12
; take random value
extp #2h, #2h
mov r13, 03FDAh ; this stores the seconds (in internal format)
mov r14, 03FDCh ; and this stores the minute (more or less)
; convert to 4 letters
and r14, #0F0Fh
add r14, #04141h ; that is , 'A' 2 times
and r13, #0F0Fh
add r13, #04141h ; that is , 'A' 2 times
extp #0, #2h
mov q(free_RAM_name)+06h, r14 ; set it in the middle of file name offset.
mov q(free_RAM_name)+08h, r13 ; set it at the end of file name offset.

; open file for write
mov r14, #10Ah ; always fixed value #10Ah
mov r13, #0h ; file name segment
mov r12, #q(free_RAM_name) ; file name offset
mov r15, #0100h ; always fixed value #100h
mov [-r0], r9 ; emulate original code in 0DA2C98h
mov [-r0], r8
calls after_open_file

cmp r4, #0FFFFh ; check if opening was correct
jmpr cc_Z, exit ; something wrong
mov [-r0], r4 ; save file handler
mov r12, r4 ; file handler
mov r13, #q(header) ; header data offset
mov r14, #p(header) ; header data segment
mov r15, #62 ; data size: 16+16+16+14 , in decimal !
calls 0DA3642h ; write header
mov r12, [r0+] ; retrieve handler


; screen starts in 5FD4 and ends in 63E4 , that is, 0x0410 bytes
; although I have copied in 001000h, that is, 0000:1000
mov r6, #050h ; number of lines: 80
;mov r13, #023D7h ; address of the last line
mov r13, #q(free_RAM_screen)+0403h ; address of the last line, when screenshot starts from 0000:1000
loop_r6:
mov [-r0], r6
mov [-r0], r13
mov [-r0], r12 ; save handler
;mov r14, #41h ; segment address of current line
mov r14, #0h ; segment address of current line, starting from 0000:1000
mov r15, #010h ; line size in bytes: 16 (although width=101, almost 13*8)
calls 0DA3642h ; write to file this screen line r13:r6
mov r12, [r0+] ; retrieve file handler
mov r13, [r0+]
sub r13, #0Dh ; jump to previous screen line
mov r6, [r0+]
sub r6, #01h ; if this is not the first line, continue
;cmp r6, #0h ; not needed because sub also set flags
jmpr cc_NZ, loop_r6

close:
calls 0DA4AB4h ; close file

exit:
mov r4, #0FFFFh
extp #0h, #1h
mov q(free_RAM_name), r4 ; flag that it has been processed

mov r15, [r0+]
mov r14, [r0+]
mov r13, [r0+]
mov r12, [r0+]
mov r6, [r0+]
mov r4, [r0+]
rets

;org 0100990h
file_name: ; file name
db 'A:\scr'
unique_name:
db '0000.'
header: ; header of a BMP file, black+white, 101x80
db 42h, 4Dh, 50h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 3Eh, 00h, 00h, 00h, 28h, 00h
db 00h, 00h, 65h, 00h, 00h, 00h, 50h, 00h, 00h, 00h, 01h, 00h, 01h, 00h, 00h, 00h
db 00h, 00h, 00h, 05h, 00h, 00h, 0C4h, 0Eh, 00h, 00h, 0C4h, 0Eh, 00h, 00h, 00h, 00h
db 00h, 00h, 00h, 00h, 00h, 00h, 0FFh, 0FFh, 0FFh, 00h, 00h, 00h, 00h, 00h

; this part is only for the compiler. It does not go into the patch, because it takes RAM, not ROM
base 0000000h
org 001000h
free_RAM_name:
db 'A:\scr????.BMP', 0h, 0h ; must be multiple of 2
free_RAM_screen:

; end of source code



; this is the binary patch

0x3A2C98: DA0E4EB0 88908880
0x2CB2D4: D7400302D4FE5E2E DA0E00B0CC00CC00
0x0EB000: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 885088B088C088E0F05C46F50E003D16
0x0EB010: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF E6FED41FE6FC1010E6FB1004D7404100
0x0EB020: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF A85E08E2D7400000B85C08C228B23DF6
0x0EB030: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF E6F5413AD7400000F6F5001098E098C0
0x0EB040: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 98B09850D7400302D4FE5E2EDB008890
0x0EB050: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 88808840886088C088D088E088F0D740
0x0EB060: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 0000F2F4001046F4413A3D4BE6FFBA02
0x0EB070: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF E6FE1C31E00DE6FC0010DAFFA040D750
0x0EB080: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 0200F2FDDA3FF2FEDC3F66FE0F0F06FE
0x0EB090: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 414166FD0F0F06FD4141D7500000F6FE
0x0EB0A0: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 0610F6FD0810E6FE0A01E00DE6FC0010
0x0EB0B0: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF E6FF000188908880DADA9C2C46F4FFFF
0x0EB0C0: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 2D208840F0C4E6FD2731E6FEBA02E6FF
0x0EB0D0: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 3E00DADA423698C0E6F65000E6FD1314
0x0EB0E0: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 886088D088C0E00EE6FF1000DADA4236
0x0EB0F0: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 98C098D026FD0D00986028613DF1DADA
0x0EB100: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF B44AE6F4FFFFD7400000F6F4001098F0
0x0EB110: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 98E098D098C098609840DB00413A5C73
0x0EB120: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 6372303030302E424D50000000000000
0x0EB130: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 003E0000002800000065000000500000
0x0EB140: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 00010001000000000000050000C40E00
0x0EB150: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 00C40E00000000000000000000FFFFFF
0x0EB160: FFFFFFFFFF 0000000000