MultiMente_LFN

Multi Mente con nombres largos — notas técnicas

Documento de referencia del parche (versión 2): qué hace, límites, cómo funciona por dentro y qué se probó. Para aplicarlo, ver el LEEME.

Multi Mente 2.07_A (MOGU) solo se publicó en binario: el parche está hecho a mano sobre el desensamblado. src/mmlfn.asm es el código nuevo y src/parchear.py lo ensambla con pasmo y lo aplica al MM.COM original; tools/hacer_parche.py hace de ahí el MM_LFN.ips y los aplicadores.

Vale para dos bases (src/parchear.py elige por el sha1; ver «La variante RC5» más abajo):

Base Original (de referencia) Parcheado
2.07_A 23.539 bytes, sha1 db7316e2b8f17deb1c34df909e2b8da8133e1601 25.726 bytes, sha1 e69bb4e32c1e86b301fc9e9053d8d264dec1ae0e
2.07A+ RC5 23.552 bytes, sha1 09c4a6b4f6fa4db19e94fa08fdcba0da2a3c29d0 25.726 bytes, sha1 12b9f581186abb647c90b37a0fef23ea55af0e83

El arreglo de Nextor y cómo se reconoce la versión

El arreglo. La wiki de Multi Mente en MSX.org dice que con Nextor sale «Not MSX-DOS Disk» y que se corrige buscando 3A E1 5F CB 4F CA en MM.COM y cambiando el CA por C3. Es LD A,(5FE1h) / BIT 1,A / JP Z,3E4Ah: sin arreglo, MM usa su propio lector de sectores (3D60h-3DDDh, solo FAT12) cuando el bit está a 1, y con Nextor falla; con JP 3E4Ah incondicional usa siempre el lector por la API de DOS 2. Las dos bases de referencia ya lo llevan (C3 en el desplazamiento 3C5Dh del fichero; también el MM.COM japonés 2.07K+ de la RC5, en otro sitio). No tenemos ninguna copia real sin el arreglo: las pruebas la fabrican cambiando ese byte. Este parche depende de él: sobrescribe 3D60h-3DDDh, el lector que el arreglo deja sin uso (comprobado en ejecución, ver las pruebas con la RC5), así que un MM.COM con CA no se puede parchear con solo el .ips.

Cómo reconoce aplicar.py/aplicar.html lo que les das (el mismo algoritmo en Python y en JavaScript, que tests/probar.py compara byte a byte):

  1. Busca 3A E1 5F CB 4F (CA|C3) 4A 3E. Si está una sola vez y es CA, lo cambia a C3 en una copia.
  2. Pone a cero la zona de configuración (00EEh-0367h del fichero: ajustes y tabla de programas por extensión, desde MOGU hasta justo antes de Drive set, que es lo que cambia CS) y calcula el sha1. Si coincide con el de una base de referencia (con la misma zona a cero), es esa versión tal cual, con los ajustes que tenga el usuario; si coincide con el de una base ya parcheada, ya lleva los nombres largos.
  3. Para una base conocida aplica el .ips a la copia arreglada (el .ips no escribe nada en la zona de configuración, lo comprueba tools/hacer_parche.py), así que lo que cambió CS se conserva, y comprueba el sha1 del resultado (sin la zona de configuración, y entero si el fichero de entrada era exactamente el de referencia).
  4. Con un MM.COM desconocido que tenga CA, solo pone el arreglo y lo guarda como MM_NEXTOR.COM; no lo hemos probado en esas versiones. Con uno desconocido que ya tenga C3, o sin el sitio, lo rechaza.

Qué cambia CS: con la 2.07_A, 59 bytes entre 0108h y 0328h; con la RC5 (CS 3.12), 13 bytes entre 00FDh y 02C8h (medido en openMSX). Nada fuera de 00EEh-0367h.

Otros parches de la comunidad (revisados el 3 de noviembre de 2026): el FAT16 y el del año 2000 ya van dentro de la RC5, así que basta usarla de base. El «copy directories» (Marcos Daniel, 2.07a, sin preguntar al crear carpetas al copiar) solo se distribuye en la lista de correo MSX Global y no publica desplazamientos. Otros parches de FAT16 (los de Okei, MM207-F-FAT16-a) aparecen en los comentarios de MSX.org, donde se dice que no funcionaban en FAT16; no hemos visto ninguna copia. Si alguien aporta un MM.COM con alguno de ellos, se puede añadir como base o como parche opcional del mismo motor.

Todo lo que sigue (direcciones, zonas, pruebas) se escribió y se midió sobre la 2.07_A; la RC5 tiene el mismo código en las mismas direcciones, y lo que cambia se cuenta al final.

Cómo se ve

antes:    ALESTE~1.ROM    FRAY2-~5.ROM    GOLVEL~5.ROM    KING'S~9.ROM    METALG~5.ROM
ahora:    Aleste 1 - E>   Fray 2 - Ver>   Golvellius 3>   King's Valle>   Metal Gear 3>

Limitaciones

Cómo funciona

Al listar un directorio, MM guarda cada entrada en un registro de 32 bytes con el mismo formato que una entrada FAT (5FFFh + 32·n, en el orden del directorio), y no usa los bytes 12-21 (comprobado con puntos de vigilancia en openMSX al listar, ordenar, marcar, árbol, copiar y borrar).

  1. Al arrancar (0100h): el código de la página 3 va en MM.COM detrás de lo de la versión 1. Al cargar cae en 5FBFh+, donde MM pone luego sus marcas y sus registros; el arranque lo copia a CB92h antes de saltar a MM. Si no cabe, deja como en la versión 1 los sitios que llaman a la página 3.
  2. El segmento (586Fh): cuando MM acaba la lista de segmentos que se queda para copiar (C831h, acabada en FFh), se le quita el último. Pedirlo antes no vale: MM hace _FORK al empezar (5783h) y lo pedido antes de eso no se libera con el _JOIN de la vuelta de un programa (se perdía un segmento en cada vuelta). Ahí mismo se hace en el segmento la tabla para convertir los caracteres.
  3. Al listar: 3E4Ah marca la tabla como no válida; 3E88h (de la versión 1) guarda en cada registro la marca A5h y la posición de la entrada que da el FIB de Nextor.
  4. Al acabar el listado (3E82h), la pasada por el directorio, con el segmento en la página 2. Solo en el listado de siempre (el que se llama desde 07ABh, al entrar en una carpeta y al volver a ella): ahí se sabe qué rutina de abort tiene puesta MM. Los otros (como 1AFFh) vuelven a listar luego por 07ABh. La pasada saca primero con _GETCLUS la cadena de clusters (tras cada _RDDRV Nextor vuelve a leer la FAT: así se lee una vez) y lee el directorio con _RDDRV de 8 en 8 sectores, sin pasar de un cluster. El primer cluster de una carpeta es el del registro de .; si el patrón del listado lo ha dejado fuera, el de _FFIRST "."; la raíz, con el _DPARM que hace MM. Junta las entradas LFN de cada 8.3 (comprobando orden y checksum) y la casa por el nombre con el registro que toca, porque los dos van en el mismo orden; si no es ese, mira los 4 siguientes (los que se salta se quedan sin nombre largo). Para cada registro, la tabla guarda el checksum de su 8.3 y el nombre ya como se pinta (hasta 31 caracteres).
  5. La entrada de la tabla va en el propio registro (byte 18, y la marca A5h en el 19): MM mueve los registros enteros al ordenar (las carpetas primero), y al borrar no vuelve a listar; la entrada se mueve con el registro.
  6. Al pintar un elemento de la lista (33BFh, la llamada a 1376h) y en File info (34D5h) se copia la entrada del segmento (se pone en la página 2 solo para eso). Si el checksum no es el del 8.3 del registro (cambiado sin volver a listar), la lista pinta el 8.3 y File info lee el disco como en la versión 1: ese sector y el anterior, juntando las entradas LFN que preceden a la 8.3, o recorriendo el directorio.

Durante la pasada hay una rutina propia de errores de disco (_DEFER) y otra de abort (_DEFAB). El primer error se ignora y la pasada se abandona; si Nextor lo reintenta, sale el diálogo de MM con la página 2 del TPA, y con Retry se vuelve a leer al segmento. Si se aborta (Abort en el diálogo; CTRL+STOP no corta _RDDRV ni _GETCLUS), se reponen la página 2, las dos rutinas de MM y el DTA, y se sigue con la de abort de MM (056Ah). Con la pila en la página 2 (alguna rutina de MM la pone ahí) no se cambia el segmento.

Zona Qué era Qué va
3D07h-3D2Ah, 3D60h-3DDDh, 3DDFh-3E01h el lector de directorios por sectores de MM (solo FAT12), muerto gracias al arreglo de Nextor: 3D5Dh lo salta con un JP 3E4Ah de la versión 1: el gancho del listado, tablas, rutinas pequeñas y las variables de un byte
5CF4h-5FAEh (+ variables hasta 5FBCh) detrás del final de MM.COM, sin usar File info (versión 1); se añade al fichero
5FBFh-600Fh del fichero lo pisan luego las marcas y los registros de MM el arranque
CB92h-D10Fh la pila de MM, que no baja de D3xxh la pasada, la lista y la tabla (se copia del fichero)
un segmento del mapper el último de los que MM se queda para copiar la tabla (8000h, 256 × 32), el nombre que se junta, la conversión de caracteres, los clusters de la carpeta y 8 sectores

No se tocan 3DDEh ni 3E3Eh (MM y MM.EXE los reescriben) ni 3D2Bh-3D5Fh y 3E03h-3E49h (los llaman overlays de MM.EXE). Los sitios desviados:

Dirección Antes Ahora
0100h JP 5CC4h JP start
586Fh LD (HL),FFh / LD A,(F24Fh) CALL takeseg / NOP / NOP
3E4Ah LD HL,5FFFh CALL lstart
3E88h LD DE,C935h JP hookfib
3E82h LD HL,(3E8Ch) JP pass
33BFh CALL 1376h CALL lstname
34C3h CALL 36C4h CALL prep
34D5h CALL 13BAh CALL tname
3547h CALL 35C3h CALL mydate
33D5h LD (1371h),A CALL fldpos (una columna: el campo siguiente al nombre va 39h más a la derecha)
3499h LD HL,1371h CALL fatt (una columna: sin los atributos; solo se llega aquí en esa vista)
3B72h 74h (de LD DE,0174h) 80h: la barra del cursor de una columna, 12 píxeles más ancha

Pruebas (openMSX, Philips NMS 8245 con 4 MB y Sunrise IDE)

Con Nextor 2.1.4 y con Nextor 3.0.0-beta2 (núcleo base de Konamiman con su driver Sunrise IDE para Nextor 3, montado con N80 y mknexrom), en imágenes hechas con MSXsdmaker.py imagen (FAT16 de 256 MB, clusters de 4 KB):

La variante RC5

Multi Mente 2.07A+ RC5 es la compilación de la comunidad que reparte MSX Resource Center (el MM.COM en inglés de la raíz del MMv2.07Aplus-RC5.zip interior; manual «patched FAT16 & Y2K»). Comparada con la 2.07_A:

Pruebas con la RC5 (banco tests/openmsx/probar_mm.py)

Mismo montaje (Philips NMS 8245, 4 MB, Sunrise IDE, imagen FAT16 de 256 MB hecha con MSXsdmaker.py), con la RC5 original y la parcheada y, como referencia, la 2.07_A original y la parcheada, con Nextor 2.1.1 (el kernel que trae openMSX). Con Nextor 2.1.4 se repitió solo la lista y File info de todos los elementos de la RC5 parcheada (sin fallos); con Nextor 3.0 la RC5 no se ha probado. Con los cuatro binarios: