'******************************************************************************
'* 
'* INIT OF NES (Video game console by Nintendo, 1985-199x)
'*
'* Note: - This script always executed while emulation starting and then 
'*         "used" by other emulation scripts (to provide access to CPU etc.)
'*
'******************************************************************************

? "[INIT] Started emulation of NES"

'Processor
public use object CPU_M6502 as CPU 'processor m6502
cpu.Name="m6502/nes" : cpu.CoreID=1 'NES-specific CPU core implementation

'--------------------------- NES Memory Stuff ---------------------------------

//Check ROM
public dim nes_Cartridge as object=emuDrives.ROM(0)
if not nes_Cartridge.Ready then ErrorMsg("Can not start without ROM image in slot!")
nes_Cartridge.pos=0 : nes_Cartridge.Latched=true
if (nes_Cartridge.Size<16) or (nes_Cartridge.Dword<>0x1A53454E) then
    ErrorMsg("Incorrect or unsupported ROM format!") : end if

//Memory areas with decoded cartridge data
public dim nes_ROMStart as dword 'first Kb index of ROM in memory space
public dim nes_ROMSize as dword 'count of ROM kilobytes
public dim nes_RAMStart as dword 'first Kb index of RAM in memory space
public dim nes_RAMSize as dword 'count of RAM kilobytes
public dim nes_VROMStart as dword 'first Kb index of VROM in memory space
public dim nes_VROMSize as dword 'count of ROM kilobytes
public dim nes_VRAMStart as dword 'first Kb index of VRAM in memory space
public dim nes_VRAMSize as dword 'count of RAM kilobytes
public dim nes_SPRTABStart as dword 'first Kb index of Sprite RAM in memory space

//Decoded cartridge settings
public dim nes_Mapper as byte=0 'kind of memory mapper
public dim nes_VertMirror as boolean=false 'vert. mirroring (instead of horiz.)
public dim nes_HasSRAM as boolean=false 'SRAM at $6000..$7000
public dim nes_HasTrainer as boolean=false 'trainer at $7000..$71FF
public dim nes_4xScreenVRAM as boolean=false 'four-screen VRAM mode
public dim nes_VSSystem as boolean=false 'VS-System cartridge
public dim nes_PALMode as boolean=false 'PAL cartridge (instead of NTSC)

//Load ROM
dim b as byte
nes_ROMSize=nes_Cartridge.Byte*16 'count of 16Kb ROM banks
nes_VROMSize=nes_Cartridge.Byte*8 'count of 8KB VROM banks
b=nes_Cartridge.Byte : nes_VertMirror=(b and 1)<>0 : nes_HasSRAM=(b and 2)<>0
nes_HasTrainer=(b and 4)<>0 : nes_4xScreenVRAM=(b and 8)<>0 
nes_Mapper=shr(b,4) 'low bits of mapper index
b=nes_Cartridge.Byte : nes_VSSystem=(b and 1)<>0
nes_Mapper=nes_Mapper or (b and 0xF0) 'high bits of mapper index
b=nes_Cartridge.Byte : if b=0 then b=1 : nes_RAMSize=b*8 'count of 8KB RAM banks
b=nes_Cartridge.Byte : nes_PALMode=(b and 1)<>0
nes_Cartridge.pos=nes_Cartridge.pos+6 'skip reserved bytes

//Check correctness and compatibility with emulator
if nes_HasTrainer then
   ErrorMsg("ROMs with trainer unsupported currently!") : end if
if nes_Cartridge.Size<>(16+nes_ROMSize*1024+nes_VROMSize*1024) then
   ErrorMsg("Incorrect or unsupported ROM format!") : end if

//Video memory size + additional 1Kb to implement Sprites Table (first 256 Kb)
nes_VRAMSize=16+1 'Kb 

//All memory 
mem.Size=(64+nes_ROMSize+nes_RAMSize+nes_VROMSize+nes_VRAMSize)*1024 'bytes
mem.Limit=0xFFFF '64 Kb of memory available to CPU

//ROM memory area
nes_ROMStart=64 : mem.Pos=nes_ROMStart*1024 
mem.Copy(nes_Cartridge.Object,nes_ROMSize*1024) 'load ROM banks

//VROM memory area
nes_VROMStart=nes_ROMStart+nes_ROMSize : mem.Pos=nes_VROMStart*1024 
mem.Copy(nes_Cartridge.Object,nes_VROMSize*1024) 'load VROM banks

//RAM memory area
nes_RAMStart=nes_VROMStart+nes_VROMSize 

//VRAM memory area
nes_VRAMStart=nes_RAMStart+nes_RAMSize 

//Sprite memory area
nes_SPRTABStart=nes_VRAMStart+nes_VRAMSize-1

//Show info to console
? "[NES] Cartridge: ";nes_Cartridge.FileName
? "[NES] Mapper: ";nes_Mapper
? "[NES] ROM Banks:  ";shr(nes_ROMSize,4);" x 16Kb"
? "[NES] VROM Banks: ";shr(nes_VROMSize,3);" x 8Kb"
? "[NES] RAM Banks:  ";shr(nes_RAMSize,3);" x 8Kb"
? "[NES] SRAM Enabled: ";nes_HasSRAM
? "[NES] VertNameTabMirror: ";nes_VertMirror
? "[NES] 4XScreenNameTab: ";nes_4xScreenVRAM

//Set CPU frequency by videomode
if nes_PALMode then 
  cpu.Frequency= 1773447 '1,77Mhz (PAL)
else
 cpu.Frequency=1789772 '1,79Mhz (NTSC)
end

//Mask drive as detected and accessed
nes_Cartridge.Detected=true : nes_Cartridge.Accessed=true

'------------------------------- Assembling -----------------------------------

//WARNING: Need to be after ROM decoding, because MB uses decoding results
public use object "mboard" as MB : pc.AddDevice(MB) 'motherboard
