Les deux programmes

Annexe technique · Accueil · English

En résumé : qui fait quoi

Le jeu se compose de deux programmes qui partagent une même session DOS. MAUPITI1.EXE est le jeu ; maup.exe est son moteur.

MAUPITI1.EXE maup.exe
Écrit en Borland Pascal Turbo C et assembleur
Rôle Décide de ce qui se passe Fait ce qui touche au matériel ou aux fichiers de données
S'occupe de Commandes, temps, horaires, conversations, énigmes, questionnaire, sympathie ; quels calques composent une scène et quelle réplique dire Fichiers et archives, décodage des images et du texte, vidéo, palettes et fondus, musique, lecture de la parole, souris, sauvegardes
Données Interprète les tables de jeu de l'enregistrement 0x2A et l'état venant de SAUP.MAU, une fois chargés Charge tous les fichiers : archives .CON, MUS.HUF, SND.HUF, .MAU

Comment ils fonctionnent ensemble :

  1. MAUPITI.BAT lance MAUPITI1.EXE, qui reste résident et rend la main à DOS sans rien faire jouer.
  2. Le fichier de commandes lance ensuite maup.exe, qui installe ses services sur INT 0FEh, détecte la carte son et joue l'introduction.
  3. maup.exe rappelle MAUPITI1.EXE, dont la boucle principale fait alors tourner le jeu jusqu'à la fin.
  4. À partir de là, MAUPITI1.EXE a la main et appelle maup.exe par 51 services INT 0FEh.

Donc MAUPITI1.EXE est chargé en premier et maup.exe est le processus qui reste actif, mais c'est MAUPITI1.EXE qui mène le jeu. Par exemple, pour dire une réplique, MAUPITI1.EXE choisit la phrase et le personnage, et maup.exe construit et joue le son.

Les détails et les preuves suivent.

Fichiers

Fichier Taille Notes
maup.exe 56 577 o MZ 16 bits, runtime Turbo C 1988. Gère les fichiers, la vidéo, le son et la souris.
MAUPITI1.EXE 76 544 o Logique du jeu en Borland Pascal, avec 51 stubs clients INT 0FEh, lancé en premier par MAUPITI.BAT.
MAUPITI1.olz 32 717 o Compression LZEXE LZ91 du même programme : il se décompresse en une image identique de 70 912 octets.
INSTALLE.EXE 12 684 o Installateur Turbo C ; contient md c:maupiti, copy *.* c:maupiti et INSERT DISK No %d.

MAUPITI.BAT : echo off, maupiti1, maup %1.

Structure de maup.exe (vérifié)

  • e_cparhdr = 0x80, donc l'image commence au fichier 0x800 = EA 0x10000. CS:IP = 0000:0000, SS:SP = 11C4:00E6, 444 relogements.
  • dseg est le paragraphe d'image 0xA42 (EA 0x1A420) ; la pile est le paragraphe 0x11C4 (EA 0x21C40).
  • Il y a 24 segments de code relogés : 0, 53, 84, 159, 2DB, 493, 5FA, 6F0, 742, 7AB, 805, 8E8, 968, 96C, 97F, 9DF, 9E3, 9E9, A1A, A2F, A31, A34, A3B, A3E. Ce sont des segments ordinaires d'un programme multi-segments. Rien dans le fichier n'indique de gestionnaire d'overlays ni de données d'overlay.
  • La taille d'image de l'en-tête est de 56 548 o. Les 29 derniers octets sont une signature de groupe de diffusion, lettres décalées de -1 et parties séparées par NUL : The X Web, - www.lankhor.net.
  • Les fonctions utilisent couramment push bp / mov bp,sp : 160 occurrences brutes de 55 8B EC.
  • INT 21h : 67 sites CD 21 (vérifié). La répartition par AH des travaux antérieurs est non vérifiée.

Démarrage (vérifié)

  • 0x10102 : le démarrage C appelle main en 0x53:0 = _main EA 0x10530, qui appelle 0x53:6 = Game_Main EA 0x10536.
  • Game_Main teste d'abord les ports 0x210-0x260 à la recherche d'une Sound Blaster avec Snd_ProbeSbDsp EA 0x107FC (réinitialisation en base+6, attend 0xAA en base+0xA). Il stocke ensuite le résultat dans bSoundCard (DS:F6).
  • 0x105C0-0x105F2 : stocke ds:0xDA = 0x5000, puis fait six appels far d'initialisation. Le dernier est 0x6F0:4 = Font_LoadCharset EA 0x16F04, qui joue l'introduction.
  • 0x105F7 : publie le DS de maup.exe en 0000:03C4.
  • 0x10603-0x10617 : place IVT[0xFE] à 0x53:0xF8 par écriture directe. Le segment 0x53 est relogé.
  • 0x10618 : charge DS depuis 0000:03C6 et saute en 0x84:0x3CB = EA 0x10C0B, qui fait call far [0000:03C8] vers MAUPITI1.

Gestionnaire INT 0FEh (vérifié)

Le gestionnaire est dans maup.exe en 0x53:0xF8 = EA 0x10628, juste après un push bp / mov bp,sp en 0x10625.

  • AX = numéro de service ; CX = décalage de pile d'un bloc d'arguments en mots.
  • Il sauvegarde les registres, charge DS depuis 0000:03C4, positionne bInInt0FE et saute en 0x10653 + (AX-1)*8.
  • Chaque emplacement de 8 octets est call far target / jmp common_exit. Sortie en 0x107E8, puis iret en 0x107FB.
Svc EA cible Nom Svc EA cible Nom
02 0x15A38 Vid_DrawTextLines 1A 0x123F9 Con_LoadRec22Images
09 0x157C3 Txt_DrawIndexed 1C 0x1135D Vid_ArenaAlloc
0A 0x11A20 Ui_DrawWidget 23 0x11F39 Save_WriteGame
0B 0x11E12 Save_LoadGame 28 0x141D9 Mau_LoadFiles
17 0x1428C Ui_CaptureSpriteSheet 2B 0x148BC Demo_Init
19 0x123D4 Con_LoadRecordPlus1E autres voir symbols.tsv SvcNN si non identifié

Les principaux groupes, lus dans leur code :

Services Noms Ce qu'ils font
03, 04, 05 Mem_PeekByte, Mem_PeekBE16, Mem_PeekBE32 lisent via un pointeur far, en convertissant depuis le gros-boutien
1F, 20, 21 Mem_PokeByte, Mem_PokeBE16, Mem_PokeBE32 la même chose pour les écritures
01, 06 Mem_SumBytes, Mem_SumBE16 additionnent les N premières entrées d'une table
26 Table_EntrySize différence entre deux mots gros-boutiens adjacents
0F Table_GetEntry recherche dans une table ; MAUPITI1 s'en sert sur le tampon de l'enregistrement 0x2A
15 Rand_Range valeur entre deux bornes, à partir du compteur DS:63F
0D, 0E, 1D, 27 Vid_ClearRect, Img_Draw, Vid_CopyRect, Vid_DrawLine dessin (les rôles de rectangle et de ligne sont déduits)
18, 1A, 1B Con_LoadRoom, Con_LoadRec22Images, Con_LoadRec23 chargent un lieu, un portrait, la carte et les petits portraits
1E Speech_Say compile et joue une réplique : voir Parole
14 Svc14 loupe : redessine une zone en double taille avec le sprite 0x27 sous-enr. 7 (déduit)
22 Svc22 recolore le cadre selon le lieu, avec la table 0xC9 (déduit)
2C, 2D Snd_PlayMusic, Snd_Stop musique (Snd_Stop est déduit)
31, 33 Time_DelayShort, Time_Delay boucles d'attente

Con_LoadRoom est le service 0x18. Pal_TimeOfDayB (service 0x2A) choisit la palette d'un lieu selon l'heure ; Formats de fichiers, scènes et palettes décrit tout le système de palettes. Pal_TimeOfDayA (service 0x29) fait le même test sur l'heure.

Ainsi MAUPITI1, programme Pascal petit-boutien, lit les données gros-boutiennes du jeu par ces services.

maup.exe s'appelant lui-même par INT 0FEh

CD FE apparaît sept fois, mais 0x13B8F est l'opérande du jmp en 0x13B8E. Les six vrais sites :

EA Service Taille du bloc
0x12194 0x24 0x1C
0x121A9 0x0A 0x18
0x12269 0x09 0x38
0x12363 0x08 0x10
0x1238A 0x1D 0x10
0x123CB 0x24 0x1C

Boîte aux lettres en mémoire basse

Emplacement Écrit par Contenu
0000:03C4 maup.exe DS de maup.exe
0000:03C6/03C8/03CA MAUPITI1 EA 0x20B80 son DS, puis IP de retour+9 et CS
0000:03F8/03FA maup.exe IVT[0xFE]

MAUPITI1.EXE (vérifié avec ndisasm)

EA = file + 0xEA00 ; en-tête 0x1600 o ; 1 378 relogements ; point d'entrée EA 0x1EF37. Segments : 0 (code principal), 0xF21 (une routine Keep), 0xF23 (bibliothèque et stubs de services), 0x10B8, 0x10F1 (runtime Borland), 0x114C (données).

Comment les deux programmes se rejoignent

  1. Main EA 0x1EF37 initialise le runtime, puis appelle Mailbox_Publish EA 0x20B80. Celui-ci stocke son DS, l'IP de retour + 9 et CS en 0000:03C6-03CB.
  2. Les instructions suivantes appellent Dos_Keep(3) en EA 0x1F210 (INT 21h AH=31h). Le programme reste résident et le fichier de commandes lance maup.exe.
  3. maup.exe met en place ses services, puis fait call far [0000:03C8]. L'IP de retour + 9 est EA 0x1EF4D, l'instruction après Dos_Keep, donc Main continue à l'intérieur du processus de maup.exe.
  4. Main calcule des pointeurs de tampons, puis appelle Game_LoadAssets EA 0x12722 et Game_InitOnce EA 0x186D9, puis répète Game_MainLoop EA 0x1EBC8 jusqu'à ce que DS:131 soit non nul.

Ainsi MAUPITI1.EXE contient la logique du jeu et appelle maup.exe pour les fichiers, la vidéo, le son et les entrées.

Constatations

  • Stubs : il y en a 51, chacun mov ax,N / mov cx,bp / add cx,6 / int 0FEh, numérotés de 1 à 51. Les cinq autres occurrences de CD FE sont des déplacements de mov [bp+di-0x133],ax, à partir de 0x17D6E. Le nombre d'appels par service est dans symbols-maupiti1.tsv ; le nom IDA Maup_Svc13 (7 appelants) est en décimal, c'est donc le service 0x0D.
  • INT 21h : 21 sites. L'un est Keep ; les autres sont dans le segment du runtime Borland. Ses appels de vecteurs visent 00h, 23h, 24h et 3Fh, donc aucun ne pose le vecteur 0FEh.
  • Runtime de fichiers : les seules routines du runtime appelées en far sont en 0x20F10, 0x20FE8, 0x21154, 0x2116D, 0x21189 et 0x211A4. Le code fichier INT 21h à partir de 0x2136E n'a aucun appelant far, donc le code du jeu ne s'en sert pas. Tous les accès aux fichiers du jeu passent par les services.
  • Matériel : un balayage linéaire ne trouve aucun vrai in, out, INT 10h ou INT 33h, et un seul iret en 0x20FD5. Ses trois occurrences de in/ins et les octets CD 33 sont des décodages désalignés ou des opérandes. Les deux sites rep movsb sont du code du runtime, donc rien ne copie de gestionnaire.
  • Texte : les sept suites imprimables du fichier sont des fragments du runtime, comme l'avaient vu les travaux antérieurs. Le texte du jeu est dans G3.CON.

État du jeu

Le service 7 renvoie un pointeur far vers le DS:166 de MAUPITI1, base d'un bloc d'état de 0x99B octets. Game_MainLoop EA 0x1EBC8 le remplit depuis SAUP.MAU (service 0x28), et le restaure depuis une sauvegarde avec le service 0x0B. Donc SAUP.MAU est l'état de départ du jeu, suivi de 8 octets de plus.

DS: Décalage dans SAUP.MAU Valeur de départ Rôle
166 0 26 numéro du lieu actuel ; son enregistrement .CON est ce nombre moins 1
168 2 20 temps en demi-heures, soit 10 h 00 : le code des palettes s'en sert pour l'heure (Formats de fichiers, scènes et palettes)
16A 4 0 passé avec le temps ; mot haut ou compteur de jours (déduit)
16C 6 79 condition, 0-99 ; des paliers de 20 points choisissent de « Lessivé » à « La pêche »
16E 8 50 score caché de sympathie, abaissé par Game_AddSympathy (voir Logique de jeu)

Structure d'un tour

Game_MainLoop charge l'état et appelle Room_Enter EA 0x141CB, puis exécute Game_Turn EA 0x1E220 jusqu'à ce que DS:132 ou DS:134 soit positionné. Si c'est DS:134, il exécute une séquence de clôture qui affiche une chaîne de classe 6. Main_Body répète Game_MainLoop jusqu'à ce que DS:131 soit positionné.

Chargement : Game_LoadAssets EA 0x12722

Con_LoadRecord EA 0x20691 appelle le service 0x19 avec record - 0x1E :

Enregistrement Sous-enr. Pointeur (DS:) Taille utilisée
0x28 0 A8 banques 1-7 des tailles de chaînes, 3 178 o
0x29 0 A4 banques 1-7 du texte, 45 410 o
0x2A 0 AC 0xA39E = 41 886 o
0x27 0 E4
0x27 7, 8 F8, 104
0x27 5, 1 BC chargés pour un traitement ultérieur
0x27 6 100

Suivant : Logique de jeu · Annexe technique · Accueil