Firstly everyone can Thank SailorSat, she has done all the magic here really!! and I couldn't do any of it without her knowledge
Ill post 2 different lua files for using with TS2 etc
This one will get VR lights working with TS2 with no cheats
daytona.luaROM = "daytona"
require("model2"); -- Import model2 machine globals
function Init()
Patch_SpecialInputs();
Patch_LampOutputs();
os.execute ("tsstub.exe "..ROM)
end
function Patch_SpecialInputs()
-- first, disable old read
Romset_PatchDWord(0, 0x1E504, 0x5CA01E00); -- MOV g4,0x00 (NOOP?)
-- now jump to our patched read
Romset_PatchDWord(0, 0x1E508, 0x090219F8); -- CALL 0x0003FF00
-- read io port
Romset_PatchDWord(0, 0x3FF00, 0x80A03000);
Romset_PatchDWord(0, 0x3FF04, 0x01C00012); -- LDOB g4,0x01C00012
-- read patched mask
Romset_PatchDWord(0, 0x3FF08, 0x80B83000);
Romset_PatchDWord(0, 0x3FF0C, 0x00500820); -- LDOB g7,0x00500820
-- and em
Romset_PatchDWord(0, 0x3FF10, 0x58A50097); -- AND g4,g4,g7
-- restore old mask
Romset_PatchDWord(0, 0x3FF14, 0x8CB800FF); -- LDA g7,0xff
-- return
Romset_PatchDWord(0, 0x3FF18, 0x0A000000); -- RET
end
function Patch_LampOutputs()
-- reroute 0x01C0001E to 0x00500824
for offset = 0x00000000, 0x0003FFFF, 4 do
if Romset_ReadDWord(0, offset) == 0x01C0001E then
Romset_PatchDWord(0, offset, 0x00500824);
local opcode = offset - 1;
if Romset_ReadByte(0, opcode) == 0x80 then
Romset_PatchByte(0, opcode, 0x90) -- replace LDOB with LD
end
if Romset_ReadByte(0, opcode) == 0x82 then
Romset_PatchByte(0, opcode, 0x92) -- replace STOB with ST
end
end
end
end
function PostDraw()
if I960_ReadByte(RAMBASE + 0x00000820) == 0x00 then
I960_WriteByte(RAMBASE + 0x00000820, 0xFF);
end
-- 0xFF = normal
-- 0xFD = force beginner
-- 0xFB = force advanced
-- 0xF9 = force expert
-- 0xF7 = emergency/remote start
-- 0x7F = ex.start; as long as hold down, the track selection stays on (even after the 15 second countdown)
-- 0x3E = DIK_F4
-- 0x3F = DIK_F5
local data = 0xFF;
data = XOR(SHL(Input_IsKeyPressed(0x3E), 0x07), data); -- F4 for ex.start
data = XOR(SHL(Input_IsKeyPressed(0x3F), 0x03), data); -- F5 for emergency/remote start
I960_WriteByte(RAMBASE + 0x00000820, data);
Video_DrawText(0,0,HEX8(I960_ReadByte(0x00500824)),0xFFFFFF);
end
This one will get VR lights working with TS2 with cheats. I added time cheat, 99,180,255 max laps (will not change the visible out of lap icon eg 8,80 or whatever. Will simply say 99/8 then tick over to 00/8 once you hit 100 or 200 etc). Just modify the script if you don't want to change lap numbers
daytona.luaROM = "daytona"
require("model2"); -- Import model2 machine globals
function Init()
Patch_SpecialInputs();
Patch_LampOutputs();
os.execute ("tsstub.exe "..ROM)
end
function Patch_SpecialInputs()
-- first, disable old read
Romset_PatchDWord(0, 0x1E504, 0x5CA01E00); -- MOV g4,0x00 (NOOP?)
-- now jump to our patched read
Romset_PatchDWord(0, 0x1E508, 0x090219F8); -- CALL 0x0003FF00
-- read io port
Romset_PatchDWord(0, 0x3FF00, 0x80A03000);
Romset_PatchDWord(0, 0x3FF04, 0x01C00012); -- LDOB g4,0x01C00012
-- read patched mask
Romset_PatchDWord(0, 0x3FF08, 0x80B83000);
Romset_PatchDWord(0, 0x3FF0C, 0x00500820); -- LDOB g7,0x00500820
-- and em
Romset_PatchDWord(0, 0x3FF10, 0x58A50097); -- AND g4,g4,g7
-- restore old mask
Romset_PatchDWord(0, 0x3FF14, 0x8CB800FF); -- LDA g7,0xff
-- return
Romset_PatchDWord(0, 0x3FF18, 0x0A000000); -- RET
end
function Patch_LampOutputs()
-- reroute 0x01C0001E to 0x00500824
for offset = 0x00000000, 0x0003FFFF, 4 do
if Romset_ReadDWord(0, offset) == 0x01C0001E then
Romset_PatchDWord(0, offset, 0x00500824);
local opcode = offset - 1;
if Romset_ReadByte(0, opcode) == 0x80 then
Romset_PatchByte(0, opcode, 0x90) -- replace LDOB with LD
end
if Romset_ReadByte(0, opcode) == 0x82 then
Romset_PatchByte(0, opcode, 0x92) -- replace STOB with ST
end
end
end
end
function PostDraw()
if I960_ReadByte(RAMBASE + 0x00000820) == 0x00 then
I960_WriteByte(RAMBASE + 0x00000820, 0xFF);
end
-- 0xFF = normal
-- 0xFD = force beginner
-- 0xFB = force advanced
-- 0xF9 = force expert
-- 0xF7 = emergency/remote start
-- 0x7F = ex.start; as long as hold down, the track selection stays on (even after the 15 second countdown)
-- 0x3E = DIK_F4
-- 0x3F = DIK_F5
local data = 0xFF;
data = XOR(SHL(Input_IsKeyPressed(0x3E), 0x07), data); -- F4 for ex.start
data = XOR(SHL(Input_IsKeyPressed(0x3F), 0x03), data); -- F5 for emergency/remote start
I960_WriteByte(RAMBASE + 0x00000820, data);
end
function Frame()
local gameState = I960_ReadByte(0x5010A4)
if gameState==0x16 -- Ingame
or gameState==0x03 -- Attract ini
or gameState==0x04 -- Attract Higscore ini
or gameState==0x05 -- Attract Highscore
or gameState==0x06 -- Attract VR Ini
or gameState==0x07 -- Attract VR
then
Model2_SetStretchBLow(1) -- Stretch the bg tilemap (sky & clouds) when widescreen
Model2_SetWideScreen(1)
else -- No widescreen on the rest of the screens
Model2_SetStretchBLow(0)
Model2_SetWideScreen(0)
end
end
--Some sample code follows to show how to draw strings and setup options/cheats
--
--function PostDraw()
-- Video_DrawText(20,10,HEX32(I960_GetRamPtr(RAMBASE)),0xFFFFFF);
-- Video_DrawText(20,10,HEX32(I960_ReadWord(RAMBASE+0x10D0)),0xFFFFFF);
-- Video_DrawText(20,20,HEX32(RAMBASE),0xFFFFFF);
-- Video_DrawText(20,30,Options.cheat1.value,0xFFFFFF);
-- Video_DrawText(20,40,Input_IsKeyPressed(0x1E),0xFFFFFF);
--end
--
--function cheat1func(value)
--
--end
--
--function cheat1change(value)
--
--end
--
--
--function cheat2func(value)
--
--end
--
--function cheat2change(value)
--
--end
--
--
function lapcheatfunc2(value)
I960_WriteWord(RAMBASE+0x10EC,99);
end
function lapcheatfunc1(value)
I960_WriteWord(RAMBASE+0x10EC,180);
end
function lapcheatfunc(value)
I960_WriteWord(RAMBASE+0x10EC,255);
end
function timecheatfunc(value)
I960_WriteWord(RAMBASE+0x10D0,50*64); --50 seconds always
end
Options =
{
-- cheat4={name="Cheat 4",values={"Off","On"},runfunc=cheat4func,changefunc=cheat4change},
lapcheat4={name="99 Laps",values={"Off","On"},runfunc=lapcheatfunc2},
-- cheat3={name="Cheat 3",values={"Off","On"},runfunc=cheat3func,changefunc=cheat3change},
lapcheat1={name="180 Laps",values={"Off","On"},runfunc=lapcheatfunc1},
-- cheat2={name="Cheat 2",values={"Off","On"},runfunc=cheat2func,changefunc=cheat2change},
lapcheat={name="255 Laps",values={"Off","On"},runfunc=lapcheatfunc},
-- cheat1={name="Cheat 1",values={"Off","On"},runfunc=cheat1func,changefunc=cheat1change},
timecheat={name="Infinite Time",values={"Off","On"},runfunc=timecheatfunc}
}
This is the ini file to go into memcfg folder of TS2
daytona.ini[Info]
Name=Daytona USA
WinCaption=Daytona USA
WinClass=MYWIN
ExeName=
ExePath=
LaunchGame=0
Enable=1
ExitMode=1
[Inputs]
[Outputs]
Enable=1
EmuName=Model2
NumberOutputs=9
Output1PTR=&H1AA888|&H100|&H824
Output1Type=byte
Output1BitMask=&h1
Output1Name=Coin Chute 1
Output2PTR=&H1AA888|&H100|&H824
Output2Type=byte
Output2BitMask=&h2
Output2Name=Coin Chute 2
Output3PTR=&H1AA888|&H100|&H824
Output3Type=byte
Output3BitMask=&h4
Output3Name=Start_Lamp
Output4PTR=&H1AA888|&H100|&H824
Output4Type=byte
Output4BitMask=&h8
Output4Name=View1_Lamp
Output5PTR=&H1AA888|&H100|&H824
Output5Type=byte
Output5BitMask=&h10
Output5Name=View2_Lamp
Output6PTR=&H1AA888|&H100|&H824
Output6Type=byte
Output6BitMask=&h20
Output6Name=View3_Lamp
Output7PTR=&H1AA888|&H100|&H824
Output7Type=byte
Output7BitMask=&h40
Output7Name=View4_Lamp
Output8PTR=&H1AA888|&H100|&H824
Output8Type=byte
Output8BitMask=&h80
Output8Name=Leader_Lamp
Output9PTR=&H1AA888|&H100|&H52D8
Output9Type=integer
Output9Name=RPM
oh and to get the network multiplayer going with AI positions is a little funky as It cannot be done before a race starts (goes back to test menu immediately if too soon) so I was hoping to add it as a cheat or similar to launch once im in a race but I need it to do a few things in a row as like a macro. I currently use cheat engine to do it
Step 1 - launch network multiplayer as per normal and start a race
Step 2 - RAMBASE+4008 needs to be locked on all slave machines. Doesn't matter for Master it seems
Step 3 - RAMBASE+5484,RAMBASE+5784,RAMBASE+5A84,RAMBASE+5D84,RAMBASE+6084,RAMBASE+6384,RAMBASE+6684 needs to be locked too if you are playing 8 player to stop nodes from resetting (car 2-8 nodes)
Step 4 - RAMBASE+4000 needs to be changed to 99 (network will lose sync with each other)
Step 5 - RAMBASE+10A4 needs to be changed to 13 (restart entrance to race with 40 positions)
Step 6 - RAMBASE+4000 needs to be changed to 01 (network will re-sync)
Pretty sure master actually doesnt need the nodes stuff to be locked, and i think technically only slave 2 needs car 2 node locked, only slave 3 needs car 3 node locked etc but its properly easier just to lock all 7 across all machines if thats possible like it is in cheat engine. Anyway its a bit clunky over cheat engine so id love to make a quick cheat or something to do all this quickly but it works well once its done.
Ive only tested up to 3 players so far and it worked well, 3 started in position 38/40,39/40 and 40/40 and changed if we passed each other and dropped down as we passed AI cars (i got down to 16/40 after a few mins)
here is a horrible video of me doing it while holding my phone and trying to use cheat engine 1 handed between mouse/keyboard lol across both networked "machines" then driving a little on keyboard