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. 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):
3A E1 5F CB 4F (CA|C3) 4A 3E. Si está una sola vez y es CA, lo cambia a C3 en una copia.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..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).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.
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>
SHIFT+1) el hueco es de 31
caracteres, como File info (si pasa de 31, 20 + ... + 8, para que se vea la extensión), y no se pintan los
atributos (los da File info) para hacer sitio: la fila acaba 6 píxeles más a la derecha (nombre, tamaño, fecha y hora).
Los que no tienen nombre largo salen en 8.3, como siempre.Wild: (31 caracteres) y tapa la
fecha de ese fichero; Size: y Time: siguen en la fila de abajo. Si pasa de 31: los
20 primeros, ... y los 8 últimos (para que se vea la extensión):
Nombre_muy_largo_de_...s_xx.dsk.(JP), [a]…); File info enseña el nombre entero. El color por
extensión sigue saliendo del 8.3, y ordenar ordena por el 8.3 (los ~1, ~2 no
siguen el orden de los nombres largos). Sin ordenar se ve el orden del directorio: el
alfabético de los nombres largos en las tarjetas de MSX SD Maker; en una copia hecha desde
Windows, el orden en que se copió.Música española ñ
→ Musica espanola n), porque la fuente de MM es la de la BIOS (japonesa en muchas
máquinas). Lo demás (japonés, símbolos) sale como ?. Lo que busca por nombre sigue
usando el 8.3._RDDRV, _GETCLUS y lo que guarda el FIB de
Nextor). Con otro DOS, o si algo falla, se ve el 8.3. Solo FAT16 y FAT12: Nextor no lee
FAT32.CB92h-D10Fh (MM usa hasta CB91h y deja el
resto para la pila). Si la cima del TPA está por debajo de D411h, el parche se queda
como en la versión 1: nombre largo solo en File info. Con Nextor 2.1.4 la cima es D806h
y con Nextor 3.0 D706h (NMS 8245 en openMSX)._RDDRV hace que Nextor vacíe e invalide sus búferes de esa unidad (es como está
hecho Nextor); no se pierde nada, solo que el siguiente acceso al disco los vuelve a leer.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).
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.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.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.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).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.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 |
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):
a.txt en minúsculas (8.3 con los bits de NT, sin
nombre largo), Telnet.com, carpetas con y sin nombre largo;*.TXT, puesto en memoria), entrar y salir de
carpetas y volver de un programa cuatro veces seguidas (el segmento se libera y se vuelve
a coger el mismo);CB92h-D0EAh (antes de la vista de una columna): no escribe nadie más que el parche (y Nextor
en el búfer de _GETCLUS); la pila no baja de D3EAh (Nextor 3, File info leyendo
el disco) ni, con la tabla, de D6E5h (Nextor 3) y D7D8h (Nextor 2.1.4).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:
3E4Ah, 3E88h, 3E82h, 33BFh, 34C3h, 34D5h, 3547h, 586Fh) son
idénticos a los de la 2.07_A, y las rutinas de MM que llama el parche (1376h, 13BAh, 15A8h, 164Eh, 36C4h,
35C3h, 56E2h…) están en el mismo sitio.2.07A+,
diálogos), tablas de configuración y asociaciones del principio del fichero, el arreglo del reloj (año 2000: la
rutina que pinta las cifras de 0D8Ah y un envoltorio en 5CF0h que llama a 15A8h), el arranque (se quita la
comprobación de turbo R de 5CC4h y el byte que ponía en 0722h queda fijo; 0100h salta directo a 5783h) y una
protección de FAT16 (wr[Y]ting se ignora en FAT16; el manual dice que no se use Sort ni el Filer en FAT16). El
arreglo de Nextor (3D5Dh: C3 en vez de CA, ver «El arreglo de Nextor») lo llevan las dos versiones, así que no
es eso lo que distingue a la RC5.5CC4h y esa rutina acaba en JP 5783h; en la RC5 0100h ya salta a
5783h. MMSTART vale 5783h (RC5 equ 1, que parchear.py escribe en variante.inc).5D00h (la 2.07_A en 5CF3h) y el código de File info (699 bytes) ya no
cabe antes de 5FBFh con sus 14 bytes de variables. En la RC5 el código va desde 5D00h y las variables van en el
relleno de 1Ah que deja la RC5 en 5CC4h-5CCDh y 5CEAh-5CEDh; ninguna instrucción referencia esas direcciones
(comprobado buscando xx 5C tras un código de operación de salto, carga o llamada). 5CD0h-5CDBh (el despachador
de FAT16, al que solo se llega desde 3D60h), 5CE0h-5CE9h y 5CF0h-5CFFh (el arreglo del reloj, que sí se
ejecuta) no se tocan: en el .ips no hay ni un byte entre 5CC0h y 5CFFh.3D60h. La RC5 puso ahí un JP 5CD0h, justo en el código muerto de MM que este parche sobrescribe
(3D60h-3DDDh). Nadie salta a 3D60h ni a 5CD0h (ni en MM.COM ni en MM.EXE) y 3D5Dh sigue siendo un JP 3E4Ah
incondicional: queda sin ejecutarse, como en la 2.07_A. Se comprobó también en ejecución (ver más abajo).MM_LFN_RC5.ips pesa 2.492 bytes (MM_LFN.ips, 2.505).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:
--escenario lista, 12 elementos; con --info-todos, todos): en la RC5 parcheada salen los
mismos nombres que en la 2.07_A parcheada, y los ficheros con solo 8.3 salen como siempre. La cabecera sigue diciendo
MM v2.07A+ y el reloj marca bien el año.--escenario interaccion, 42 capturas por pasada, 10 comprobaciones mecánicas, 0 fallos en los
cuatro): ordenar por nombre ascendente y descendente (carpetas primero; cada hueco sigue siendo de su fichero:
comprobado por el tamaño de File info en 8 posiciones), marcar 3 ficheros y desmarcarlos, entrar en una carpeta con
nombre largo y volver, volver 4 veces de [X]ecom (ver, un HOLA.COM, dir, HOLA.COM; la lista se repinta
idéntica byte a byte en VRAM), borrar, copiar (lo copiado sale con el 8.3, como avisa el LEEME) y salir.CS MM (CS 3.11 con la 2.07_A, CS 3.12 con la RC5; el MM parcheado tiene 25.726 bytes): CS termina bien
(complete), no cambia el tamaño ni trunca, y solo toca el bloque de configuración del principio (59 bytes entre
0108h y 0328h en la 2.07_A; 13 bytes entre 00FDh y 02C8h en la RC5), nada del código del parche. Después MM
arranca y sigue enseñando nombres largos, con los mismos hashes de VRAM que sin CS. En este entorno CS no lanza MM
al acabar (vuelve al prompt), también con el original.--contar-ejecucion "3D60-3DDD 5CD0-5CFF", un punto de ruptura en cada instrucción, con los
originales sin parche, durante el escenario entero): en 3D60h-3DDDh el código de MM.COM no se ejecuta ni una vez ni
en la 2.07_A ni en la RC5, ni tampoco 5CD0h. Los aciertos que salen en esas direcciones (2 a 4 en 3D60h, 123 a 145
en 3DCDh) son del COMMAND2.COM que [X]ecom carga en el TPA, y del dir de DOS al salir de MM. Cuidado: el resto
de 5CD0h-5CFFh no está muerto (en la 2.07_A, 5CD1h-5CEBh corre una vez por cada vuelta de [X]ecom; en la RC5,
5CF0h-5CFFh lee el reloj sin parar), pero ahí el parche no escribe nada.MM.COM con la configuración cambiada con CS (el de una tarjeta real: 2.07_A con OPFXSD en la tabla de programas,
8 bytes distintos de la referencia en 0328h), parcheado con aplicar.py y puesto en su propia carpeta MM (con su
MM.EXE, MM.TBL, etc.), con Nextor 2.1.4: escenario interaccion completo, 10 comprobaciones, 0 fallos. La tabla del
usuario sale intacta en el fichero parcheado.SHIFT+1, nombre de 31 y sin atributos): lista de 28 elementos con nombres de hasta 53 caracteres
(cada uno con su tamaño, fecha y hora, y la barra del cursor cubre toda la fila), las dos páginas, marcar, entrar en una
carpeta con nombre largo y volver, volver de un programa de [X]ecom, y los cambios de vista a 3 y 5 columnas (12
caracteres, sin cambios). Con la 2.07_A (la tarjeta de un usuario) y con la RC5, Nextor 2.1.4; el escenario interaccion
completo vuelve a dar 10 de 10 en las dos con el parche nuevo. Con SHIFT+2 el banco no consigue cambiar de vista (no se
ha probado la de 2 columnas).Unrecognized command.
Dos diferencias entre versiones que no son del parche: al volver de un programa el cursor se queda donde estaba en la
2.07_A y vuelve a ..\ en la RC5, que además repinta más despacio (pausas de 7-8 s emulados al borrar o copiar).