Unos meses atras, me hice con una TV TFT 640x480, con entrada VGA, y llevaba algun tiempo con ganas de ponerla en onda para emulacion. Lo bueno de esta TV es que soporta entre 50 y 85khz, y acepta resoluciones de hasta 1920x1080, siempre escalando a 640x480 obviamente
Ayer me puse con el emu de x68000, y me decante al final por el winx68k, ya que los otros emus, especialmente el mas moderno XM6 typeG, no son buenos para baja resolucion
El problema del winx68k, es que es una puta mierda para usarlo en frontends, no tiene ninguna manera de arrancar a pantalla completa, y todo se maneja desde el menu, con dialogos de windows comunes, vamos, un horror
El otro horror, son las resoluciones... madre de dios!! es que es malo con ganas en este aspecto. Si se usa en CRT a 15khz no es problema, ya que puede emitir resolucion nativa por medio de un parche
Pero en TFT es horrorosamente limitado, pero lo que no quita, que con algo de ingenio, se pueda solucionar todo esto
Lo primero de todo fue solucionar el tema de las resoluciones. El emulador tiene estas opciones de video
1 - Escala todo a 800x600

este es el modo mas comun. Horror absoluto a menos q tengan un TFT 800x600
2 - En modo flip trata de sacar ressoluciones aproximadas (por ejemplo 384x256>400x300). Falla mucho
3 - En modo Wide, trata de escalar en enteros (Da preferencia a la resolucion vertical)
Asi que me enfoque en lo que me parecio mas razonable, el modo wide
Por ejemplo, el castlevania, tiene una resolucion real de 256x256, asi que para que en modo wide, pueda mostrarlo correctamente, la resolucion tiene que ser multiplo.... 512x512, 768x512, 1024x512, 1024x768, 1280x1024....
Como mi monitor es 640x480, juegos con una resolucion de 256px de alto, no seran posibles de mostrar completos a 2x, se perderan 16pixeles, 256 vs 240... el problema era COMO engañar al winx68k para escalar en enteros, aun sin tener suficiente pantalla....
Se me ocurrio la idea de crear resoluciones virtuales, multiplos del juego a probar. Asi que por ejemplo, cree una resolucion virtual de 1280x960 a 55.45hz, dentro de un marco 1280x1024
El emulador detecta 1280x1024, no 1280x960, y escala el juego a esta resolucion. Luego simplemente centro la imagen, y listo


Se aprecia el escalado correcto en las lineas del equalizador



Bueno, segui con el final fight, que este juego tiene modo 15khz, y efectivamente, escalado perfecto, algo muy facil de ver en los scanlines



Bueno, ya contento con el acabado grafico, descubri algo MUY UTIL, y es que el emulador, cuando graba un savestate, no solo graba eso, no....
El jodido emulador, graba TODO EL JUEGO en el savestate, si todo, ademas LA CONFIGURACION tambien, o sea, que no es necesario "introducir" los floppy manualmente, simplemente grabamos un savestate, y al cargarlo, ya esta todo listo para jugar!
Esto es alucinante! por ejemplo, arranco el Final Fight, me voy al menu, configuro el MT-32, configuro los controles, salgo al menu principal, guardo un state, y ya esta... siempre comenzare ahi, con todo listo... vamos, MEJOR IMPOSIBLE
Esto me llevo a un ultimo problemilla... y un verdadero dolor de cabeza... la incapacidad del emulador para tomar lineas de comando o guardar cosas tan utiles como fullscreen en el INI
Problemas que tenia a resolver
1 - El emulador no cambia la resolucion, usa la del escritorio en modo wide
2 - El emulador no va a fullscreen automaticamente
3 - Para cargar savestates, es necesario ir al menu, load state, y cargarlo manualmente
4 - Para cargar/salvar partidas hay que ir al menu... un coñazo desde frontend
Bueno, pensando que hacer, al final solucione el problema haciendo un script de AutoHotKey
Este script, automaticamente al ser ejecutado, pone la pantalla en negro, de fondo abre el Winx68k, carga un savestate, cambia la resolucion de pantalla, y pone el emulador a pantalla completa
Ademas, asigno las teclas F5 y F8 para salvar/cargar partida de forma transparente
O sea, desde el doble click al icono, o desde el frontend, hasta estar dentro del juego, son dos segundos de pantalla negra... y nada mas
Un exe por cada juego, y listo. Como el catalogo de x68k es reducido, es una solucion ideal, especialmente para frontends
Que lo disfruten, cada uno q lo adapte a su PC
DetectHiddenWindows, On
SetTitleMatchMode, 2
Gui, Color, Black
Gui, +ToolWindow -Caption +AlwaysOnTop
Gui, show, x0 y0 w%A_ScreenWidth% h%A_ScreenHeight%, NA
Run, WinX68kHighSpeed_eng.exe,,Hide
sleep 500
WinActivate, WinX68
sleep 200
SendInput {F11}{s}{l}
sleep 100
loop, {
IfWinExist Load
{
WinMove, Load, , 2500, 500
Break
}
sleep 1
}
sleep 500
SendInput {Raw}Ffight.x68
sleep 100
SendInput {Enter}
sleep 200
ChangeDisplaySettings( (ClrDep:=32) , (Wid:=1280) , (Hei:=1024) , (Hz:=55) )
sleep 200
CoordMode, mouse, screen
MouseMove 0,984
BlockInput, MouseMove
sleep 500
SendInput {F11}{d}{f}
loop, {
IfWinNotExist WinX68
{
BlockInput, MouseMoveOff
exitapp
}
if(GetKeyState("F5","P"))
{
SendInput {F11}{s}{s}
sleep 800
SendInput {Raw}Ffight-1.x68
sleep 100
SendInput {Enter}
}
if(GetKeyState("F8","P"))
{
SendInput {F11}{s}{l}
sleep 800
SendInput {Raw}Ffight-1.x68
sleep 100
SendInput {Enter}
}
if(GetKeyState("F10","P"))
{
SendInput {F11}{s}{q}
BlockInput, MouseMoveOff
ChangeDisplaySettings( (ClrDep:=32) , (Wid:=640) , (Hei:=480) , (Hz:=60) )
exitapp
}
sleep 50
}
ChangeDisplaySettings( cD, sW, sH, rR ) {
VarSetCapacity(dM,156,0), NumPut(156,2,&dM,36)
DllCall( "EnumDisplaySettings", UInt,0, UInt,-1, UInt,&dM ), NumPut(0x5c0000,dM,40)
NumPut(cD,dM,104), NumPut(sW,dM,108), NumPut(sH,dM,112), NumPut(rR,dM,120)
Return DllCall( "ChangeDisplaySettings", UInt,&dM, UInt,0 )
}
DetectHiddenWindows, On
SetTitleMatchMode, 2
Gui, Color, Black
Gui, +ToolWindow -Caption +AlwaysOnTop
Gui, show, x0 y0 w%A_ScreenWidth% h%A_ScreenHeight%, NA
Run, WinX68kHighSpeed_eng.exe,,Hide
sleep 500
WinActivate, WinX68
sleep 200
SendInput {F11}{s}{l}
sleep 100
loop, {
IfWinExist Load
{
WinMove, Load, , 2500, 500
Break
}
sleep 1
}
sleep 500
SendInput {Raw}Ffight.x68
sleep 100
SendInput {Enter}
sleep 200
ChangeDisplaySettings( (ClrDep:=32) , (Wid:=1280) , (Hei:=1024) , (Hz:=55) )
sleep 200
CoordMode, mouse, screen
MouseMove 0,984
BlockInput, MouseMove
sleep 500
SendInput {F11}{d}{f}
loop, {
IfWinNotExist WinX68
{
BlockInput, MouseMoveOff
exitapp
}
if(GetKeyState("F5","P"))
{
SendInput {F11}{s}{s}
sleep 800
SendInput {Raw}Ffight-1.x68
sleep 100
SendInput {Enter}
}
if(GetKeyState("F8","P"))
{
SendInput {F11}{s}{l}
sleep 800
SendInput {Raw}Ffight-1.x68
sleep 100
SendInput {Enter}
}
if(GetKeyState("F10","P"))
{
SendInput {F11}{s}{q}
BlockInput, MouseMoveOff
ChangeDisplaySettings( (ClrDep:=32) , (Wid:=640) , (Hei:=480) , (Hz:=60) )
exitapp
}
sleep 50
}
ChangeDisplaySettings( cD, sW, sH, rR ) {
VarSetCapacity(dM,156,0), NumPut(156,2,&dM,36)
DllCall( "EnumDisplaySettings", UInt,0, UInt,-1, UInt,&dM ), NumPut(0x5c0000,dM,40)
NumPut(cD,dM,104), NumPut(sW,dM,108), NumPut(sH,dM,112), NumPut(rR,dM,120)
Return DllCall( "ChangeDisplaySettings", UInt,&dM, UInt,0 )
}
Moraleja del asunto? el winx68k no solo sirve para CRT, es posible usarlo en TFT y no morir en el intento, solo toca meterle algo de imaginacion