[ad_1]

La realidad virtual ha pasado por varias olas para ser la "próxima gran novedad" que cambiaría para siempre el panorama de los videojuegos. A principios de la década de 1990, el potencial de la realidad virtual había capturado la imaginación del público, con características vívidas en periódicos, revistas, canales de noticias de televisión e incluso grandes películas como Hombre cortadora de césped. Si bien finalmente se lanzaron algunos productos de realidad virtual, muchas otras empresas experimentaron con la tecnología.
Una de esas empresas era Sega, que buscaba crear una solución de realidad virtual asequible como complemento para su consola doméstica, Sega Genesis. A diferencia de las gigantescas máquinas recreativas de realidad virtual que podrían costar bien en el rango de cinco cifras, el producto de realidad virtual para el hogar de Sega ha establecido un precio sugerido de venta al público de solo $ 200. ¿Podría hacerse? Especie de.
Equipado con una unidad de medición inercial de alta frecuencia y pantallas LCD duales, los auriculares Sega VR comparten un gran diseño fundamental con los auriculares VR actuales. Este diseño fue nada menos que innovador cuando Sega presentó oficialmente la unidad a periodistas y minoristas en 1993, prometiendo innovar en la frontera de la realidad virtual. Alcanzaron milagrosamente su objetivo de $ 200 gracias a la tecnología con licencia de una startup llamada Ono-Sendai, cuya solución de seguimiento patentada podría fabricarse por solo $ 1.

La razón oficial de Sega para cancelar sus gafas de realidad virtual era cuestionable: afirmaron que la experiencia era tan realista e inmersiva que presentaba un alto riesgo de lesiones para los jugadores que se movían mientras la usaban. . Sin embargo, un factor probable en la cancelación fueron los comentarios que Sega recibió del Instituto de Investigación de Stanford, que advirtió sobre dolores de cabeza, mareos y enfermedades, especialmente en usuarios jóvenes y niños. En un episodio de Retro Gamer Podcast, el ex CEO de Sega of America, Tom Kalinske, confirmó estos problemas como factores importantes en la decisión de abandonar el proyecto.
Hasta ahora, la mayor parte de lo que sabemos sobre Sega VR proviene de apariciones en ferias comerciales, materiales de marketing, documentos de patentes y testimonios de primera mano. Esto significa que muchos detalles técnicos de la unidad han permanecido especulativos o completamente desconocidos. Sin embargo, cuando miras hacia atrás y estudias material que empujó tantos límites técnicos en su tiempo, ¡estos detalles importan! Ya sea que Sega VR haya logrado o no sus muchos y elevados objetivos, sigue siendo una entrada fascinante y notable en la historia de la realidad virtual.
Para estudiar hardware de esta naturaleza, si no tiene acceso al hardware o los detalles de su implementación, el acceso al software suele ser la mejor solución. El software le dirá exactamente lo que espera del hardware y, dadas esas expectativas, es posible que encuentre que tiene suficiente información para emular el hardware. Como mínimo, tendrá suficiente información para emular una versión del hardware que cumpla con las expectativas del software, ¡y eso es exactamente hacia donde nos dirigimos!
Se estaban desarrollando varios títulos para Sega VR, pero como el material nunca salió, ninguno de ellos ha visto la luz del día, hasta ahora. Gracias a los increíbles esfuerzos de Dylan Mansfield en Gaming Alexandria, uno de ellos fue recogido. Dylan se puso en contacto con Kenneth Hurley, cofundador de Futurescape Productions.
El título de Sega VR en el que trabajó su compañía, Nuclear Rush, es un juego de acción en primera persona que se describe mejor, de la manera más 1993 posible, en la propia introducción del juego:
2032 d.C.
LA ELECTRICIDAD ESTÁ EN DEMANDA,
PERO LOS COMBUSTIBLES FÓSILES SE FUERON.SU MISIÓN: ADQUIRIR COMBUSTIBLE RADIOACTIVO …
POR CUALQUIER MEDIO NECESARIO.
UN INFORMANTE, CONOCIDO ÚNICAMENTE BAJO PLAZO,
INDICA ZONAS SECRETAS LLENAS DE RESIDUOS
DE ANTIGUOS REACTORES.
El juego a veces se ha confundido con Iron Hammer, otro título de Sega VR, posiblemente debido a muchas similitudes visuales y descriptivas. En las pocas breves vistas previas proporcionadas en CES en el verano de 1993, Nuclear Rush también carecía del HUD utilizado en la versión final del juego, contribuyendo a una apariencia más distintiva.

Después de que Dylan se puso en contacto con Hurley y le explicó su interés en Sega VR, Hurley desenterró un CD-ROM con fecha del 6 de agosto de 1994. Afortunadamente, aún intacto después de 26 años, el disco contenía el código fuente completo de Nuclear Rush, así como el código fuente. y las herramientas para algunos de los otros juegos de Sega Genesis en los que Hurley ha trabajado.
Esto nos lleva al inicio de nuestro viaje. Comenzaremos por hacer que Nuclear Rush vuelva a funcionar, y al final habremos resucitado una pieza increíble y nunca antes vista de la historia de Sega, más de 25 años después de que fue abandonada. A lo largo del camino, a veces profundizaremos en los detalles técnicos, así que no dude en usar la tabla a continuación si se encuentra perdido.
Aunque el código fuente de Nuclear Rush estaba completamente presente en el disco de Hurley, no había un binario compilado. En un esfuerzo por encontrar a alguien que pudiera arreglarlo todo, Dylan se acercó a mí. A primera vista, parecía que teníamos prácticamente todo lo que necesitábamos para construir el juego. Todas las dependencias artísticas estaban ahí, y la mayoría de las herramientas estaban presentes, aunque en los datos de otro juego que estaba en el CD-ROM Monster Hunter de Hurley.
La mayor parte del código del juego Nuclear Rush está escrito en C, basándose en el compilador Sierra 68000 C, con código estándar (incluido el controlador de auriculares Sega VR) y algunas otras cosas escritas en ensamblaje. La parte más intensiva en ciclismo del juego, el escalador, también está escrito en C, pero con un giro. El código C genera código M68K nativo a pedido, luego llama al código generado, donde van la mayoría de los ciclos.
Más allá de las herramientas de compilación estándar, el proceso de compilación utiliza algunas herramientas patentadas para ingerir datos artísticos y escupirlos en una forma lista para el juego. CVTSCE.EXE se utiliza para pantallas de fondo / UI estáticas. ANM2FPA.EXE se utiliza para animaciones y sprites preparados a escala con RLE opcional. Finalmente, LZSSC.EXE se utiliza para comprimir la salida de CVTSCE.EXE, aplicando compresión LZSS a la velocidad estándar (desplazamiento de 12 bits, longitud de 4 bits).

En mi primer intento de construir encontré una herramienta que faltaba, DUMP.EXE. Al observar el uso previsto, era obvio que este programa solo estaba abriendo un archivo y emitiendo texto a la salida estándar para cada byte, por lo que el ensamblador podría ingerir el binario. Después de unos preciosos minutos dedicados a escribir código en Borland C ++ 3.0, hice construir un ejecutable de reemplazo, ¡y me fui!
El proceso de construcción se completó con éxito y generó un archivo COFF, con las partes importantes de la ROM divididas en dos secciones. Quería mantener todo el proceso de producción de una imagen ROM ya preparada en el mismo entorno MS-DOS, así que volví brevemente a mi buen amigo Borland y escribí otro programa. para analizar el COFF, generando un binario con las secciones colocadas correctamente y la suma de control en el encabezado de la ROM calculada.
En mi primer intento de ejecutar la ROM en un emulador, fui recibido con una pantalla que me hizo muy feliz:

Por supuesto, no hubo seguimiento de la cabeza. El juego reconoció con éxito este hecho y pasó a la pantalla de título con el soporte para auriculares desactivado. La música del título comenzó a reproducirse y todo parecía ir bien, hasta que hice clic en Inicio y llegué al menú principal. El juego continuó ejecutándose, pero parecía que la paleta utilizada por la fuente del menú acababa de ser sobrescrita. Todavía podía leer el texto, así que intenté cargar en el primer nivel … y fue entonces cuando el contador del programa cayó por un precipicio y todo explotó.
Entonces, como suele ser el caso con estos proyectos, ¡era hora de depurar! Dejé todos los símbolos de depuración del COFF y luego usé las direcciones de los símbolos para colocar algunos puntos de interrupción y ver qué tan lejos estaba yendo en la carga de nivel frontal que las cosas no se vuelvan equivocadas.
Después de algunas pruebas y errores, determiné que el juego había logrado cargarse en el primer nivel e incluso mostrar una imagen o dos en ocasiones y luego el escalador eliminó una mala compensación. ; un objeto, que tuvo muy malas consecuencias en el futuro. Quizás recuerdes que mencioné que tuve que tomar algunas de estas herramientas de datos de otro juego, lo que resultó ser el problema. Las herramientas se cambiaron en algún momento después de Nuclear Rush, y se redujo a este pequeño código en la parte superior del punto de entrada del escalador principal:
wptr ++; / * Ignora el número de sprites en el marco * /
wptr ++; / * Ignorar el desplazamiento del punto de acceso * /
wptr ++;
wptr ++;
Esos últimos 2 incrementos de puntero omiten datos que permanecen completamente sin usar, y parece que en algún momento los datos se eliminaron del ANM2FPA.EXE producción. Dado que estos datos ya no se usaban, la solución fue simple: solo tuve que eliminar esos dos incrementos de puntero adicionales.
Con eso, el nivel se cargó, pero los mosaicos de fondo y algunos de los sprites de HUD todavía estaban revueltos. Estos resultaron ser problemas similares, además de cambios en los formatos de datos compartidos por las herramientas de Monster Hunter. En estos casos, los problemas manifestados fueron un poco menos catastróficos. Entonces, finalmente, con la ROM construida y todos estos problemas resueltos durante un sábado muy ajetreado, ¡logré subir a un nivel y disfrutar de mi primera sesión de Nuclear Rush!

Con el juego en funcionamiento, quería volver atrás y corregir cualquier otro error que hubiera encontrado en el camino. No estaba seguro de cuántos de estos errores eran el resultado del conjunto de herramientas híbridas y cuántos podrían quedar en la versión final del juego. Recuerda que "final" aquí no significa "venta final". retail ”, y aunque el juego estaba lleno, no había apreciado el típico choque de errores que acompaña a un último impulso de control de calidad. De manera especulativa, basado en un puñado de WCES94 con comprobaciones de preprocesador apareciendo en todo el código, Nuclear Rush había planeado otra exhibición en Winter CES 1994. Hasta donde yo sé, el juego nunca apareció en la exhibición, y eso pudo haber jugado un papel en el presagio. del final del proyecto. Al estar bastante lejos de estos eventos, es justo suponer que el CD de Kenneth Hurley del 6 de agosto de 1994 representa una buena mirada final al desarrollo, en algún lugar cerca de la línea de meta, pero no del todo listo para su lanzamiento. comercial.
Dicho esto, pensé que había una buena posibilidad de que el pisoteo generalizado que vi a lo largo del juego estuviera relacionado nuevamente con el kit de herramientas, y eso se metió de nuevo. ; resultó ser un problema interesante. CVTSCE.EXE También se había cambiado en algún momento después de Nuclear Rush, y como habrás notado en la captura de pantalla de uso hace un tiempo, el programa tiene algunas opciones para cambiar la forma en que los datos de la paleta se agrupan en el binario final. Parecía que se habían cambiado algunos de esos argumentos predeterminados, pero había un problema más profundo.
Muchas imágenes de origen basadas en mosaicos son ingeridas por CVTSCE.EXE contienen múltiples paletas, con un número variable de paletas en diferentes desplazamientos base. Por ejemplo, una imagen puede usar la paleta 1 y la paleta 2, mientras que otra solo puede usar la paleta 0, y así sucesivamente. El formato de salida fue diseñado para especificar un índice para la primera paleta en el archivo y el número de paletas. Cuando se carga la imagen, utiliza este índice y recuento para determinar qué paletas existentes pisar y transferir a CRAM. El problema aquí es que ningún valor predeterminado universal para el número de índice / paleta tiene sentido para todas las imágenes en Nuclear Rush, y no he visto ningún dato por archivo que podría ayudar a indicar los valores correctos que se utilizarán además del contenido del mapa de mosaicos en sí.
Esto me llevó a editar CVTSCE.EXE. Agregué una opción para escanear el mapa de mosaicos, determinar qué paletas fueron referenciadas y usar esos datos para determinar el rango de la paleta y cuántas generar. No tengo idea de si esto es lo que la herramienta hizo originalmente para Nuclear Rush, ¡pero pareció funcionar!
Encontré el siguiente problema importante al probar en hardware real. Nuclear Rush combina el desplazamiento horizontal con el desplazamiento vertical basado en tablas, que los modelos posteriores de Genesis pueden manejar sin problemas. Los modelos más antiguos, sin embargo, ocultarán la columna izquierda del plano de fondo. Cuando esto sucede, se ve así:

Nuclear Rush intenta evitar este problema comprobando la versión del hardware (guardar $ A10001), y si la versión es 0, equivale a truncar los bits de desplazamiento horizontal. Esto significa que el fondo solo puede desplazarse una miniatura a la vez, ocultando el problema de eliminación de la columna. El resultado es un desplazamiento horizontal muy grande en lugar de suave, y dado que aparece sin advertencia en algunos modelos de Sega Genesis, esta no es una solución ideal. Sucede que tengo un Model 2 Genesis que informa una versión superior a 0, pero todavía faltan las ediciones posteriores de VDP que solucionaron este problema de desplazamiento. Cuando lancé el juego por primera vez en hardware, fui recibido por esa columna vertical en blanco en el lado izquierdo de la pantalla porque la prueba no agarra mi versión de hardware particular.
Nuclear Rush utiliza la tabla de desplazamiento vertical para lograr un efecto de "balanceo", que se hace visible al girar. El efecto funciona acumulando un pequeño desplazamiento para cada entrada de columna en la tabla de desplazamiento y compensando las posiciones de los sprites aplicando el desplazamiento de la columna en la que se encuentra el objeto:

En lugar de revisar el efecto por completo, instituí una solución simple al exponer una opción en el menú. El primer modo desactiva la tabla de desplazamiento vertical (lo que permite un desplazamiento suave en versiones anteriores de hardware), el segundo modo fuerza el desplazamiento suave (incluso si el hardware no puede admitirlo sin eliminar la columna), el tercer modo El modo fuerza el desplazamiento truncado y el cuarto modo vuelve a comprobar la versión de hardware original. No es del todo un todo y podría ajustarse dado mi caso del Modelo 2, pero está aquí para la posteridad.
Después de eso, continué solucionando problemas y haciendo pequeñas adiciones hasta que estuve satisfecho con el estado del juego. Esto incluyó corregir un error de sincronización DMA y algunas fallas, para hacer que la pantalla de ingreso de contraseña funcione nuevamente y corregir un montón de cosas que solo aparecían cuando el juego se ejecutaba en modo estereoscópico.
¡Finalmente, llegó el momento de trabajar en la emulación de auriculares Sega VR! Esto es lo que realmente me excitaba todo el tiempo. Si solo tuviera una imagen ROM precompilada para trabajar aquí en lugar del código fuente, esto aún habría sido posible. Habría tardado mucho más y habría implicado una gran cantidad de análisis para determinar qué tipo de datos esperaba el juego de los auriculares. Sin embargo, tener el código fuente facilitó mucho las cosas.
El código fuente de Nuclear Rush tiene dos archivos de referencia para la comunicación con los auriculares Sega VR. HELMET.ASME es el código fuente del controlador original proporcionado por Sega of America, y VRDRV.ASM es una versión ligeramente modificada del código utilizado por Nuclear Rush. Las rutinas básicas relacionadas con la reproducción de auriculares son las mismas en ambas copias. La fuente del conductor también se refiere a "VR.DOC / VR.TXT», Que probablemente contendrá información técnica interesante sobre la implementación de los auriculares, pero desafortunadamente no está presente en el repositorio. Si bien hubiera sido bueno tener otra fuente de información, todavía hay información más que suficiente para crear una implementación de auriculares solo a partir del código fuente. .
La reproducción de auriculares se realiza a través de un esquema de multiplexación, al igual que un controlador Sega Genesis normal. De hecho, toda la interacción con los auriculares se produce a través del puerto 2 del controlador, donde el conductor asume que los auriculares están conectados.
La inicialización del auricular del lado del software comienza con un apretón de manos. El software establece los pines TR y TH para escribir a través del registro $ A1,000 billones. A diferencia de un controlador estándar donde solo el pin TH está configurado para escribir, esto nos da dos bits para especificar diferentes tipos de comandos cuando escribimos en el auricular a través del registro. $ A10005. Una entrada de valor de $ 60 (TH + TR) le dice a los auriculares que entren en modo de espera y 40 $ (TH) indica a los auriculares que realicen un reinicio. Mi implementación espera un comando de reinicio y lo usa para iniciar el emulador en el modo Sega VR. Después de un comando inactivo, el software cambia $ 20 (TR) para avanzar los datos que se pueden leer desde $ A10005. El software espera leer inmediatamente $ 70 como respuesta de reconocimiento después de un comando inactivo, verificando que TH, TR y TL están configurados como se esperaba. El acuse de recibo va seguido del identificador del auricular, $ 08.00, cuya segunda mitad está reservada. Si parte de esta transacción no sale según lo planeado, el conductor cancela todo y procedemos en modo "sin auriculares".

Una vez que se completa el apretón de manos inicial, todas las lecturas del auricular se toman en serie para solicitar la orientación actual, el paso y los bits del ojo izquierdo / derecho. El rollo está notablemente ausente, lo que significa que el casco solo se puede utilizar para seguir dos ejes de rotación. No estoy seguro de qué tipo de deriva podríamos haber visto en la IMU o qué tipo de filtro se aplicó antes de acumular movimiento en los ángulos, ya que el casco es responsable de proporcionar ángulos en coordenadas absolutas. . Esto significa que el software simplemente lee el resultado y lo aplica tal cual, sin hacer preguntas. Si bien esto hizo que fuera más difícil saber qué estaba sucediendo solo dentro del hardware basado en software, este detalle de implementación tiene sentido cuando se considera la falta de potencia de procesamiento (y / o hardware especializado) en el Genesis. Estoy especulando, pero es posible que exista hardware dedicado para este propósito fuera del auricular, en algún lugar entre el auricular y el Genesis.
Ahora, necesitaba comprender el formato del flujo de datos posterior a la inicialización del auricular y, afortunadamente, la fuente del controlador del auricular presenta todo muy bien en un comentario:
* xxxx | xxxx | xxxx | L R X8 Y8 | X7 X6 X5 X4 | X3 X2 X1 X0 | Y7 Y6 Y5 Y4 | Y3 Y2 Y1 Y0
* X0-X8 representan valores YAW absolutos de 0 a 360 grados en HEX
* Y0-Y7 representa valores absolutos de PITCH de 0 a +/- 30 grados
* Y8 es la búsqueda del bit de signo Y8 = 0
* mirar hacia abajo Y8 = 1
Esto describe el formato de los datos devueltos por la función de reproducción de los auriculares, pero es 1: 1 con el formato de los datos realmente leídos desde los auriculares. Los x bits son los bits no utilizados en la parte superior del registro de 32 bits que contiene la acumulación de datos de los auriculares leídos cuando regresa la función de lectura.
Eso significa que obtenemos 9 bits para representar 360 grados de guiñada y 9 bits (incluido el signo) para representar 60 grados de altura, con una buena parte del rango potencial sin usar. Los bits "L R" especifican qué ojo espera que se escanee el casco a continuación. En mi implementación, realizo un seguimiento de los ángulos como valores de punto flotante de 32 bits para que puedan permanecer sensibles a la entrada de alta precisión. Cuando envío los ángulos de regreso al Génesis, los pellizco y los cuantifico / codifico como tal:
uint32_t encode_headset_angles (const float * pAngles)
{
// suponga que los ángulos ya se han ajustado
const uint32_t paso = (pAngles (0)> = 0.0f)? (uint8_t) pÁngulos (0): ((uint8_t) -pAngles (0) ^ 0xFF) | (1 << 16);
const uint32_t yaw = (uint32_t) ángulos (1);
sin retorno | ((guiñada y 0xFF) << 8) | ((encaje & 0x100) << 9);
}
La salida de esta función se combina con el estado emulado de los bits del ojo, lo que nos lleva al interesante tema de la temporización de visualización.
Nuclear Rush está diseñado para ejecutarse en modo bloqueado de 15 Hz, lo que significa que el bucle completo del juego debe ejecutarse 15 veces por segundo. Sin embargo, todavía llega a las interrupciones VBlank a 60 Hz. El auricular se lee al final de la interrupción VBlank, pero al comienzo del VBlank leemos los datos del auricular del VBlank anterior para determinar qué ojo configurar (potencialmente iniciar transferencias DMA) para la digitalización. Para agregar al interesante orden de eventos aquí, aunque la fuente del controlador del auricular dice que el auricular admite una operación de 60Hz, Nuclear Rush solo reproduce el auricular al final. todos los otros VBlank.
Cuando su Genesis está conectado a una buena pantalla NTSC antigua, asumiendo que VDP no funciona en modo entrelazado, busca nuevas imágenes a alrededor de 60 Hz. Normalmente eso significa barrer a dos campos entrelazados separados, pero también podríamos interpretar fácilmente la misma señal como imágenes de escaneo progresivo entrelazadas para dos pantallas de ojos separadas, cada una de las cuales se actualiza a 30 Hz. Esperaba que esto fuera lo que harían los auriculares Sega VR, lo que hizo que el La forma en que Nuclear Rush leyó los auriculares y sacudió el metraje un poco extraño.
Ahora, les advertiré de antemano, esto probablemente será difícil de seguir. ¡Pero intentemos! Si saltamos al inicio de un VBlank, la salida del cuadro de Nuclear Rush se puede desglosar de la siguiente manera:
- Entra VBlank.
- Lea los resultados anteriores del casco VBlank. Se establece el bit del ojo izquierdo.
- Configure el siguiente escaneo con la lista de visualización del ojo izquierdo.
- Lea el casco al final de VBlank. Se establece el bit del ojo derecho.
- Busque el ojo izquierdo.
- Entra VBlank.
- Lea los resultados anteriores de los auriculares. Se establece el bit del ojo derecho.
- Configure el siguiente escaneo para el ojo derecho.
- nosotros saltar decía el auricular, estamos en un extraño VBlank.
- Busque el ojo derecho.
- Entra VBlank.
- Lea los resultados anteriores de los auriculares. El ojo derecho es de nuevo juntos. Omitimos la reproducción de auriculares en el último VBlank.
- Configure el siguiente escaneo para el ojo derecho nuevamente.
- Lea el auricular. Se establece el bit del ojo izquierdo.
- Busque el ojo derecho.
- Entra VBlank.
- Lea los resultados anteriores de los auriculares. Se establece el bit del ojo izquierdo.
- Configure el siguiente escaneo para el ojo izquierdo.
- Omita la lectura de auriculares, es extraño VBlank de nuevo.
- Busque el ojo izquierdo.
- Regrese al 1 y observe que todavía estaremos en el ojo izquierdo.
¡Bien! Por lo tanto, en el orden mencionado anteriormente, escaneamos las imágenes en orden "izquierda, derecha, derecha, izquierda" o "izquierda, izquierda, derecha, derecha", según cómo desee superponerlas. Esto se confirma si miramos directamente las imágenes de salida mientras el juego se ejecuta en modo estereoscópico. De izquierda a derecha, partiendo de una imagen por la que pasamos para encontrar el ojo izquierdo, esto es lo que veremos en 4 imágenes secuenciales:

La razón por la que esto me pareció extraño es que esperaría que los auriculares quisieran cambiar la pantalla con cada deslizamiento, y parece poco probable que el hardware esté diseñado de tal manera que limite cada pantalla debe actualizarse solo con una sola imagen a 15 Hz. La alternativa a esta idea es que el auricular cambie su objetivo de visualización solo durante la lectura. Funciona para todos los casos, ya sea que leamos los auriculares al final de cada VBlank o solo al final de cada otro VBlank. El auricular espera ser leído al final de un VBlank y le dice al software qué ojo espera escanear después del próximo VBlank. ¡Al menos esa es mi teoría! He adoptado este enfoque con mi implementación, cambiando el objetivo de pantalla solo cuando se lee el auricular (con un intervalo VBlank mínimo opcional), y parece funcionar bien.
En este punto de la implementación, quería una forma rápida de visualizar la salida estereoscópica del juego, así que implementé un postproceso 3D anaglifo que combina las salidas del ojo izquierdo y derecho después de mapear los colores a la ligereza. Hice cada color de ojos personalizable en la configuración del emulador y lo ajusté ligeramente para las gafas que estaba usando en ese momento. El resultado fue bastante hermoso:

Una vez que comencé a jugar de esta manera, noté algo extraño. Mientras giraba, a veces vi que los ojos no estaban sincronizados, lo que fue particularmente notable en este modo 3D anaglifo:

Inicialmente, pensé que había roto algo en mi extremo y comencé a depurar nuevamente. Todo parecía funcionar, así que implementé una función para tomar cuatro capturas de pantalla secuenciales de un nuevo intercambio a un marco del ojo izquierdo (que también se usó para producir esta serie de tomas antes), y me las arreglé para tomar uno de los fotogramas fuera de sincronización para confirmar lo que pensé que estaba viendo:

Volvemos a mirar las imágenes secuenciales en orden de izquierda, izquierda, derecha, derecha, pero puede ver que la segunda imagen del ojo derecho se inclina hacia adelante. Estaba girando a la izquierda en el casco cuando tomé esta serie, y lo que sucedió aquí es que el juego realmente se adelantó al juego justo en el medio. imágenes para el ojo derecho.
Resulta que nada realmente detiene esto, y puede suceder en cualquier momento, incluso entre los ojos izquierdo y derecho. El juego intenta realizar un bucle y esperar 4 VBlanks al final de cada cuadro para bloquear a 15Hz, pero a veces un error de sincronización lo empujará fuera de ese límite y terminará para configurar el juego. ; siguiente ojo sin sincronizar nunca. a los auriculares. Con toda probabilidad, este comportamiento también estuvo presente en el casco real. Sin embargo, dado que la realidad se basó en gran medida en la persistencia de la visión para compensar las bajas resoluciones, las bajas frecuencias de actualización y las limitaciones de tiempo al presentar la señal activa, mi teoría es que todo ya se estaba arrastrando tan mal que el problema no lo estaba. Nunca se ha notado o nunca se ha visto realmente como un problema.
Terminé implementando un código en el juego real para sincronizarlo con los auriculares al final del ciclo del juego, lo que limpió todo muy bien. Tendría curiosidad si esto cambia la experiencia en un visor de realidad virtual Sega real, o si hay un costo particularmente tremendo para probar el visor al final de cada VBlank (más allá de los ciclos adicionales, Tendremos que pasar dos veces cambiando de ojos (como ocurre a menudo dentro del VBlank), ¡pero tal vez nunca lo sepamos!
Mi emulación de auriculares funcionaba bien en este punto, pero todavía me sentía obligado a intentar confirmar algunas de las suposiciones que había hecho en mi implementación. J'ai décidé de vérifier à nouveau avec Dylan Mansfield pour voir s'il pourrait être en mesure de transmettre quelques questions à Kenneth Hurley pour moi.C'est à ce moment que j'ai découvert que Dylan avait déjà été en contact avec le programmeur principal de Nuclear Rush, Kevin McGrath. Dylan a eu la gentillesse de me présenter Kevin, et Kevin a eu la gentillesse de parler technique avec moi!
Tout de suite, Kevin a pu confirmer que chaque écran du casque était mis à jour à 30 Hz. C'est quelque chose qui m'avait d'abord semblé une évidence. Cependant, avec la façon dont Nuclear Rush scanne les images en double et ne lit le casque que sur tous les autres VBlank, c'était un détail important à confirmer.
Nous avons longuement discuté de l'anatomie d'un cadre Nuclear Rush. La discussion a porté sur la logique VBlank du jeu, l’ordre de lecture, l’ordre de lecture du casque et le problème de désynchronisation des yeux que j’ai rencontré. Kevin n'a pas été en mesure de se souvenir de tous les détails, mais il a trouvé plausible la théorie du «casque ne change que les cibles d'affichage lors de la lecture», et semblait convenir qu'il était plus logique d'expliquer comment le casque faisait face à la ruée vers le nucléaire. ordre des cadres.
En fin de compte, je n’ai pas eu besoin de changer quoi que ce soit dans la mise en œuvre, et Kevin a pu confirmer suffisamment les principes fondamentaux pour que je sois un peu plus confiant dans mes hypothèses de mise en œuvre. Kevin a également fourni de nombreuses informations et informations anecdotiques sur le développement de Nuclear Rush et son expérience avec le prototype de matériel Sega VR.
Un autre point d'intérêt qui est ressorti de cette discussion est que Kevin a passé une grande partie du cycle de développement de Nuclear Rush à travailler sans accès au matériel Sega VR. Avant de recevoir le casque prototype Sega VR, Kevin a même essayé de mettre au point sa propre solution pour simuler un effet de scintillement stéréo en inversant rapidement un signal composite entre les moniteurs.
La difficulté à obtenir du matériel prototype peut avoir été un thème commun parmi les développeurs, étant donné l'expérience de Kevin en conjonction avec un autre compte d'Alex Smith, programmeur principal sur le titre Sega VR Outlaw Racing. En réponse à l’une des questions de Dylan sur le casque, Alex a déclaré qu’il n’avait jamais vu le matériel prototype. Cela semblerait restreindre davantage la liste des jeux qui implémentaient réellement le support de Sega VR, même parmi les jeux développés avec Sega VR à l'esprit. Nous sommes d’autant plus chanceux d’être tombés sur l’un des jeux qui a réussi à implémenter pleinement la prise en charge du casque!
Je courais en 3D anaglyphe et contrôlais les angles du casque avec un stick analogique, et c'était génial. Alors, naturellement, je voulais l'améliorer!
J'ai créé une version spécialement ciblée de Nuclear Rush avec quelques correctifs de synchronisation pour permettre au jeu de fonctionner à 30 Hz lorsqu'il n'est pas en mode stéréoscopique, changé l'échantillonnage du casque pour qu'il se produise sur chaque VBlank et activé le correctif mentionné ci-dessus pour maintenir le jeu synchronisé avec le casque à une fréquence constante de 15 Hz en mode stéréoscopique. Pour compléter cette version, j'ai ajouté une option pour overclocker le M68K dans l'émulateur avec mon implémentation Sega VR. Bien que 30 Hz entraîne une exécution de la logique de jeu réelle deux fois plus souvent qu'elle était initialement prévue, elle se sent toujours plutôt bien! Il est intéressant de penser que nous pourrions peut-être profiter du fait que nous ne sommes plus contraints par 2 Mo de ROM afin de mettre à l'échelle statiquement plus de données de sprite, et associés à quelques optimisations bien ciblées, nous ne le serons peut-être pas. loin de permettre au jeu de bien fonctionner sur du matériel normal.
Avec le jeu prêt à fonctionner dans un environnement de réalité virtuelle légèrement plus exigeant (où un manque de synchronisation oculaire pourrait augmenter la tendance à perdre le déjeuner), il était temps de recentrer l'attention sur la recréation de l'expérience Sega VR originale. La prochaine étape serait d'ajouter la prise en charge des casques VR modernes à l'émulateur.

Équipé d'un HTC Vive Cosmos (qui était heureusement à peine préparé à assumer la puissance impressionnante de Sega VR), j'ai commencé à écrire le support OpenVR dans l'émulateur.
L'objectif principal ici était de prendre la sortie stéréoscopique de l'émulateur et de la transmettre directement au casque réel. Cela semblait être assez simple, mais ce n’était pas un cas d’utilisation tout à fait courant, il y avait donc quelques considérations spéciales. J'ai dû prendre soin de baser ma projection orthographique sur la projection «brute» fournie par la bibliothèque, afin de tenir compte de la variation œil / lentille. J'ai également dû convaincre la bibliothèque que je n'avais vraiment besoin d'aucun type de lissage ou d'extrapolation de mouvement, ce qui signifiait prendre soin de mettre à jour le casque à l'intervalle souhaité tout en maintenant la sortie Genesis verrouillée à 60 Hz.
Une fois que les problèmes de synchronisation d'OpenVR ont été réglés, j'ai eu d'autres problèmes de synchronisation Sega VR à résoudre. Il ne semble pas que le casque Sega VR ait tenté de synchroniser les affichages oculaires. Pour que Nuclear Rush fonctionne correctement sans aucune modification de la ROM, j'ai dû modéliser ce comportement, j'ai donc ajouté une option à l'émulateur appelée dgen_openvr_eyes_sync. Si vous activez cette option et essayez de jouer à la version de Nuclear Rush sans mon correctif de synchronisation, vous vous retrouverez assez souvent louche. This is because, as discussed earlier, there’s really nothing preventing the eyes from becoming desynchronized on the game side. In order to cope like a real Sega VR headset, I update each eye buffer just as soon as it gets scanned out. When both eyes are fed to the real headset at once, they won’t necessarily be from the same game frame, and you’ll get the occasional flicker that you’d probably get on a real headset.
If you turn the sync option on and play with the sync fixed build of the game, on the other hand, everything works fine!
Aspect ratio and perspective were another couple of significant issues to deal with. By default, I’m crunching the image in each eye to adjust for the Genesis aspect ratio, but settings are exposed so that you can disable that or change it to whatever relative aspect you’d like.

Since I don’t have exact physical specifications for the screens or lenses in the Sega VR headset, I can only guess at effective field of view, distortion, and so on. I found that when I corrected for aspect ratio and just plastered the images up on each eye, it was fairly disorienting. I could see myself eventually going crazy and implementing a bunch of different perspective filters, but as a simple first step, I added an option called dgen_openvr_imgpscale which can be used to change the size of the image in eye projection space. After that, I decided to add customizable lens geometry. Using a Noesis script, you can export from most common model formats to a custom lens format, which is then used by the emulator to render each image in eye projection space. The above image is a fisheye test, showing the source model for the lens as well.
This approach allows us to mathematically generate any lens shape we’d like without having to consider the computational cost of the model, or literally just eyeball it and rely on interpolation to fill in the gaps. In addition to the custom lenses, bilinear filtering can be enabled with the option dgen_openvr_bilinear. Although I’m not usually a fan of scaling with bilinear filtering in emulators, it can help reduce the sense of disorientation in this case.
So, here we are! We’ve got a real VR headset driving our Sega VR emulation, and a whole bunch of tools in place for fine-tuning. It may not be exact, but here it is: The Sega VR experience!
VR at 15Hz ended up being a lot more playable than I’d expected, and the lack of roll wasn’t too jarring either. I expect the experience won’t sit so well with everyone, but I’ve had a good time with it! We’re probably benefitting a lot from low latency head tracking here as well, even with the software’s limited sampling rate.
There are a lot of fun next steps that could be taken from here. I like the idea of piggybacking on the existing Sega VR protocol to add support for room-scale tracking, or creating an interface to emulate the headset on real hardware. There’s also plenty of room for best-guess attempts at approximating more aspects of the real experience, for better or for worse, with different perspective and motion filters.
I’ve put two repositories up on GitHub for this project, where you’ll find both source code and binaries.
First, the emulator where I’ve implemented Sega VR support.
Repository
Download (Windows)
Second, Nuclear Rush in buildable form with source code and all of the necessary tools.
Repository
Download (pre-built ROM images)
Nuclear Rush is ready to be played in most emulators or on real hardware, but you’ll have to use the emulator provided for a real Sega VR experience. The emulator is also stuffed full of options that it’s managed to pick up from some of my other projects, so take a look through the configuration file if you’re feeling adventurous. You might also have to make some changes in the configuration to get your input device of choice to map to the headset angles. If you’re going for the real VR experience with a headset of your own, there are more than a few options to adjust on that side of things too. In case you find that you feel disoriented or have a hard time tracking movement with the default settings, one of the first things to try is reducing the value for int_openvr_imgpscale until you feel more comfortable.
If you spot any mistakes, either in the code or in the article here, feel free to contact me. This project had a lot of moving parts, so I might have overlooked a few things.
Also of note, in the Nuclear Rush repository, you’ll find plenty of art and other resources which aren’t actually used in the game, including some interesting HUD designs. Have fun exploring!
You wouldn’t be reading this right now if Dylan Mansfield hadn’t taken that first step in contacting a Sega VR developer. Indeed, Nuclear Rush and the additional insight it’s given us into Sega VR may have been lost entirely if Kenneth Hurley hadn’t thought to store backups of his early work, or if he hadn’t been so generous in granting us access to the Nuclear Rush source code. We owe a great deal of thanks to Dylan Mansfield (and by extension, Gaming Alexandria) and Kenneth Hurley for their roles in helping us to preserve this important piece of video game history.
I also want to personally thank Kevin McGrath for working through my huge walls of technical questions and providing some very thoughtful replies. Thanks, Kevin! Special thanks should also be given to Sega Retro. Nearly every time I went looking for a good link to provide further reading on a topic broached by this article, there was already a Sega Retro article to fit the bill. They’re doing great work over there.
Nuclear Rush is another excellent example of the importance of source code (and data) preservation. The game’s repository as a whole tells an even deeper story about the game’s development under some rather unique circumstances. The source code, through comments and structure which would be lost in compiled binary form, provides even greater insight into both the game and the Sega VR hardware. Nuclear Rush has given us the unique ability to recreate key parts of a hardware-based experience, over one quarter of a century after the hardware was last seen in public. That’s pretty amazing.
As we enjoy all of the new material and knowledge stemming from this project, we should remember that all of it may have been lost if human circumstance had been just a little bit different, or if Kenneth Hurley’s CD-ROM had become a corroded chunk of unreadable sectors over the course of 26 years. Safely preserving source code like this requires a lot of care and dedication, and right now, it’s still way too easy for important pieces of video game history to fall through the cracks. But for every Nuclear Rush that we do manage to preserve, the future will thank us!

[ad_2]
Be the first to comment