Bon alors je crois savoir d'où viens le problème, mais je n'arrive pas à le résoudre... D'abord il y avait un bug dans la routine get_byte : avec
_getbytepaged, b était copié à l'adresse contenue dans hl, et non pas dans le registre lui même :
get_byte:
push de
push hl ; hl = data to read
ld a,b ; b = flash page #, or 0 if in ram
or a
call nz,get_byte_paged
push hl
ld hl,(program_length)
dec (hl) ; just to make sure we're not reading out of the program
ld a,(hl)
or a
pop hl
ld a,(hl)
pop hl
pop de
inc hl
ret nz
scf ; c is set if we're out of the program
ret
get_byte_paged:
push bc
ld a,b
bcall(_getbytepaged)
ld h,0
ld l,b
pop bc
ret
Ensuite le problème vient de la lecture des deux octets de la taille du programme lorsqu'il est archivé :
_chkfindsym renvoi bien l'adresse des données du programme dans de (qu'on swap avec hl), et
_getbytepaged y accède bien, sauf que ça ne semble pas être la taille du programme...
Dans la source de noshell il y a :
; ce code est exécuté si le prog est archivé, après un _chkfindsym et ex de,hl
ld de,9
call BHL_plus_DE
call getDataByte
ld c,a
$$: call getDataByte
dec c
jr nz,$B
readProgramData:
call getDataByte
ld e,a
call getDataByte
ld d,a
ld (wProgSize),de
Donc hl ne pointe pas vers les données du programme (ce qui est le cas si le prog est dans la ram), mais vers l'header ? Le wikiti
ne dit rien là dessus...
Si c'est le cas donc, il saute les 9 premiers octets (type+nom), mais pourquoi ensuite sauter x fois des données avant d'arriver à la taille du prog ?!

hook.inc
zshell_hook:
.db $83 ; used by os for hook safety check (add a,e can be used too)
di
or a
jr z,zshell_hook_start ; we just want to handle prgm, not TI-Basic functions
zshell_hook_return_z:
xor a
ret
zshell_hook_start:
ld hl,$0002
ld (program_length),hl ; to be able to read at least the length bytes
ld hl,(nextparsebyte) ; what's on homescreen
ld a,(hl)
cp tprog
jr nz,zshell_hook_return_z ; if it don't start with "prgm", we don't care
rst rmov9toop1 ; we put "prgmANYTHING" into op1
ld hl,op1
ld (hl),progobj ; then replace "prgm" token with the program type (progobj)
bcall(_chkfindsym) ; so we can find its datas
bjumpc(_errundefined) ; if not found, throw an "undefined error"
ex de,hl ; cause of _getbytepaged parameters
call get_byte ; else start to read it
ld e,a
call get_byte ; first two bytes are length of the program
jp c,zshell_hook_return_nz ; if empty, don't parse
ld d,a
ld (program_length),de
call get_byte ; skip t2bytetok/texttok
call get_byte
cp tasmprgm
jp z,zshell_hook_handle_unsquished_asm_prgm
cp tasmcmp
jp z,zshell_hook_execute_compiled_asm_prgm
;cp tzshellprgm
;ld hl,zshell_txt
;jr z,zshell_hook_execute_zshell_prgm
set allowprogtokens,(iy+newdispf) ; allow programming tokens to be parsed in TI-Basic programs
ld a,b
or a
ret z ; the TI-Basic program is unarchived, so let the parser handle it
exx ; app_push_errorh uses the stack, so we use shadow registers to hold hl and bc
ld hl,zshell_error_handler
call app_push_errorh
call allocate_temp_prog ; check if there is other temp progs, then put an unique name into op1
ld hl,(program_length)
bcallnc(_createprog) ; bcallnc(_createprotprog)
bjumpc(_errmemory)
inc de
inc de ; de = data section (skip the length bytes)
xor a
ld (parse_var),a ; clear the type byte of the currently executed TI-Basic program
ld (parse_var+1),a ; and the first letter of its name ?
push de
exx
pop de
ld a,b
ld bc,(program_length)
bcall(_flashtoram) ; copy the datas from the archived TI-Basic prog to the temp prog
;bcall(_op4toop1) ; op1 was copied into op4 then destroyed by _createprotprog
;bcall(_parseinp)
;call delete_temp_prog
call app_pop_errorh
zshell_hook_return_nz:
or $80 ; reset zero flag, the parser can't continue to parse the variable
ret
zshell_hook_handle_unsquished_asm_prgm:
ld a,b
or a
jr z,zshell_hook_execute_unsquished_asm_prgm
; todo : unarchive prgm
zshell_hook_execute_unsquished_asm_prgm:
bcall(_executeprgm) ; can only run unarchived prgm
or $80
ret
zshell_hook_execute_compiled_asm_prgm:
call zshell_hook_program_start_begin
zshell_hook_load:
push hl ; how many bytes left to copy
ld hl,(progaddress) ; copy the program to the gbuf
push bc ; hl = program data start
ld de,gbuf ; bc = # bytes to copy
ldir ; copy bc bytes
pop de ; # bytes copied
ld (progaddress),hl ; save new program data pointer
; delete bc bytes from the program
or a ; hl = start of prog data+768
sbc hl,de
push de ; de = # of bytes copied
bcall(_delmem) ; hl = where to delete from, de = # bytes
pop hl ; hl = # bytes deleted
; insert HL bytes to $9d95
ld de,(progstartlocation) ; progstart ($9d95)
push hl ; hl = # bytes deleted
bcall(_insertmem) ; insert hl bytes to $9d95
pop bc ; bc = bytes deleted
ld hl,(progstartlocation) ; ex de,hl ???
add hl,bc
ld (progstartlocation),hl
; copy gbuf to $9d95
ld hl,gbuf ; de = location where memory was inserted ($9d95+XXXX)
ldir ; copy # of bytes deleted from gbuf to progstart
pop hl ; how many bytes are left to copy
ld a,l
or h
jr nz,zshell_hook_load_loop
call progstart ; run the program
; now rewrite the data back into the program
; ...not done yet...
zshell_hook_program_start_begin:
ld a,b
or a
call nz,zshell_hook_unarchive
; hl = first byte of program data
; de = program length-2
ld bc,progstart
ld (progstartlocation),bc
ld (progaddress),hl
ex de,hl ; hl = length
zshell_hook_load_loop:
ld bc,768 ; check if there are <768 bytes left to copy (gbuf length)
or a
sbc hl,bc ; subtract 768 from the program size
ret nc ; if no carry, there are still more than 768 bytes to copy
add hl,bc
ld b,h
ld c,l
ld hl,$0000
ret
zshell_hook_unarchive:
; push hl
; ld hl,(program_length)
; push bc
; bcall(_enoughmem)
; pop bc
; pop hl
; ld a,e_memory
; bjumpc(_jerror)
; ld a,b
; ld de,progstart
; ld bc,(program_length)
; inc bc
; inc bc ; we have to count t2bytetok/tprog this time
; bcall(_flashtoram)
ret
zshell_error_handler:
res 7,a ; ???
push af
call delete_all_temp_progs
pop af
bjump(_jerror)
allocate_temp_prog: ; fail is carry flag is set
ld hl,temp_prog_name_str
rst rmov9toop1
check_then_allocate_temp_prog:
bcall(_chkfindsym)
ccf ; inverse the carry flag
ret nc ; ret if program not found (we can name it using the ID at op1+2)
ld a,(op1+2)
dec a
scf ; set carry flag in case we ret (meaning we can't allocate the temp prog, but there's a few chance for that)
ret z ; ret if a = 0
ld (op1+2),a
jr check_then_allocate_temp_prog
delete_temp_prog:
ld hl,temp_prog_name_str
rst rmov9toop1
ld a,1
ld (op1+2),a ; we start by checking the temp prog with the ID = 01
find_then_delete_temp_prog:
bcall(_chkfindsym)
jr nc,delete_temp_prog_ok ; if the temp prog is found, delete it
ld a,(op1+2) ; else we increase the prog id
inc a
scf ; if we're over $ff, there's no more temp prog
ret z
ld (op1+2),a
jr find_then_delete_temp_prog
delete_temp_prog_ok:
bcall(_delvararc)
xor a
ret
delete_all_temp_progs:
call delete_temp_prog
ret c
jr delete_all_temp_progs
temp_prog_name_str:
;.db protprogobj,$01,$ff,$00
.db progobj,"A",$ff,0