1

Créer un shell pour la 84+ C SE à plusieurs ça vous dit ?

Je ne parle pas d'une usine à gaz qui regroupe 36000 routines, des icônes énormes etc... mais d'un petit shell proposant des routines simples et suffisante pour rapidement porter nos projets actuels smile

Voici quelques routines qui pourraient être intéressante (à compléter et à discuter bien entendu) :

- tirage d'un nombre aléatoire
- affichage de sprite clippées (16-bits voire moins ? Peut être même 1-bit pour la retrocompatibilité ?)
- flip/rotation de sprites
- dessin de rectangle pleins/vides, cercles, lignes
- routine qui copie un buffer de 768 octets au milieu de l'écran (ou 1 bit = 1 pixel)
- link ?

Au niveau du format, je pense qu'il vaudrait mieux partir sur une app.

Pour la mise en page il faudrait un truc simple : le nom du shell, un "toggle" (button on/off) pour l'installation, le choix de "write-backer" les programmes désarchivés et de quoi quitter l'app.

Au niveau des fonctions : autoréinstallation après un reset (peut être re-réglage de l'horloge aussi ?) etc...

J'ai commencé à écrire quelques bouts de codes, le problème c'est qu'on ne peux pas (encore) tester sur 84+ C SE, du coup ça compile pour 83+, mais de toute façons il n'y aura que la partie graphique à revoir (le système des apps/hook est très certainement le même). On peut déjà commencer à coder quelques routines (tirage aléatoire, copie de buffers...) smile

L'header est normalement correcte, l'app est bien signée (par contre la clé RSA est-elle la même ?), j'ai codé la création de l'appvar (qui stock l'état de l'installation du shell (mais on pourrait peut être le deviner en détectant le hook ?), et si on write-back), un début de lecture/écriture de ce même appvar et l'installation d'un hook qui empêche le lancement des programmes (par contre je n'ai pas encore codé sa désinstallation).
zshell.z80
.nolist ;#include "ti84pcse.inc" #include "ti83p.inc" ; only for debug .list .org $4000 .db $80,$0f,$00,$00,$00,$00 ; program length = 0 .db $80,$12,$01,$04 ; program type = shareware for TI 83+ .db $80,$21,$01 ; app id = 1 .db $80,$31,$01 ; app build # = 1 .db $80,$48, "zSHELL " ; app name (must be 8 bytes long) .db $80,$81,$01 ; app page = 1 .db $80,$90 ; no default splash screen .db $03,$26,$09,$04,$04,$06f,$1b,$80 ; date stamp = 5/12/1999 .db $02,$0d,$40 ; encrypted TI date stamp signature .db $a1,$6b,$99,$f6,$59,$bc,$67 .db $f5,$85,$9c,$09,$6c,$0f,$b4,$03,$9b,$c9 .db $03,$32,$2c,$e0,$03,$20,$e3,$2c,$f4,$2d .db $73,$b4,$27,$c4,$a0,$72,$54,$b9,$ea,$7c .db $3b,$aa,$16,$f6,$77,$83,$7a,$ee,$1a,$d4 .db $42,$4c,$6b,$8b,$13,$1f,$bb,$93,$8b,$fc .db $19,$1c,$3c,$ec,$4d,$e5,$75 .db $80,$7f,$00,$00,$00,$00 ; program image length = 0 .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000 ; padding (header length must be 128 bytes long) start: di ; disable interrupts (todo : check which bcall may resume them) bcall(_clrlcdfull) ; clear screen bcall(_indicatoroff) ; disable run indicator bcall(_cleargbuf) ; clear graph buffer res texterasebelow,(iy+textflags) ; reset some textflags res textinverse,(iy+textflags) ; reset some textflags ld hl,$0501 ld (currow),hl ld hl,zshell_string call iputs ld hl,zshell_appvar rst rmov9toop1 ; hl to op1 bcall(_chkfindsym) call c,create_zshell_appvar ex de,hl ; cause of _getbytepaged parameters ld a,b or a jr z,appvar_is_in_ram ; todo : unarchive appvar appvar_is_in_ram: inc hl inc hl ;skip size bytes call get_byte or a jr z,install_zshell uninstall_zshell: dec hl ld (hl),0 ld hl,$0003 ld (currow),hl ld hl,uninstalling_string call iputs bcall(_getkey) bcall(_jforcecmdnochar) install_zshell: dec hl ld (hl),1 ; set zschell installed in the appvar bit parserhookactive,(iy+hookflags4) ; activate parser hook jr nz,some_hook_already_exists ld hl,zschell_hook ; put hook adress into hl in a,(pmpagea) ; put page # into a bcall(_setparserhook) ; install hook ld hl,$0003 ld (currow),hl ld hl,installing_string call iputs bcall(_getkey) some_hook_already_exists: ; todo : ask for destroying or chaining it bcall(_jforcecmdnochar) ; quit the app get_byte: ld a,b or a ld a,(hl) push de call nz,get_byte_paged pop de inc hl ret get_byte_paged: ld a,b bcall(_getbytepaged) ld a,b ret create_zshell_appvar: ld hl,zshell_appvar rst rmov9toop1 ld hl,zshell_appvar_content_length-zshell_appvar_content bcall(_createappvar) ; todo : check if enough ram inc de inc de ; skip first two bytes (size of the appvar) ld hl,zshell_appvar_content ld bc,zshell_appvar_content_length-zshell_appvar_content ldir ld hl,zshell_appvar rst rmov9toop1 bcall(_chkfindsym) ret iputs: ld a,(hl) or a ret z bcall(_putc) inc hl jr iputs zshell_appvar: .db appvarobj,"zSHELL",0 zshell_appvar_content: .db 0 ; is installed .db 0 ; allow program writeback zshell_appvar_content_length: #include "hook.inc" zshell_string: .db "zSHELL",0 installing_string: .db "zSHELL has been installed",0 uninstalling_string: .db "zSHELL has been uninstalled",0 .end
hook.inc
zschell_hook: .db $83 ; used by os for hook safety check ld a,(parse_var) ; check the currently executed program type cp progobj jr z,run_program cp protprogobj jr nz,exit_zschell_hook run_program: exit_zschell_hook: or $80 ; reset zero flag, the parser can't continue to parse the variable ret

zSHELL.zip

Qu'en pensez-vous ? Il faudrait aussi discuter de l'header des programmes asm compatibles (pour ma part je pensais au moins inclure du code unsquishé au début qui afficherai un message d'erreur si le shell n'est pas installé).

La prochaine chose à coder est le hook en lui même (et gérer quelques autres cas gênant lors de l'installation : s'il y a déjà un hook d'installé, si l'appvar est dans l'archive etc...).

Quant au nom du shell, j'ai fait simple mais on peut tout à fait le changer, j'attend vos propositions ! happy

2

Une chose que l'on pourrait ajouter serait l'option d'activer le writeback (et vice-versa) dans le programme même. Si tu as choisi de ne pas l'activer, alors un petit message pourrait s'afficher comme avertissement, mais il y a des fois que je ne veux pas que le jeu "writeback".

Et maintenant le clippage de sprites ne va pas être si difficile comme avant smile Une autre chose qui serait utile serait pouvoir descomprimir tes sprites 1-bit dans un buffer quelque part pour ne pas avoir à le faire chaque fois que tu veux afficher un sprite. Par exemple :
;hl = source
;de = destination
;b = taille (en octets)
unpack:
 ld c,(hl)
unpack8_boucle_out:
 push bc
 ld b,8
unpack8_boucle_in:      ;unpack un octet
 xor a
 rl b
 sbc a,0          ;s'il y avait un carry, a=$FF, sinon, a=0
 ld (de),a     ;premier octet
 inc de
 ld (de),a      ;deuxième octet (des couleurs 16-bit)
 inc de
 djnz unpack8_boucle
 inc hl
 pop bc
 ld c,(hl)
 djnz unpack8_boucle_out
 ret
Je l'ai pas testé, mais ça c'est l'idée. Comme ça tu pourras descomprimir tes sprites dans la RAM additionnelle, par exemple, pour utiliser des routines de sprite plus vites.

3

Le write-back dans les programme eux-mêmes c'est une bonne idée, oui smile

En détectant si le hook est installé il n'y a même plus besoin d'appvar. Par contre il faudra que je regarde comment le réinstaller à chaque reset de la calc.

La décompression des sprites des sprites dans un buffer semble être une bonne idée aussi, mais je me demande comment gérer ça côté des utilisateurs (sauf si on demande le buffer en paramètre, comme ça ils se débrouillent ensuite ?).

Pour le moment j'essaie de faire comprendre au hook la différence entre l'exécution d'un programme et une simple fonction...

Autrement il semblerai que certains programmes/fonctions ont le caractère '#' ($23) en début de nom (à basic_prog+1 ou parse_var+1, après l'octet du type), mais je ne voit pas trop pourquoi (parce qu'ils sont lancés depuis l'écran d'accueil ?).

Le wikiti m'aide un peu ( http://wikiti.brandonw.net/index.php?title=83Plus:Hooks:9BAC ), mais il y a beaucoup de zones d'ombre (et pourquoi TI n'a pas pris la peine de documenter ces fonctions dans le SDK ??? mad).

4

Je n'ai jamais utilisé les hooks, donc je ne sais pas comment je pourrait t'aider :/

Et si le hook ne se réinstalle pas à chaque reset je crois que c'est pas trop grave, on peut simplement exécuter encore une fois l'app.

Quant aux décompression, j'ai quelques idées. La première, charger tes sprites comme ci :
sprite1:
.dw 8 ;taille du sprite en octets
.db %11111111
.db %10000001
.db %10000001
.db %10000001
.db %10000001
.db %10000001
.db %10000001
.db %11111111
Puis, quand tu décompresses le sprite tu n'as que charger l'adresse du sprite dans HL, la routine de décompression lira la taille du sprite (ici 8 octets), la mettre dans b, puis SMC l'adresse où le sprite va se décompresser (disons, $8000). Après avoir décompressé le sprite, tu peut envoyer l'adresse de sprite1 à la routine d'affichage, la routine lira l'adresse sauvée ($8000) et l'utilisera pour afficher le sprite.

Une autre idée serait de donner un id à chaque sprite selon l'ordre de décompression. Donc le premier sprite décompressé aura l'id 0, et le 100ème aura l'id 99. La routine de décompression sauvera les adresses dans une table dans saferam. Puis, pour afficher un sprite, tu envoies l'id (0-255) du sprite, pas son adresse. Il faudrait que ton code soit un peu plus organisé comme ci pour savoir (peut-être avec des equates) l'id de chaque sprite décompressé, mais tous les datas extras sont sauvés dans saferam.

Ou si tu ne demandais que comment savoir où décompresser les sprites, on peut avoir deux octets dans saferam qui contiennent l'adresse du buffer, si on veux la changer on n'a qu'y écrire la nouvelle adresse.

5

Oui mais c'est un peu contraignant pour l'utilisateur qu'on "empiète" sur les saferams, non ? Moi je verrai ça comme ça : l'utilisateur met dans un registre 16-bit l'adresse du buffer où la routine doit décompresser la sprite et dans un autre l'adresse du sprite (dont le premier octet est la taille du sprite), et la routine se charge du reste. Ensuite une autre routine permettrai d'afficher la sprite à partir de l'adresse d'un buffer quelconque, de sa largeur et de sa hauteur.

Comme ça ça ne limite pas les utilisateurs à 256 sprites.
chickendude (./4) :
Ou si tu ne demandais que comment savoir où décompresser les sprites, on peut avoir deux octets dans saferam qui contiennent l'adresse du buffer, si on veux la changer on n'a qu'y écrire la nouvelle adresse.

Autant demander l'adresse du buffer à chaque fois avec hl, de, bc ou af, non ?

edit : une version sans appvar :
zshell.z80
.nolist ;#include "ti84pcse.inc" #include "ti83p.inc" ; only for debug .list .org $4000 .db $80,$0f,$00,$00,$00,$00 ; program length = 0 .db $80,$12,$01,$04 ; program type = shareware for TI 83+ .db $80,$21,$01 ; app id = 1 .db $80,$31,$01 ; app build # = 1 .db $80,$48, "zSHELL " ; app name (must be 8 bytes long) .db $80,$81,$01 ; app page = 1 .db $80,$90 ; no default splash screen .db $03,$26,$09,$04,$04,$06f,$1b,$80 ; date stamp = 5/12/1999 .db $02,$0d,$40 ; encrypted TI date stamp signature .db $a1,$6b,$99,$f6,$59,$bc,$67 .db $f5,$85,$9c,$09,$6c,$0f,$b4,$03,$9b,$c9 .db $03,$32,$2c,$e0,$03,$20,$e3,$2c,$f4,$2d .db $73,$b4,$27,$c4,$a0,$72,$54,$b9,$ea,$7c .db $3b,$aa,$16,$f6,$77,$83,$7a,$ee,$1a,$d4 .db $42,$4c,$6b,$8b,$13,$1f,$bb,$93,$8b,$fc .db $19,$1c,$3c,$ec,$4d,$e5,$75 .db $80,$7f,$00,$00,$00,$00 ; program image length = 0 .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000 ; padding (header length must be 128 bytes long) start: di ; disable interrupts (todo : check which bcall may resume them) bcall(_clrlcdfull) ; clear screen bcall(_indicatoroff) ; disable run indicator bcall(_cleargbuf) ; clear graph buffer res texterasebelow,(iy+textflags) ; reset some textflags res textinverse,(iy+textflags) ; reset some textflags ld hl,$0501 ld (currow),hl ld hl,zshell_string call iputs bit parserhookactive,(iy+hookflags4) jr z,install_zshell ; no current hook ;in a,(pmpagea) ;ld hl,parserhookptr+2 ;cp (hl) ;jr nz,quit ; zshell hook already exists uninstall_zshell: ; todo : ask to destroy/chain current hooks or uninstall zshell hook bcall(_disableparserhook) ld hl,$0003 ld (currow),hl ld hl,uninstalling_string call iputs bcall(_getkey) bcall(_jforcecmdnochar) install_zshell: ld hl,zshell_hook ; put hook adress into hl in a,(pmpagea) ; put page # into a bcall(_setparserhook) ; install hook ld hl,$0003 ld (currow),hl ld hl,installing_string call iputs bcall(_getkey) quit: ; todo : ask for destroying or chaining it bcall(_jforcecmdnochar) ; quit the app iputs: ld a,(hl) or a ret z bcall(_putc) inc hl jr iputs zshell_hook: .db $83 ; used by os for hook safety check (add a,e can be used too) or a jr z,zshell_hook_start ; we just want to handle prgm, not TI-Basic functions exit_zshell_hook: xor a ret zshell_hook_start: ;ld a,(parse_var) ; check the currently executed program type ;cp protprogobj ;jr nz,hook_return_nz ;ld hl,parse_var ;rst rmov9toop1 ;bcall(_chkfindsym) ;ex de,hl ;ld a,(parse_var+1) ;cp '#' ;jr nz,exit_zshell_hook run_program: ld hl,test_str call iputs hook_return_nz: or $80 ; reset zero flag, the parser can't continue to parse the variable ret test_str: .db "test",0 zshell_string: .db "zSHELL",0 installing_string: .db "zSHELL has been installed",0 uninstalling_string: .db "zSHELL has been uninstalled",0 .end

Pour l'instant lancer l'app "toggle" l'installation du hook (qui ne fait rien d'autre à part afficher "test" lorsqu'on exécute une fonction).

6

A propos, as-tu vu app.inc ?

Et deux octets n'est pas trop, on pourrait utiliser asm_Flags ou un autre endroit que dont on ne se sert que très rarement. Comment penses-tu intégrer les routines de zSHELL dans les programmes ? Je crois que ion charge les routines à la fin du programme et mettre les pointeurs dans textShadow, je ne sais pas comment le font MirageOS/CrunchyOS/DoorsCS, mais je suppose qu'ils aussi utilisent du saferam. Mais je n'en suis pas sûr.

7

Oui j'avais regardé un peu app.inc mais au final ça ne sert qu'a créer l'header et gérer les pages, et je ne pense pas dépasser la première (du moins pour l'instant).

Pour les routines je ne sais pas encore vraiment comment faire, il faudra les caser dans la RAM obligatoirement je pense, mais je vais voir comment noshell/zstart font.

8

J'ai lu un comment de Kerm chez Cemetech qui disait que zStart patch l'OS pour l'exécuter après un RAM Clear. Et je crois que zStart/noshell auront obligatoirement à mettre au moins la table de vecteurs dans cmdShadow, sinon qu'est-ce qu'on va faire quand le programme fait un appel à l'un des routines d'ion ?

Je crois que j'ai vu ce que fait zStart. Regarde ces deux bouts de code :
	ld	b, 8					;ion a 8 routines
	ld	hl, cmdShadow+80		;la table de vecteurs d'ion commence à partir d'ici
makeVectorsLoop:
	ld	(hl), $CD				;c'est le HEX pour "call"
	inc	hl
	ld	(hl), cmdShadow&255		;LSB : tous les routines vont faire un appel à cmdShadow
	inc	hl
	ld	(hl), cmdShadow>>8		;MSB
	inc	hl
	djnz	makeVectorsLoop		;répéter
	
	ld	hl, ionFaker			;le code qui va exécuter la routine
	ld	de, cmdShadow			;sauvé dans au début de cmdShadow
	ld	bc, ionFakerEnd-ionFaker
	ldir

	in	a, (06)					;SMC la page de flash actuelle dans la routine ionFaker
	ld	(smc_ionFaker-ionFaker+cmdShadow+1), a
Ce code-ci crée la table de vecteur et charge un petit code pour exécuter les routines dans cmdShadow.

Puis quand on fait un appel à une des routines d'ion, le code d'ionFaker va s'exécuter :
;chargé dans cmdShadow
ionFaker:
	ex	(sp), hl				;hl = valeur dans la pile (le prochain octet après le call)
	push	de					;sauver de
	ld	de, cmdShadow+80+3		;début du vecteur + 3 (parce que hl = l'adresse de l'appel + 3)
	or	a						;reset carry
	sbc	hl, de					;(adresse de la routine appelée + 3) - (l'adresse du début du vecteur + 3)
								;hl = un numéro entre 0 et 21 (0 = la première routine, 21 = la 8ème)
	ld	de, myIonVectors		;une autre table qui contient des sauts aux routines d'ion dans zStart
	add	hl, de					;un numéro entre 0 et 21 + myIonVectors, l'offset de la routine appelée
	push	af					;sauver af
smc_ionFaker:
	ld	a, 00					;smc a remplacé $00 avec la page de FLASH où se trouve zStart (et donc les routines d'ion)
	out	(06), a					;charger la page FLASH
	pop	af						;restaurer a
	pop	de						;restaurer de
	ex	(sp), hl				;(sp) = l'adresse de la routine appelée
	ret							;sauter à la routine
ionRet:							;toutes les routines sautent ici, je suppose que l'on restaure la page FLASH actuelle
	push	af
	ld	a, $C2
	out	(06), a
	pop	af
	ret
Alors les routines mêmes il semble qu'elles restent dans zStart, on les met pas dans safeRAM/à la fin du programme.

9

C'est pas bête, je pense faire pareil, mais doit-on tenter de garder la compatibilité avec Ion (en adaptant ses routines au nouvel écran) ? J'hésite, ce serait peut être mieux de repartir sur du neuf.

edit : Le parser hook commence à me prendre la tête sick

_chkfindsym est sensé retourner 0 ou le # de la page flash dans laquelle est le programme dans le registre b, sauf que ça me renvoi toujours 0...
hook.inc
zshell_hook: .db $83 ; used by os for hook safety check (add a,e can be used too) 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 a,(parse_var) ; check the currently executed program type cp progobj jr z,zshell_hook_continue cp protprogobj jr nz,zshell_hook_return_z ; if it's not a prgm or a protected prgm, let the parser continue zshell_hook_continue: ld hl,parse_var rst rmov9toop1 bcall(_chkfindsym) ;ex de,hl ;ld a,(parse_var+1) ;cp '#' ;jr nz,zshell_hook_return_z ld a,b or a ; if the prgm is in ram, read it as it jr z,zshell_hook_read_data ; todo : unarchive or read the prgm from flash jr zshell_hook_return_nz zshell_hook_read_data: run_program: ld hl,test_str call iputs zshell_hook_return_nz: or $80 ; reset zero flag, the parser can't continue to parse the variable ret test_str: .db "test",0

10

Voici un bout de code que j'ai écrit :
		ld hl,nombre_de_programme
		rst	20h				;9 octets à (hl) dans OP1
		bcall(_ChkFindSym)	;chercher le programme dans OP1
							;hl = VAT, de = addresse du data
		ret	c				;c armé si pas encontré
		in a,(6)			;il faut sauvegarder la page FLASH actuelle
		ld (savePort),a			;sauver avec SMC
		ld a,b				;b = 0 si le fichier est dans RAM
		or a
		 ret z				;si pas dans le RAM, b = la page FLASH
		out (6),a			;a = la page FLASH où est notre fichier
;...
nombre_de_programme:
.db ProgObj,"PROGNAME",0
Tu es sûr que parse_var contient le type d'objet et son nom ? S'il retourne 0 je crois que c'est parce que l'objet doit être dans la RAM... Carry est armé si le programme/variable n'a pas été trouvé.

Et oui, tu as raison, je suppose que ça ne vaut pas la peine de supporter ion :P

11

Oui normalement après chaque appel du parser hook, parse_var contient le type et le nom du dernier programme lancé (mais d'ailleurs, même s'il est protégé, le type semble toujours être progobj ($05), alors qu'il devrait être protprogobj ($06)...).

Autrement les fonctions basiques types "sin(" etc... sont bien des fonctions de classe 1, 2 ou 3 ? Parce que c'est pareil, ça me renvoi toujours 0 (valeur de l'accumulateur au début du hook) sad

12

Je ne sais pas, je vais y jeter un coup d'oeuil dès que j'aurai le temps smile

Le code actuel est-il disponible quelque part ?

EDIT : A propos, si tu veux tester si un variable est entre deux numéros, disons 10 et 25, tu peux faire :
	ld a,(numéro)
	sub 10
	cp 25-10+1	;cp 16
	 jr nc,sauter
;faire quelque chose
;...
sauter:
	ret

13

zSHELL.zip

Je ferais peut être une page google code si on arrive jusqu'au point d'être capable d'exécuter des programmes avec nos propres routines.
chickendude (./12) :
A propos, si tu veux tester si un variable est entre deux numéros, disons 10 et 25, tu peux faire

Tiens j'aurai pas pensé à ça, ça va m'être utile même pour d'autres projets ! Merci tongue

14

J'ai testé avec l'émulateur et il semble que parse_var ne contient pas le nom du programme, mais je sais pas pourquoi. Mais il semble que tu peux tirer le nom de (basic_start), attends une minute et j'essayerai d'écrire quelque chose...

Et voilà, hook.inc :
zshell_hook:
    .db $83 ; used by os for hook safety check (add a,e can be used too)
    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,(basic_start)	;ce que l'on a écrit sur le homescreen
	ld a,(hl)
	cp $5F				;tProg, on pourrait même permettre l'utilisiteur de ne pas écrire prgm
	 jr nz,zshell_hook_return_z
zshell_hook_continue:
	rst rmov9toop1
	ld hl,op1
	ld (hl),5			;progObj
    bcall(_chkfindsym)
    ld hl,not_found_txt
     jr c,run_program
    ld a,b				;b = 0 (dans RAM) ou la page FLASH
    or a				;si a = 0, le programme est dans la RAM
    ld hl,ram_txt
	 jr z,zshell_hook_read_data
	    ld hl,flash_txt	;sinon, dans la FLASH
zshell_hook_read_data:
run_program:
    call iputs
zshell_hook_return_nz:
    or $80  ; reset zero flag, the parser can't continue to parse the variable
    ret

not_found_txt:
	.db "not found",0
ram_txt:
	.db "in RAM",0
flash_txt:
	.db "in FLASH",0

15

Ah génial, je ne comprenais pas pourquoi ça renvoyait "not found" pour un programme test en RAM, mais c'est parce qu'en faite il était vide... Mais c'est dommage de ne pas pouvoir simplement utiliser parse_var.

Maintenant il va falloir faire la différence entre les programmes TI-Basic et ceux en ASM, mais je crois que ça n'est pas si difficile que ça. Il faudrait peut être définir l'header, mais à part peut être un token spécial pour indiquer à quel shell se réfère le programme, et un octet (ou bit ?) pour spécifier le write-back, il n'y a rien d'autre à indiquer ? Le nom du programme peut être (même s'il n'apparaitra nul part avec ce shell) ?

Autrement, j'ai lu qu'il était possible avec un petit hack de lire un programme depuis la flash (sans le désarchiver), tu sais si c'est vraiment possible ? J'imagine que ça pose problème pour la lecture de données interne au programme/le SMC ?

16

En effet, je l'ai fait dans un projet. A vrai dire, c'est très simple. Tu simplement cherches le programme dans la flash puis le copies toi-même dans la RAM. Il faut que le programme s'exécute de $9D95, donc tu n'as que l'y copier (après avoir _insertmem la taille du programme). Ce que l'on fait en général c'est copier 768 octets à la fois (tout ce que l'on peut mettre dans saferam). Voici le code :
openFile:
;... le (nom/type du)  fichier à chercher doit être dans OP1
	bcall(_ChkFindSym)	;chercher le programme dans OP1
						;hl = VAT, de = addresse du data
	 ret	c				;c armé si pas encontré
	in a,(6)			;il faut sauvegarder la page FLASH actuelle
	ld (savePort),a
	ld a,b				;b = 0 si le fichier est dans RAM
	or a
	 ret z				;si pas dans le RAM, b = la page FLASH
	out (6),a			;a = la page FLASH où est notre fichier
	ex de,hl
	ld de,20				;
	add hl,de			;il y a 20 octets avant le début du data, le nom du program, sa taille, addresse, page de FLASH, etc.
;...
; hl = début des datas
;...
	ret

closeFile:
savePort = $ + 1
	ld a,0
	out (6),a
	ret

;merci à thepenguin77 de m'avoir aidé avec ce code-ci
;vérifier que l'on ne va pas lire hors de $4000-$7FFF
;si hl = $8000, il faut le remettre à $4000 est incrémenter la page d'où nous lisons
loadNextHL:
	inc hl
checkOverflow:
	ld a,h
	res 7,h			;bit 7 = $8000+
	set 6,h			;bit 6 = $4000+
	cp h
	 ret z
		in a,(6)	;charger la prochaine page de FLASH
		inc a
		out (6),a
		ret
Chaque fois que tu veux lire le prochain octet il faut faire un appel à loadNextHL. Après tu peux ld a,(hl) ou faire ce que tu voudras. Il faut le faire comme ça parce que si la valeur de HL dépasse $7FFF il faut charger la prochaine page FLASH.

On a aussi écrit une routine style LDIR :
;hl = position dans FLASH
;bc = combien d'octets à charger
;gbuf utilisé comme buffer
flashToBuffer:
	ld de,gbuf
flashToBufferLoop:
	ldi
	 ret po
	call checkOverflow
	jr flashToBufferLoop
S'il y a de l'espace dans l'app on peut écrire une routine plus rapide qui calcule combien d'octets il reste avant d'atteindre $8000 pour ne pas avoir à vérifier après chaque octet lu.

En bref, le programme reste dans l'archive, tu ne fais que le copier dans la RAM. Si le programme a changé pendant son exécution, il faudra le récrire dans l'archive (mais je ne sais pas comment faire cette dernière partie, je simplement "désarchive" le fichier, copier les changements, puis je le "rearchive". Je crois que l'on peut "unlocker" l'archive et changer seulement les octets qui ont changé, mais je ne sais pas comment le faire.

Et la différence entre les programmes TI-BASIC/asm, on peut pas simplement chercher le token AsmPrgm ? Mais je suppose que l'on pourrait gagner deux octets en l'omettant :P Et pour le moment, il n'existe aucun shell pour la 84+C wink Je m'avais toujours interessé aux shells, mais je n'en ai jamais écrit un.

EDIT : J'ai trouvé _WriteAByte, _WriteFlash, et Port 14

17

Cool, dès que j'en suis à l'exécution de programmes je test tout ça, merci tongue

Autrement ça y est j'ai fait la différenciation des programmes ASM "unsquishés" avec le reste (donc principalement TI-Basic, mais il faudrait pouvoir identifier les autres futurs types de programmes TI 84+CSE).
zshell.z80
.nolist ;#include "ti84pcse.inc" #include "ti83p.inc" ; only for debug #define program_size_count saferam1 .list .org $4000 .db $80,$0f,$00,$00,$00,$00 ; program length = 0 .db $80,$12,$01,$04 ; program type = shareware for TI 83+ .db $80,$21,$01 ; app id = 1 .db $80,$31,$01 ; app build # = 1 .db $80,$48, "zSHELL " ; app name (must be 8 bytes long) .db $80,$81,$01 ; app page = 1 .db $80,$90 ; no default splash screen .db $03,$26,$09,$04,$04,$06f,$1b,$80 ; date stamp = 5/12/1999 .db $02,$0d,$40 ; encrypted TI date stamp signature .db $a1,$6b,$99,$f6,$59,$bc,$67 .db $f5,$85,$9c,$09,$6c,$0f,$b4,$03,$9b,$c9 .db $03,$32,$2c,$e0,$03,$20,$e3,$2c,$f4,$2d .db $73,$b4,$27,$c4,$a0,$72,$54,$b9,$ea,$7c .db $3b,$aa,$16,$f6,$77,$83,$7a,$ee,$1a,$d4 .db $42,$4c,$6b,$8b,$13,$1f,$bb,$93,$8b,$fc .db $19,$1c,$3c,$ec,$4d,$e5,$75 .db $80,$7f,$00,$00,$00,$00 ; program image length = 0 .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000 ; padding (header length must be 128 bytes long) start: di ; disable interrupts (todo : check which bcall may resume them) bcall(_clrlcdfull) ; clear screen bcall(_indicatoroff) ; disable run indicator bcall(_cleargbuf) ; clear graph buffer res texterasebelow,(iy+textflags) ; reset some textflags res textinverse,(iy+textflags) ; reset some textflags ld hl,$0501 ld (currow),hl ld hl,zshell_string call iputs bit parserhookactive,(iy+hookflags4) jr z,install_zshell ; no current hook ;in a,(pmpagea) ;ld hl,parserhookptr+2 ;cp (hl) ;jr nz,quit ; zshell hook already exists uninstall_zshell: ; todo : ask to destroy/chain current hooks or uninstall zshell hook bcall(_disableparserhook) ld hl,$0003 ld (currow),hl ld hl,uninstalling_string call iputs bcall(_getkey) bcall(_jforcecmdnochar) install_zshell: ld hl,zshell_hook ; put hook adress into hl in a,(pmpagea) ; put page # into a bcall(_setparserhook) ; install hook ld hl,$0003 ld (currow),hl ld hl,installing_string call iputs bcall(_getkey) quit: ; todo : ask for destroying or chaining it bcall(_jforcecmdnochar) ; quit the app iputs: ld a,(hl) or a ret z bcall(_putc) inc hl jr iputs get_byte: push de ; de = vat pointer 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_size_count) dec (hl) ; just to make sure we're not reading out of the program (todo : check if prgm size are +1) 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: ld a,b bcall(_getbytepaged) ld (hl),b ret #include "hook.inc" zshell_string: .db "zSHELL",0 installing_string: .db "zSHELL has been installed",0 uninstalling_string: .db "zSHELL has been uninstalled",0 .end
hook.inc
zshell_hook: .db $83 ; used by os for hook safety check (add a,e can be used too) 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,(basic_start) ; what's on homescreen ld a,(hl) cp tprog jr nz,zshell_hook_return_z zshell_hook_continue: rst rmov9toop1 ld hl,op1 ld (hl),progobj bcall(_chkfindsym) ex de,hl ; cause of _getbytepaged parameters ld a,e_undefined bjumpc(_jerror) ld a,b ; b = 0 if in ram, else flash page # or a ld a,e_archived ; temporary bjumpnz(_jerror) zshell_hook_read_data: inc hl call get_byte ld e,a call get_byte ld d,a ; de now contains the size of the program ld (program_size_count),de call get_byte ret c ; the program is empty cp tasmprgm ld hl,asm_unsquished_txt jr z,zshell_hook_next ;cp tzshellprgm ;ld hl,zshell_txt ;jr z,zshell_hook_next ld hl,basic_txt zshell_hook_next: call iputs zshell_hook_return_nz: or $80 ; reset zero flag, the parser can't continue to parse the variable ret asm_unsquished_txt: .db "ASM unsquished",0 zshell_txt: .db "zSHELL",0 basic_txt: .db "TI-Basic (?)",0

zSHELL.zip

Par contre je ne sais pas pourquoi mais basic_start ne contient pas toujours le type et le nom du programme exécuté, et du coup ça fait une erreur "undefined" de temps à autres...?

18

Je n'ai reçu l'erreur "undefined" que quand le programme n'existait pas. Peut-être il faut écrire un zéro après le nom du programme (dans OP1) ? Mais même avec les noms courts je n'ai pas de problèmes.

Je crois que l'on peut commencer à coder la partie qui exécute les programmes grin Voici un bout de code que j'avais écrit pour sauter la limite de 8k (on peut peut-être l'optimiser et je suppose qu'il faudra faire quelques modifications, mais c'est un début) :
debut_routine:
	bcall(_ChkFindSym)
	 ret	c
	ld	a, b					;a = page flash
	or	a
	 ret	z					;quitter si dans la ram
	ex	de, hl					;hl = début du programme
	ld	de, appBackUpScreen
	ld	bc, 2+2+7+1+3+3+3
	push	af					;sauver page flash
		bcall(_FlashToRam)		;copier 22 octets (header/AsmPrgm) dans appbackupscreen
	pop	af						;restaurer page flash (possiblement pas nécéssaire)
	ld	bc, 2+2+7+1+3+3+3+$4000
	or	a
	sbc	hl, bc					;si hl <$4022, on a avancé à la prochaine page
	add	hl, bc					; il faut donc augmenter a
	adc	a, 0					;a+1 si on a avancé une page
	push	af
	ex	de, hl					;hl = prochain octet dans appBackUpScreen
	dec	hl
	dec	hl
	dec	hl
	ld	a, (hl)					;MSB de la taille du programme
	dec	hl						;
	ld	l, (hl)					;LSB de la taille du programme
	ld	h, a
	push	hl					;hl = taille du programme
	push	de
	ld	de, $9D95				;de = où charger le programme
	bcall(_InsertMem)			;créer de l'espace
	pop	hl						;hl = premier octet des datas du programme
	pop	bc						;bc = taille du programme
	pop	af						;af = première page de ses datas
	bcall(_FlashToRam)
	jp	$9D95					;l'exécuter

19

Donc pour notre propre header (celui des programmes), voilà un début : .nolist #include "ti84pcse.inc" .list .org usermem-2 .db texttok,tasm84ccmp ; permet au TI-OS de lancer le programme, je me demande quel serait le moyen le plus propre de lui indiquer ; que le programme n'est pas exécutable sans zshell (ion rajoutait un 'ret' juste après il me semble) ? .db 1 ; pour le write-back [...] .end

edit : un début de désarchivage des programmes (mais je suis à peu près sûr que ça ne marche pas encore tongue) :
zshell.z80
.nolist ;#include "ti84pcse.inc" #include "ti83p.inc" ; only for debug #define program_length_count saferam1 .list .org $4000 .db $80,$0f,$00,$00,$00,$00 ; program length = 0 .db $80,$12,$01,$04 ; program type = shareware for TI 83+ .db $80,$21,$01 ; app id = 1 .db $80,$31,$01 ; app build # = 1 .db $80,$48, "zSHELL " ; app name (must be 8 bytes long) .db $80,$81,$01 ; app page = 1 .db $80,$90 ; no default splash screen .db $03,$26,$09,$04,$04,$06f,$1b,$80 ; date stamp = 5/12/1999 .db $02,$0d,$40 ; encrypted TI date stamp signature .db $a1,$6b,$99,$f6,$59,$bc,$67 .db $f5,$85,$9c,$09,$6c,$0f,$b4,$03,$9b,$c9 .db $03,$32,$2c,$e0,$03,$20,$e3,$2c,$f4,$2d .db $73,$b4,$27,$c4,$a0,$72,$54,$b9,$ea,$7c .db $3b,$aa,$16,$f6,$77,$83,$7a,$ee,$1a,$d4 .db $42,$4c,$6b,$8b,$13,$1f,$bb,$93,$8b,$fc .db $19,$1c,$3c,$ec,$4d,$e5,$75 .db $80,$7f,$00,$00,$00,$00 ; program image length = 0 .dw $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000 ; padding (header length must be 128 bytes long) start: di ; disable interrupts (todo : check which bcall may resume them) bcall(_clrlcdfull) ; clear screen bcall(_indicatoroff) ; disable run indicator bcall(_cleargbuf) ; clear graph buffer res texterasebelow,(iy+textflags) ; reset some textflags res textinverse,(iy+textflags) ; reset some textflags ld hl,$0501 ld (currow),hl ld hl,zshell_string call iputs bit parserhookactive,(iy+hookflags4) jr z,install_zshell ; no current hook ;in a,(pmpagea) ;ld hl,parserhookptr+2 ;cp (hl) ;jr nz,quit ; zshell hook already exists uninstall_zshell: ; todo : ask to destroy/chain current hooks or uninstall zshell hook bcall(_disableparserhook) ld hl,$0003 ld (currow),hl ld hl,uninstalling_string call iputs bcall(_getkey) bcall(_jforcecmdnochar) install_zshell: ld hl,zshell_hook ; put hook adress into hl in a,(pmpagea) ; put page # into a bcall(_setparserhook) ; install hook ld hl,$0003 ld (currow),hl ld hl,installing_string call iputs bcall(_getkey) quit: ; todo : ask for destroying or chaining it bcall(_jforcecmdnochar) ; quit the app iputs: ld a,(hl) or a ret z bcall(_putc) inc hl jr iputs get_byte: push de ; de = vat pointer 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_count) dec (hl) ; just to make sure we're not reading out of the program (todo : check if prgm length are +1) 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 (hl),b pop bc ret #include "hook.inc" zshell_string: .db "zSHELL",0 installing_string: .db "zSHELL has been installed",0 uninstalling_string: .db "zSHELL has been uninstalled",0 .end
hook.inc
zshell_hook: .db $83 ; used by os for hook safety check (add a,e can be used too) 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,(basic_start) ; what's on homescreen ld a,(hl) cp tprog jr nz,zshell_hook_return_z zshell_hook_continue: rst rmov9toop1 ld hl,op1 ld (hl),progobj bcall(_chkfindsym) ex de,hl ; cause of _getbytepaged parameters ld a,e_undefined bjumpc(_jerror) call get_byte ld e,a call get_byte ret c ; the program is empty ld d,a ; de now contains the length of the program ld (program_length_count),de call get_byte ; skip t2bytetok/texttok call get_byte cp tasmprgm ld hl,asm_unsquished_txt jr z,zshell_hook_execute_prgm ;cp tzshellprgm ;ld hl,zshell_txt ;jr z,zshell_hook_execute_prgm jr zshell_hook_return_z ; TI-Basic program zshell_hook_execute_prgm: ; todo : skip zshell things ld a,b or a call nz,zshell_hook_unarchive ; todo : relocate non archived prgm before launch jp progstart zshell_hook_unarchive: push hl ld hl,(program_length_count) push bc bcall(_enoughmem) pop bc pop hl ld a,e_memory bjumpc(_jerror) ld a,b ld de,progstart ld bc,(program_length_count) bcall(_flashtoram) ret zshell_hook_return_nz: or $80 ; reset zero flag, the parser can't continue to parse the variable ret asm_unsquished_txt: .db "ASM unsquished",0 zshell_txt: .db "zSHELL",0 basic_txt: .db "TI-Basic (?)",0

20

Maintenant je bosse sur l'exécution des programmes dans RAM. Ça résulte assez compliqué :/ J'ai écrit une routine qui copie le program à $9D95, mais ça ne te permet utiliser que la motie de la RAM (sinon on aura pas espace suffisant pour le _InsertMem). Voice le "simple way" :
simpleWay:
;get program size
	ld e,(hl)
	inc hl
	ld d,(hl)				;de = program size, first two bytes in data
	dec de
	dec de					;-2 because of AsmPrgm token
;check if it starts with AsmPrgm token
	inc hl					;$BB
	ld a,(hl)
	cp $BB					;if first byte isn't $BB, not an assembly program
	 jr nz,zshell_hook_return_z	;parse as basic
	inc hl					;$6D AsmPrgm token (2 bytes)
	ld a,(hl)
	cp $6D
	 jr nz,zshell_hook_return_z	;if program is not an assembly program, quit
;create space at $9D95 to load the program
	inc hl					;first byte of program data
	push hl					;hl = first byte of prog data
	push de					;de = prog size (-AsmPrgm token)
		ex de,hl			;hl = prog size
		ld de,progstart		;$9D95
		bcall(_InsertMem)	;insert 'hl' bytes to $9D95
	pop bc					;bc = size of program
	pop hl					;hl = first byte of program data
	push bc					;save size of program
		add hl,bc			;we've inserted 'bc' bytes ;)
		ldir				;de = progstart
		call progstart		;run the program
;now delete that memory
	pop de					;de = number of bytes to delete
	ld hl,progstart			;hl = where to delete them from
	bcall($4357)			;_DelMem
	ret
Bientôt j'aurai fini le "hard way", au moins la première partie smile

EDIT : Ok, ça marche !
progstartLocation = saferam1	;current address in progstart
progAddress = saferam1+2		;current address of program in RAM

;the program is in RAM, so let's copy it to $9D95!
;hl = pointer to start of data
;de = VAT info (not important)
;a = 0 (in RAM) (also unimportant)
zshell_hook_execute_prgm_ram:
;get program size
	ld e,(hl)
	inc hl
	ld d,(hl)				;de = program size, first two bytes in data
	dec de
	dec de					;-2 because of AsmPrgm token
;check if it starts with AsmPrgm token
	inc hl					;$BB
	ld a,(hl)
	cp $BB					;if first byte isn't $BB, not an assembly program
	 jr nz,zshell_hook_return_z	;parse as basic
	inc hl					;$6D AsmPrgm token (2 bytes)
	ld a,(hl)
	cp $6D
	 jr nz,zshell_hook_return_z	;if program is not an assembly program, quit
	inc hl					;first byte of program data
load_program_to_progstart:
;hl = first byte of program data
;de = program size
	ld bc,progstart
	ld (progstartLocation),bc
	ld (progAddress),hl
	ex de,hl				;hl = size
load_loop:
;check if there are <768 bytes left to copy
	ld bc,768
	or a
	sbc hl,bc				;subtract 768 from the program size
	 jr nc,$+8				;if no carry, there are still more than 768 bytes to copy
		add hl,bc
		ld c,l
		ld b,h
		ld hl,$0000
	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)	;$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+XXX)
		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,load_loop

	call progstart			;run the program
;now rewrite the data back into the program
;...not done yet...
	ret


x7e3

Pour le moment tu ne peux l'exécuter qu'une fois parce que je ne copie pas le programme de nouveau (donc la seconde fois le programme sera vide :P). Mais je crois que je peut tout simplement invertir progstartLocation et progAddress...

21

Wow, bravo happy

C'est génial, j'ai adapté ton premier code au shell : zSHELL.zip tongue

0exz

Mais je ne sais pas pourquoi j'ai des erreurs "undefined" de temps à autres (comme si _chkfindsym ne trouvait pas le programme)... sad
hook.inc
zshell_hook: .db $83 ; used by os for hook safety check (add a,e can be used too) 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,(basic_start) ; 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 ex de,hl ; cause of _getbytepaged parameters ld a,e_undefined bjumpc(_jerror) ; if not found, throw an "undefined error" call get_byte ; else start to read it ld e,a call get_byte ; first two bytes are length of the program jr c,zshell_hook_return_nz ; if empty, don't parse ld d,a dec de dec de ; we don't count the first two bytes (t2bytetok/texttok+tasmcmp/tasm84ccmp) into the program length ld (program_length_count),de call get_byte ; skip t2bytetok/texttok call get_byte cp tasmcmp jr z,zshell_hook_execute_prgm ;cp tzshellprgm ;ld hl,zshell_txt ;jr z,zshell_hook_execute_prgm jr zshell_hook_return_z ; TI-Basic program zshell_hook_execute_prgm: ; todo : skip zshell things ld a,b or a call nz,zshell_hook_unarchive ; todo : relocate non archived prgm before launch simpleWay: ; create space at progstart to load the program push hl ; hl = first byte of prog data push de ; de = prog length-2 ex de,hl ;hl = prog size ld de,progstart ; $9d95 bcall(_insertmem) ; insert hl bytes to progstart pop bc ; bc = size of program pop hl ; hl = first byte of program data push bc ; save size of program add hl,bc ; we've inserted bc bytes ;) ldir ; de = progstart call progstart ; run the program ; now delete that memory pop de ; de = number of bytes to delete ld hl,progstart ; hl = where to delete them from bcall(_delmem) ret zshell_hook_unarchive: push hl ld hl,(program_length_count) push bc bcall(_enoughmem) pop bc pop hl ld a,e_memory bjumpc(_jerror) ld a,b ld de,progstart ld bc,(program_length_count) bcall(_flashtoram) ret zshell_hook_return_nz: or $80 ; reset zero flag, the parser can't continue to parse the variable ret

Enfaite j'ai utilisé call get_byte pour calculer la taille du programme et son type pour ne pas avoir plus tard à d'abord désarchiver le programme avant de le tester (savoir s'il est vide et si c'est bien un programme ASM, enfin quoique si on veut permettre l'exécution de programmes TI-Basic archivés...?)

Je vais adapter le "hard way" (ah et je n'ai pas testé le désarchivage, mais ça m'étonnerai que ça marche) smile

edit : autrement je n'avais pas fait gaffe, mais un shell TI 85 porte déjà ce nom ZShell (enfin c'est pas exactement identique, mais ça peut être trompeur, non ?). J'aime bien ce nom mais s'il faut on peut le changer.

edit 2 : voilà :
hook.inc
zshell_hook: .db $83 ; used by os for hook safety check (add a,e can be used too) 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,(basic_start) ; 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 ex de,hl ; cause of _getbytepaged parameters ld a,e_undefined bjumpc(_jerror) ; if not found, throw an "undefined error" call get_byte ; else start to read it ld e,a call get_byte ; first two bytes are length of the program jr c,zshell_hook_return_nz ; if empty, don't parse ld d,a dec de dec de ; we don't count the first two bytes (t2bytetok/texttok+tasmcmp/tasm84ccmp) into the program length ld (program_length_count),de call get_byte ; skip t2bytetok/texttok call get_byte cp tasmprgm jr z,zshell_hook_execute_unsquished_asm_prgm cp tasmcmp jr z,zshell_hook_execute_compiled_asm_prgm ;cp tzshellprgm ;ld hl,zshell_txt ;jr z,zshell_hook_execute_zshell_prgm jr zshell_hook_return_z ; TI-Basic program zshell_hook_execute_unsquished_asm_prgm: ;call zshell_hook_program_start_begin bcall(_executeprgm) ; can only run unarchived prgm jr zshell_hook_return_nz 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_return_nz: or $80 ; reset zero flag, the parser can't continue to parse the variable ret 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_count) push bc bcall(_enoughmem) pop bc pop hl ld a,e_memory bjumpc(_jerror) ld a,b ld de,progstart ld bc,(program_length_count) bcall(_flashtoram) ret

Enfaite les erreurs "undefined" étaient simplement dues au fait que le hook se terminait avec le zero flag mis cheeky

22

Attention: Je suis une américaine et je ne parle pas bien le français. Je suis désolé en avance pour ma grammaire .___.

D: Je suis désolé, je pensais que j'ai déjà posté. Il y a été deux jours depuis je "l'ai posté" XD

J'ai crée ces codes:

Un Hook: .db 83h or a jr z,$+4 ExitHook3: cp a ret ld hl,(OP1) ld bc,2305h or a sbc hl,bc jr nz,ExitHook3 ld hl,(nextParseByte) ld a,5Fh cp (hl) jr nz,ExitHook3 ld de,OP1+1 ld b,8 CopyNameLoop: inc hl ld a,(hl) cp 30h jr c,FinishCopyLoop cp 3A jr nc,FinishCopyLoop cp 41h jr c,FinishCopyLoop cp 5Ch jr nc,FinishCopyLoop ld (de),a inc de djnz CopyNameLoop FinishCopyLoop: xor a ld (de),a bcall(_ChkFindSym) jr c,ProgNotFound ld a,b or a ex de,hl jr z,DataAtAHL ld b,0 ;BC = name size add hl,bc ld c,10 add hl,bc bit 7,h jr z,$+7 inc a set 6,h res 7,h DataAtAHL: push hl push af ld bc,8 ld de,OP2 bcall(_FlashToRAM2) pop af pop hl ;Now OP2 has the first 8 bytes of data (first two bytes are the size of the var) ;A is the flash page the the size bytes start on ;HL points to to the size bytes
Utilisez le 8 octets pour le taille de la programme et le premier 6 octets de la programme pour le "header."


- routine qui copie un buffer de 768 octets au milieu de l'écran (ou 1 bit = 1 pixel)


Voila smile : Define96x64Window: ld hl,$10B8 ; BGR mode, increment order ld a,$03 call SetLCDRegister ld hl,0 ;coord start ld a,20h ;set y coord = 0 call SetLCDRegister+2 ;A incremented to 21h call SetLCDRegister+2 ;set x coord = 0 ld a,50h ;horizontal call SetLCDRegister+2 ;set y coord = 0 ld hl,63 call SetLCDRegister+2 ;set y coord = 63 ld hl,0 call SetLCDRegister+2 ;set x coord = 0 ld hl,95 call SetLCDRegister+2 ;set x coord = 95 BWImage: ;Inputs: ; HL points to the data ; the window is already defined ;Outputs: ; B,D,E are all 0 ; A is either $00 or $FF ; C is the last byte of the buffer ld de,3 ;10 10 BWLoop: ; ld b,8 ;7 7*768 ld a,(hl) ;7 7*768 cpl ;4 4*768 ld c,a ;4 4*768 BWLoop2: ; rlc c ;8 8*6144 sbc a,a ;4 4*6144 out (11h),a ;11 11*6144 out (11h),a ;11 11*6144 djnz BWLoop ;13|8 768(13*8-5) dec d ;4 4*768 jr nz,BWLoop ;12|7 12*768-15 dec e ;4 4*3 jr nz,BWLoop ;12|7 12*3-5 ret ;10 10 ;Total time: ;314160 t-states. SetLCDRegister: ld c,$11 out ($10),a \ out ($10),a out (c),h out (c),l inc a ret

- dessin de rectangle pleins/vides, cercles, lignes

Dessiner un rectangle sur l'écran: Rectangle: ;Inputs: ; DE = color ; 4 pushes to the stack in order: ; push <width> ; push <right coordinate> ; push <height> ; push <upper coordinate> ;RAM: needs 2 bytes of RAM: ; (TempWord1) is two bytes ld hl,$10B8 ; BGR mode, increment order ld a,$03 call SetLCDRegister pop hl \ ex (sp),hl ld a,20h ;set upper coordinate call SetLCDRegister+2 ;A incremented to 21h ld a,50h ;horizontal call SetLCDRegister+2 ; ld b,h ld c,l pop hl \ ex (sp),hl ld (TempWord1),hl add hl,bc call SetLCDRegister+2 ;set lower coordinate pop hl \ ex (sp),hl ld a,21h call SetLCDRegister+2 ld a,52h call SetLCDRegister+2 ;set right coordinate ld b,h ld c,l pop hl \ ex (sp),hl push hl add hl,bc call SetLCDRegister+2 ;set left coordinate pop hl ;width ld a,(TempWord1) ; ld b,a ;b is height ;DE is color ;C is 11h ;B is the height ;HL is the width dec hl inc h inc l push hl FillRectLoop: out (c),d out (c),e dec l jr nz,FillRectLoop dec h jr nz,FillRectLoop pop hl djnz FillRectLoop-1 ret

Et je créerai le code pour les cercles, aussi grin
Grammer : v1.05.07.11 (5 juillet 2011)

Grammer 83/82 : 0%

23

Wow c'est génial, merci smile

Je vais tenter de comprendre comment ça marche car ça m'a l'air très optimisé, bravo tongue

De mon côté je tente de gérer l'exécution de programmes TI-Basic archivés (en gros je les désarchive avec _flashtoram à $9d95 avant d'utiliser _parseinp, mais ça ne marche pas encore).

edit : Aussi, qu'est censé contenir OP1 au début du hook ? Le wikiti dit de ne pas s'y fier.

24

Peut-être pour les programmes BASIC tu peux créer un nouveau programme dans RAM, l'y copier, puis exécuter ce nouveau programme ? Je crois que les programmes TI BASIC peuvent s'exécuter de n'importe quel endroit dans RAM. Peut-être quelque chose avec : http://wikiti.brandonw.net/index.php?title=83Plus:BCALLs:4C3C ?

25

J'ai trouvé une page intéressante : http://z80-heaven.wikidot.com/shells . Je tenterai bien de faire un système d'exécution de programmes compressés (comme crunchyos), mais je me demande si ça fait vraiment gagner de l'espace (je ferai quelques tests).

Autrement je me demande, lorsqu'un programme TI-Basic est désarchivé et exécuté, s'il fait appel à un autre programme TI-Basic archivé, il n'est pas possible de le désarchiver à son tour ? Ou alors il faut déplacer le programme actuel (progstart+la taille du deuxième programme), copier le nouveau à progstart, l'exécuter, puis quand on a finit replacer le premier programme ?

Ça risque d'être difficile à coder si le deuxième programme fait appel à un troisième etc..., non ?

26

Je crois que les programmes TI-BASIC peuvent s'exécuter de n'importe quel endroit dans la RAM, il ne faut pas les copier à progstart. On pourrait peut-être écire un autre hook pour le token prgm, quand on exécute ce token notre hook cherchera le programme et le desarchiver s'il est dans l'archive avant de le faire courir. Je ne sais pas s'il serait plus efficace de le copier dans un nouveau programme et faire courir le nouveau programme. Pour le moment je vais seulement m'occuper des programmes asm grin

27

J'ai un début de gestion des programmes TI-Basic archivés (grâce à la source de noshell) : on crée un programme temporaire avec un nom unique, puis on y copie les données archivées avant de l'exécuter, mais je ne sais pas pourquoi ça bug encore (le programme temporaire semble bien créé) :/
hook.inc
zshell_hook: .db $83 ; used by os for hook safety check (add a,e can be used too) 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,(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 ex de,hl ; cause of _getbytepaged parameters bjumpc(_errundefined) ; if not found, throw an "undefined error" call get_byte ; else start to read it ld e,a call get_byte ; first two bytes are length of the program jr c,zshell_hook_return_nz ; if empty, don't parse ld d,a dec de dec de ; we don't count the next two bytes (t2bytetok/texttok+tasmcmp/tasm84ccmp) into the program length ld (program_length_count),de call get_byte ; skip t2bytetok/texttok call get_byte cp tasmprgm jr z,zshell_hook_handle_unsquished_asm_prgm cp tasmcmp jr 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 push hl push 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_count) push af bcall(_createprotprog) pop af pop bc pop hl bjumpc(_errmemory) push hl push bc inc de inc de ; de = data section (skip the length bytes) xor a ld (parse_var),a ld (parse_var+1),a pop bc pop hl ld a,b ld bc,(program_length_count) 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_count) ; push bc ; bcall(_enoughmem) ; pop bc ; pop hl ; ld a,e_memory ; bjumpc(_jerror) ; ld a,b ; ld de,progstart ; ld bc,(program_length_count) ; 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 find_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 find_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,0

zSHELL.zip

J'ai aussi du mal à comprendre le handler des erreurs, et notamment pourquoi est-ce qu'il faut faire un "res 7,a" ?
chickendude (./26) :
On pourrait peut-être écire un autre hook pour le token prgm, quand on exécute ce token notre hook cherchera le programme et le desarchiver s'il est dans l'archive avant de le faire courir.

Il me semble que noshell/zstart font ça (d'où l'utilisation de programmes temporaires avec un ID unique dans le nom), il faudra que je vérifie. On aura peut être même pas besoin de créer un nouvel hook.

28

J'ai un peu "débuggé" la partie du code qui sert à désarchiver les programmes TI-Basic (juste au dessus du label zshell_hook_return_nz), mais je ne sais pas pourquoi le programme temporaire se remplit de n'importe quoi (alors que les paramètres de _flastoram semblent correctes) :/
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,(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 ex de,hl ; cause of _getbytepaged parameters bjumpc(_errundefined) ; if not found, throw an "undefined error" 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 dec de dec de ; we don't count the next two bytes (t2bytetok/texttok+tasmcmp/tasm84ccmp) into the program length ld (program_length_count),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_count) 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_count) 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_count) ; push bc ; bcall(_enoughmem) ; pop bc ; pop hl ; ld a,e_memory ; bjumpc(_jerror) ; ld a,b ; ld de,progstart ; ld bc,(program_length_count) ; 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 find_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 find_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

29

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 ?! confus
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

30

http://www.omnimaga.org/index.php?topic=6989.msg264864#msg264864

[nombre d'octets: nom]
Flash archive variable format:

[1:status flag] [2:archived variable total size] [1tonguerog type] [1:T2] [1:version] [1tongueage] [2:address] [1:chars in name] [name length:name] [2:size of program] [size of programtonguerogram data]
So, I have these mentally grouped. In this order, it's 3+3+3+1+nameLength+2 and then the last +2 is for BB 6D. Really, the archive is just a vat entry with those extra three bytes out front.


La taille du programme n'est pas toujours la même, donc il faut lire la taille du nom et l'ajouter pour arriver à la taille du jeu/les données smile