Although I have made much progress it still is not completed; once it is the full source-codes will be release by public-domain. Please you can write on here whatever comment/question/answers/complaints/etc.
The mapper in use is User:Zzo38/Mapper I; an implementation for Nintendulator (in C, not C++) is listed below. This implemention tries to emulate bus conflicts too, although I do not recommend their use. It does not attempt to consider race conditions; you should still try to avoid race conditions in a program that uses it though.
I fixed interface.h to add the following codes immediately after the pragmas:
Here is the implementation in Nintendulator:
I will also show you a few of the macros right now (maybe you can learn the working of macros in Unofficial-MagicKit then):
If you have other questions about Famizork II, please write it on here
The mapper in use is User:Zzo38/Mapper I; an implementation for Nintendulator (in C, not C++) is listed below. This implemention tries to emulate bus conflicts too, although I do not recommend their use. It does not attempt to consider race conditions; you should still try to avoid race conditions in a program that uses it though.
I fixed interface.h to add the following codes immediately after the pragmas:
Code:
#ifndef __cplusplus
typedef struct EmulatorInterface EmulatorInterface;
typedef struct MapperInfo MapperInfo;
typedef struct ROMInfo ROMInfo;
typedef struct DLLInfo DLLInfo;
typedef enum COMPAT_TYPE COMPAT_TYPE;
typedef enum RESET_TYPE RESET_TYPE;
typedef enum STATE_TYPE STATE_TYPE;
typedef enum CFG_TYPE CFG_TYPE;
typedef enum ROM_TYPE ROM_TYPE;
#endif
Maybe you should also include it into the official file too. It can then allow mapper plugins written in C rather than only C++ mapper plugins.typedef struct EmulatorInterface EmulatorInterface;
typedef struct MapperInfo MapperInfo;
typedef struct ROMInfo ROMInfo;
typedef struct DLLInfo DLLInfo;
typedef enum COMPAT_TYPE COMPAT_TYPE;
typedef enum RESET_TYPE RESET_TYPE;
typedef enum STATE_TYPE STATE_TYPE;
typedef enum CFG_TYPE CFG_TYPE;
typedef enum ROM_TYPE ROM_TYPE;
#endif
Here is the implementation in Nintendulator:
Code:
/*
Nintendulator mapper interface for Famizork II
This program is in the public domain.
*/
#include <stdlib.h>
#include "interface.h"
HWND hWnd;
HINSTANCE hInstance;
const EmulatorInterface*EMU;
const ROMInfo*ROM;
static uint16 MapperNum=380;
static uint32 story_rom_mask;
static uint32 story_ram_mask;
static uint16 story_addr;
static uint8*story_ram[64];
static uint8*story_rom[64];
static FCPURead orig_read1;
static FCPURead orig_read3;
static FCPURead orig_read5;
static FCPUWrite orig_write1;
static FCPUWrite orig_write3;
static FCPUWrite orig_write5;
static int MAPINT Read(int Bank,int Addr) {
int v=255;
switch(Bank) {
case 1: v=orig_read1(Bank,Addr); break;
case 3: v=orig_read3(Bank,Addr); break;
}
if(Addr&2048) {
if(Addr&4) {
v&=story_rom[((story_addr|(Addr<<16))&story_rom_mask)>>12][story_addr&story_rom_mask&0xFFF];
} else {
v&=story_ram[((story_addr|(Addr<<16))&story_ram_mask)>>12][story_addr&story_ram_mask&0xFFF];
}
}
if(Addr&16) story_addr=(story_addr&0xFF00)|(v&255);
if(Addr&32) story_addr=(story_addr&0x00FF)|((v&255)<<8);
return v;
}
static void MAPINT Write(int Bank,int Addr,int Val) {
int v=Val&255;
if(Addr&2048) {
if(Addr&4) {
v&=story_rom[((story_addr|(Addr<<16))&story_rom_mask)>>12][story_addr&story_rom_mask&0xFFF];
} else {
story_ram[((story_addr|(Addr<<16))&story_ram_mask)>>12][story_addr&story_ram_mask&0xFFF]=v;
}
}
if(Addr&16) story_addr=(story_addr&0xFF00)|(v&255);
if(Addr&32) story_addr=(story_addr&0x00FF)|((v&255)<<8);
switch(Bank) {
case 1: orig_write1(Bank,Addr,v); break;
case 3: orig_write3(Bank,Addr,v); break;
}
}
static int MAPINT SaveLoad(STATE_TYPE mode,int offset,unsigned char*data) {
SAVELOAD_WORD(mode,offset,data,story_addr);
return offset;
}
static BOOL MAPINT Load(void) {
return TRUE;
}
static void MAPINT Reset(RESET_TYPE typ) {
int i;
if(ROM->INES_Flags&1) EMU->Mirror_V(); else EMU->Mirror_H();
switch(ROM->INES_PRGSize) {
case 1: // 8K story + 8K interpreter
story_rom_mask=0x1FFF;
EMU->SetPRG_ROM8(0x8,1);
EMU->SetPRG_ROM8(0xA,1);
EMU->SetPRG_ROM8(0xC,1);
EMU->SetPRG_ROM8(0xE,1);
break;
case 2: // 16K story + 16K interpreter
story_rom_mask=0x3FFF;
EMU->SetPRG_ROM8(0x8,2);
EMU->SetPRG_ROM8(0xA,3);
EMU->SetPRG_ROM8(0xC,2);
EMU->SetPRG_ROM8(0xE,3);
break;
case 3: // 16K story + 32K interpreter
story_rom_mask=0x3FFF;
EMU->SetPRG_ROM8(0x8,2);
EMU->SetPRG_ROM8(0xA,3);
EMU->SetPRG_ROM8(0xC,4);
EMU->SetPRG_ROM8(0xE,5);
break;
case 4: // 32K story + 32K interpreter
story_rom_mask=0x7FFF;
EMU->SetPRG_ROM8(0x8,4);
EMU->SetPRG_ROM8(0xA,5);
EMU->SetPRG_ROM8(0xC,6);
EMU->SetPRG_ROM8(0xE,7);
break;
case 5: // 64K story + 16K interpreter
story_rom_mask=0xFFFF;
EMU->SetPRG_ROM8(0x8,8);
EMU->SetPRG_ROM8(0xA,9);
EMU->SetPRG_ROM8(0xC,8);
EMU->SetPRG_ROM8(0xE,9);
break;
case 6: // 64K story + 32K interpreter
story_rom_mask=0xFFFF;
EMU->SetPRG_ROM8(0x8,8);
EMU->SetPRG_ROM8(0xA,9);
EMU->SetPRG_ROM8(0xC,10);
EMU->SetPRG_ROM8(0xE,11);
break;
case 9: // 128K story + 16K interpreter
story_rom_mask=0x1FFFF;
EMU->SetPRG_ROM8(0x8,16);
EMU->SetPRG_ROM8(0xA,17);
EMU->SetPRG_ROM8(0xC,16);
EMU->SetPRG_ROM8(0xE,17);
break;
case 10: // 128K story + 32K interpreter
story_rom_mask=0x1FFFF;
EMU->SetPRG_ROM8(0x8,16);
EMU->SetPRG_ROM8(0xA,17);
EMU->SetPRG_ROM8(0xC,18);
EMU->SetPRG_ROM8(0xE,19);
break;
case 17: // 256K story + 16K interpreter
story_rom_mask=0x3FFFF;
EMU->SetPRG_ROM8(0x8,32);
EMU->SetPRG_ROM8(0xA,33);
EMU->SetPRG_ROM8(0xC,32);
EMU->SetPRG_ROM8(0xE,33);
break;
case 18: // 256K story + 32K interpreter
story_rom_mask=0x3FFFF;
EMU->SetPRG_ROM8(0x8,32);
EMU->SetPRG_ROM8(0xA,33);
EMU->SetPRG_ROM8(0xC,34);
EMU->SetPRG_ROM8(0xE,35);
break;
}
if(ROM->INES_CHRSize) EMU->SetCHR_ROM8(0,0);
story_ram_mask=(64<<((ROM->INES2_PRGRAM|(ROM->INES2_PRGRAM>>4))&15))-1;
if(ROM->INES_Flags&2) EMU->Set_SRAMSize(64<<(ROM->INES2_PRGRAM>>4));
EMU->SetPRG_ROM4(6,story_rom_mask>>12);
for(i=0;i<64;i++) {
EMU->SetPRG_ROM4(6,i&(story_rom_mask>>12));
story_rom[i]=EMU->GetPRG_Ptr4(6);
}
EMU->SetPRG_RAM4(6,story_ram_mask>>12);
for(i=0;i<64;i++) {
EMU->SetPRG_RAM4(6,i&(story_ram_mask>>12));
story_ram[i]=EMU->GetPRG_Ptr4(6);
}
EMU->SetPRG_OB4(6);
orig_read1=EMU->GetCPUReadHandler(1);
orig_read3=EMU->GetCPUReadHandler(3);
orig_read5=EMU->GetCPUReadHandler(5);
orig_write1=EMU->GetCPUWriteHandler(1);
orig_write3=EMU->GetCPUWriteHandler(3);
orig_write5=EMU->GetCPUWriteHandler(5);
EMU->SetCPUReadHandler(1,Read);
EMU->SetCPUReadHandler(3,Read);
EMU->SetCPUReadHandler(5,Read);
EMU->SetCPUReadHandler(7,Read);
EMU->SetCPUWriteHandler(1,Write);
EMU->SetCPUWriteHandler(3,Write);
EMU->SetCPUWriteHandler(5,Write);
EMU->SetCPUWriteHandler(7,Write);
}
static const MapperInfo the_mapper={
.MapperId=&MapperNum,
.Description=_T("Famizork II"),
.Compatibility=COMPAT_FULL,
.Load=Load,
.Reset=Reset,
.SaveLoad=SaveLoad,
};
static void MAPINT UnloadMapper(void) {
ROM=0;
}
static const MapperInfo*MAPINT LoadMapper (const ROMInfo*_ROM) {
ROM=_ROM;
if(ROM->ROMType!=ROM_INES || ROM->INES_MapperNum!=MapperNum) {
UnloadMapper();
return 0;
}
return &the_mapper;
}
DLLInfo DLL_Info={
_T("famizorkii_mapper.dll by zzo38"),
0x20150303,
0x00010000,
LoadMapper,
UnloadMapper
};
__declspec(dllexport) void MAPINT UnloadMapperDLL (void) {
EMU = NULL;
hWnd = NULL;
}
__declspec(dllexport) DLLInfo*MAPINT LoadMapperDLL (HWND hWndEmu, const EmulatorInterface *_EMU, int VersionRequired) {
hWnd = hWndEmu;
EMU = _EMU;
if(VersionRequired != CurrentMapperInterface) {
UnloadMapperDLL();
return NULL;
}
return &DLL_Info;
}
BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
hInstance = hinstDLL;
return TRUE;
}
Note: I compile using GNU C on MinGW, not using Microsoft. (I didn't get any compiler errors/warnings.)Nintendulator mapper interface for Famizork II
This program is in the public domain.
*/
#include <stdlib.h>
#include "interface.h"
HWND hWnd;
HINSTANCE hInstance;
const EmulatorInterface*EMU;
const ROMInfo*ROM;
static uint16 MapperNum=380;
static uint32 story_rom_mask;
static uint32 story_ram_mask;
static uint16 story_addr;
static uint8*story_ram[64];
static uint8*story_rom[64];
static FCPURead orig_read1;
static FCPURead orig_read3;
static FCPURead orig_read5;
static FCPUWrite orig_write1;
static FCPUWrite orig_write3;
static FCPUWrite orig_write5;
static int MAPINT Read(int Bank,int Addr) {
int v=255;
switch(Bank) {
case 1: v=orig_read1(Bank,Addr); break;
case 3: v=orig_read3(Bank,Addr); break;
}
if(Addr&2048) {
if(Addr&4) {
v&=story_rom[((story_addr|(Addr<<16))&story_rom_mask)>>12][story_addr&story_rom_mask&0xFFF];
} else {
v&=story_ram[((story_addr|(Addr<<16))&story_ram_mask)>>12][story_addr&story_ram_mask&0xFFF];
}
}
if(Addr&16) story_addr=(story_addr&0xFF00)|(v&255);
if(Addr&32) story_addr=(story_addr&0x00FF)|((v&255)<<8);
return v;
}
static void MAPINT Write(int Bank,int Addr,int Val) {
int v=Val&255;
if(Addr&2048) {
if(Addr&4) {
v&=story_rom[((story_addr|(Addr<<16))&story_rom_mask)>>12][story_addr&story_rom_mask&0xFFF];
} else {
story_ram[((story_addr|(Addr<<16))&story_ram_mask)>>12][story_addr&story_ram_mask&0xFFF]=v;
}
}
if(Addr&16) story_addr=(story_addr&0xFF00)|(v&255);
if(Addr&32) story_addr=(story_addr&0x00FF)|((v&255)<<8);
switch(Bank) {
case 1: orig_write1(Bank,Addr,v); break;
case 3: orig_write3(Bank,Addr,v); break;
}
}
static int MAPINT SaveLoad(STATE_TYPE mode,int offset,unsigned char*data) {
SAVELOAD_WORD(mode,offset,data,story_addr);
return offset;
}
static BOOL MAPINT Load(void) {
return TRUE;
}
static void MAPINT Reset(RESET_TYPE typ) {
int i;
if(ROM->INES_Flags&1) EMU->Mirror_V(); else EMU->Mirror_H();
switch(ROM->INES_PRGSize) {
case 1: // 8K story + 8K interpreter
story_rom_mask=0x1FFF;
EMU->SetPRG_ROM8(0x8,1);
EMU->SetPRG_ROM8(0xA,1);
EMU->SetPRG_ROM8(0xC,1);
EMU->SetPRG_ROM8(0xE,1);
break;
case 2: // 16K story + 16K interpreter
story_rom_mask=0x3FFF;
EMU->SetPRG_ROM8(0x8,2);
EMU->SetPRG_ROM8(0xA,3);
EMU->SetPRG_ROM8(0xC,2);
EMU->SetPRG_ROM8(0xE,3);
break;
case 3: // 16K story + 32K interpreter
story_rom_mask=0x3FFF;
EMU->SetPRG_ROM8(0x8,2);
EMU->SetPRG_ROM8(0xA,3);
EMU->SetPRG_ROM8(0xC,4);
EMU->SetPRG_ROM8(0xE,5);
break;
case 4: // 32K story + 32K interpreter
story_rom_mask=0x7FFF;
EMU->SetPRG_ROM8(0x8,4);
EMU->SetPRG_ROM8(0xA,5);
EMU->SetPRG_ROM8(0xC,6);
EMU->SetPRG_ROM8(0xE,7);
break;
case 5: // 64K story + 16K interpreter
story_rom_mask=0xFFFF;
EMU->SetPRG_ROM8(0x8,8);
EMU->SetPRG_ROM8(0xA,9);
EMU->SetPRG_ROM8(0xC,8);
EMU->SetPRG_ROM8(0xE,9);
break;
case 6: // 64K story + 32K interpreter
story_rom_mask=0xFFFF;
EMU->SetPRG_ROM8(0x8,8);
EMU->SetPRG_ROM8(0xA,9);
EMU->SetPRG_ROM8(0xC,10);
EMU->SetPRG_ROM8(0xE,11);
break;
case 9: // 128K story + 16K interpreter
story_rom_mask=0x1FFFF;
EMU->SetPRG_ROM8(0x8,16);
EMU->SetPRG_ROM8(0xA,17);
EMU->SetPRG_ROM8(0xC,16);
EMU->SetPRG_ROM8(0xE,17);
break;
case 10: // 128K story + 32K interpreter
story_rom_mask=0x1FFFF;
EMU->SetPRG_ROM8(0x8,16);
EMU->SetPRG_ROM8(0xA,17);
EMU->SetPRG_ROM8(0xC,18);
EMU->SetPRG_ROM8(0xE,19);
break;
case 17: // 256K story + 16K interpreter
story_rom_mask=0x3FFFF;
EMU->SetPRG_ROM8(0x8,32);
EMU->SetPRG_ROM8(0xA,33);
EMU->SetPRG_ROM8(0xC,32);
EMU->SetPRG_ROM8(0xE,33);
break;
case 18: // 256K story + 32K interpreter
story_rom_mask=0x3FFFF;
EMU->SetPRG_ROM8(0x8,32);
EMU->SetPRG_ROM8(0xA,33);
EMU->SetPRG_ROM8(0xC,34);
EMU->SetPRG_ROM8(0xE,35);
break;
}
if(ROM->INES_CHRSize) EMU->SetCHR_ROM8(0,0);
story_ram_mask=(64<<((ROM->INES2_PRGRAM|(ROM->INES2_PRGRAM>>4))&15))-1;
if(ROM->INES_Flags&2) EMU->Set_SRAMSize(64<<(ROM->INES2_PRGRAM>>4));
EMU->SetPRG_ROM4(6,story_rom_mask>>12);
for(i=0;i<64;i++) {
EMU->SetPRG_ROM4(6,i&(story_rom_mask>>12));
story_rom[i]=EMU->GetPRG_Ptr4(6);
}
EMU->SetPRG_RAM4(6,story_ram_mask>>12);
for(i=0;i<64;i++) {
EMU->SetPRG_RAM4(6,i&(story_ram_mask>>12));
story_ram[i]=EMU->GetPRG_Ptr4(6);
}
EMU->SetPRG_OB4(6);
orig_read1=EMU->GetCPUReadHandler(1);
orig_read3=EMU->GetCPUReadHandler(3);
orig_read5=EMU->GetCPUReadHandler(5);
orig_write1=EMU->GetCPUWriteHandler(1);
orig_write3=EMU->GetCPUWriteHandler(3);
orig_write5=EMU->GetCPUWriteHandler(5);
EMU->SetCPUReadHandler(1,Read);
EMU->SetCPUReadHandler(3,Read);
EMU->SetCPUReadHandler(5,Read);
EMU->SetCPUReadHandler(7,Read);
EMU->SetCPUWriteHandler(1,Write);
EMU->SetCPUWriteHandler(3,Write);
EMU->SetCPUWriteHandler(5,Write);
EMU->SetCPUWriteHandler(7,Write);
}
static const MapperInfo the_mapper={
.MapperId=&MapperNum,
.Description=_T("Famizork II"),
.Compatibility=COMPAT_FULL,
.Load=Load,
.Reset=Reset,
.SaveLoad=SaveLoad,
};
static void MAPINT UnloadMapper(void) {
ROM=0;
}
static const MapperInfo*MAPINT LoadMapper (const ROMInfo*_ROM) {
ROM=_ROM;
if(ROM->ROMType!=ROM_INES || ROM->INES_MapperNum!=MapperNum) {
UnloadMapper();
return 0;
}
return &the_mapper;
}
DLLInfo DLL_Info={
_T("famizorkii_mapper.dll by zzo38"),
0x20150303,
0x00010000,
LoadMapper,
UnloadMapper
};
__declspec(dllexport) void MAPINT UnloadMapperDLL (void) {
EMU = NULL;
hWnd = NULL;
}
__declspec(dllexport) DLLInfo*MAPINT LoadMapperDLL (HWND hWndEmu, const EmulatorInterface *_EMU, int VersionRequired) {
hWnd = hWndEmu;
EMU = _EMU;
if(VersionRequired != CurrentMapperInterface) {
UnloadMapperDLL();
return NULL;
}
return &DLL_Info;
}
BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
hInstance = hinstDLL;
return TRUE;
}
I will also show you a few of the macros right now (maybe you can learn the working of macros in Unofficial-MagicKit then):
Code:
; Z-character-decoding assigning macro
macro def_zchars
if \#=1
macset 2,4,\1
else
macset 2,4,\2
endif
macset 1,4,\1
macset 3,4,*
macset 4,4,?B
bank bank(zchad)
macgoto def_zchars_0
endm
macro def_zchars_0
macset 5,4,\1=\2
org zchad+\1
db low(\3-1)
if \3<$FE01
fail "Z-character routine out of range"
endif
if \3>$FF00
fail "Z-character routine out of range"
endif
macset 1,4,\1+1
macgoto def_zchars_\5
endm
macro def_zchars_1
bank \4
org \3
endm
; Instruction assigning macro
macro def_inst
macset 2,4,*
macset 3,4,?B
bank bank(instadl)
org instadl+(\1)
db low(\2-1)
org instadh+(\1)
db high(\2-1)
bank \3
org \2
endm
macro def_inst_2op
def_inst (\1)+$00
def_inst (\1)+$20
def_inst (\1)+$40
def_inst (\1)+$60
def_inst (\1)+$C0
endm
macro def_inst_2op_eq
def_inst (\1)+$00
def_inst (\1)+$20
def_inst (\1)+$40
def_inst (\1)+$60
endm
macro def_inst_1op
def_inst (\1)+$00
def_inst (\1)+$10
def_inst (\1)+$20
endm
macro def_inst_0op
def_inst (\1)+$00
endm
macro def_inst_ext
def_inst (\1)+$00
endm
macro def_zchars
if \#=1
macset 2,4,\1
else
macset 2,4,\2
endif
macset 1,4,\1
macset 3,4,*
macset 4,4,?B
bank bank(zchad)
macgoto def_zchars_0
endm
macro def_zchars_0
macset 5,4,\1=\2
org zchad+\1
db low(\3-1)
if \3<$FE01
fail "Z-character routine out of range"
endif
if \3>$FF00
fail "Z-character routine out of range"
endif
macset 1,4,\1+1
macgoto def_zchars_\5
endm
macro def_zchars_1
bank \4
org \3
endm
; Instruction assigning macro
macro def_inst
macset 2,4,*
macset 3,4,?B
bank bank(instadl)
org instadl+(\1)
db low(\2-1)
org instadh+(\1)
db high(\2-1)
bank \3
org \2
endm
macro def_inst_2op
def_inst (\1)+$00
def_inst (\1)+$20
def_inst (\1)+$40
def_inst (\1)+$60
def_inst (\1)+$C0
endm
macro def_inst_2op_eq
def_inst (\1)+$00
def_inst (\1)+$20
def_inst (\1)+$40
def_inst (\1)+$60
endm
macro def_inst_1op
def_inst (\1)+$00
def_inst (\1)+$10
def_inst (\1)+$20
endm
macro def_inst_0op
def_inst (\1)+$00
endm
macro def_inst_ext
def_inst (\1)+$00
endm
If you have other questions about Famizork II, please write it on here