Add rom mappers to NES target

This commit is contained in:
drmortalwombat 2023-03-11 11:01:11 +01:00
parent 868564ff08
commit aed086bdb9
16 changed files with 600 additions and 89 deletions

View File

@ -104,7 +104,11 @@ A list of source files can be provided.
* pet: Commodore PET, 8K RAM (0x0400..0x2000)
* pet16 : Commodore PET, 16K RAM (0x0400..0x4000)
* pet32 : Commodore PET, 32K RAM (0x0400..0x8000)
* nes : Nintendo entertainment system, NROM 32 K ROM
* nes : Nintendo entertainment system, NROM 32 K ROM, no mirror
* nes_nrom_h : Nintendo entertainment system, NROM 32 K ROM, h mirror
* nes_nrom_v : Nintendo entertainment system, NROM 32 K ROM, v mirror
* nes_mmc1 : Nintendo entertainment system, MMC1, 256K PROM, 128K CROM
* nes_mmc3 : Nintendo entertainment system, MMC3, 512K PROM, 256K CROM
* atari : Atari 8bit systems, (0x2000..0xbc00)
### Files generated
@ -482,6 +486,50 @@ The overlay file can then be loaded in memory during program execution:
krnio_setnam(P"OVL1");
krnio_load(1, 8, 1);
#### NES ROM Banks
With NROM mappers, the prg and chr code is put into cartridge bank zero.
#pragma section( tiles, 0 )
#pragma region( tbank, 0x0000, 0x2000, , 0, { tiles } )
#pragma data(tiles)
__export char tiles[] = {
#embed "nesmini.chr"
};
#pragma data(data)
The 32KByte of prg code starts at 0x8000 and goes upto 0xff80. A startup section from 0xff80 to 0xfff9 is taken from the crt.c.
A six byte boot section is placed from 0xfffa to 0xffff in all modes, which has to be populated by the game code with the appropriate pointers.
#pragma data(boot)
__export struct Boot
{
void * nmi, * reset, * irq;
} boot = {
nmi,
(void *)0xff80,
nullptr
};
#pragma data(data)
Rom mappers MMC1 and MMC3 share the last rom bank from 0xc000 to 0xffff including the boot section. This is bank 15 in MMC1 and bank 31 in MMC3.
The pageable ROM is assumed to be 0x8000 to 0xbfff in all banks from zero up.
#pragma section( code0, 0 )
#pragma region( code0, 0x8000, 0xc000, , 0, { code0 } )
And for bank one
#pragma section( code1, 0 )
#pragma region( code1, 0x8000, 0xc000, , 1, { code1 } )
### Inline Assembler

View File

@ -171,6 +171,10 @@ w0:
#elif defined(OSCAR_TARGET_NES)
sei
cld
#if defined(__NES_MMC3__)
lda #$00
sta $8000
#endif
#else
byt 0x0b
byt 0x08

60
include/nes/mmc1.c Normal file
View File

@ -0,0 +1,60 @@
#include "mmc1.h"
void mmc1_reset(void)
{
*(volatile char *)0x8000 = 0x80;
}
void mmc1_config(MMC1Mirror mirror, MMC1MPrgMode pmode, MMC1MChrMode cmode)
{
char reg = mirror | (pmode << 2) | (cmode << 4);
*(volatile char *)0x8000 = reg;
reg >>= 1;
*(volatile char *)0x8000 = reg;
reg >>= 1;
*(volatile char *)0x8000 = reg;
reg >>= 1;
*(volatile char *)0x8000 = reg;
reg >>= 1;
*(volatile char *)0x8000 = reg;
}
void mmc1_bank_prg(char bank)
{
*(volatile char *)0xe000 = bank;
bank >>= 1;
*(volatile char *)0xe000 = bank;
bank >>= 1;
*(volatile char *)0xe000 = bank;
bank >>= 1;
*(volatile char *)0xe000 = bank;
bank >>= 1;
*(volatile char *)0xe000 = bank;
}
void mmc1_bank_chr0(char bank)
{
*(volatile char *)0xa000 = bank;
bank >>= 1;
*(volatile char *)0xa000 = bank;
bank >>= 1;
*(volatile char *)0xa000 = bank;
bank >>= 1;
*(volatile char *)0xa000 = bank;
bank >>= 1;
*(volatile char *)0xa000 = bank;
}
void mmc1_bank_chr1(char bank)
{
*(volatile char *)0xc000 = bank;
bank >>= 1;
*(volatile char *)0xc000 = bank;
bank >>= 1;
*(volatile char *)0xc000 = bank;
bank >>= 1;
*(volatile char *)0xc000 = bank;
bank >>= 1;
*(volatile char *)0xc000 = bank;
}

41
include/nes/mmc1.h Normal file
View File

@ -0,0 +1,41 @@
#ifndef NES_MMC1_H
#define NES_MMC1_H
#include <c64/types.h>
enum MMC1Mirror
{
MMC1M_LOWER,
MMC1M_UPPER,
MMC1M_VERTICAL,
MMC1M_HORIZONTAL
};
enum MMC1MPrgMode
{
MMC1P_32K,
MMC1P_32Kx,
MMC1P_16K_UPPER,
MMC1P_16K_LOWER
};
enum MMC1MChrMode
{
MMC1C_8K,
MMC1C_4Kx,
};
void mmc1_reset(void);
void mmc1_config(MMC1Mirror mirror, MMC1MPrgMode pmode, MMC1MChrMode cmode);
void mmc1_bank_prg(char bank);
void mmc1_bank_chr0(char bank);
void mmc1_bank_chr1(char bank);
#pragma compile("mmc1.c")
#endif

36
include/nes/mmc3.c Normal file
View File

@ -0,0 +1,36 @@
#include "mmc3.h"
char mmc3_shadow;
void mmc3_reset(void)
{
mmc3_shadow = 0;
}
void mmc3_config(MMC3MPrgMode pmode, MMC3MChrMode cmode)
{
mmc3_shadow = (pmode << 6) | (cmode << 7);
*(volatile char *)0x8000 = mmc3_shadow;
}
void mmc3_bank(MMC3BankReg reg, char bank)
{
*(volatile char *)0x8000 = reg | mmc3_shadow;
*(volatile char *)0x8001 = bank;
}
void mmc3_bank_prg(char bank)
{
mmc3_bank(MMC3B_PRG0, bank * 2 + 0);
mmc3_bank(MMC3B_PRG1, bank * 2 + 1);
}
void mmc3_bank_chr0(char bank)
{
mmc3_bank(MMC3B_CHR0, bank);
}
void mmc3_bank_chr1(char bank)
{
mmc3_bank(MMC3B_CHR1, bank);
}

48
include/nes/mmc3.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef NES_MMC3_H
#define NES_MMC3_H
#include <c64/types.h>
enum MMC3MPrgMode
{
MMC3P_8K_LOWER,
MMC3P_8K_UPPER
};
enum MMC3MChrMode
{
MMC3C_2K_LOWER,
MMC3C_2K_HIGHER,
};
enum MMC3BankReg
{
MMC3B_CHR0,
MMC3B_CHR1,
MMC3B_CHR2,
MMC3B_CHR3,
MMC3B_CHR4,
MMC3B_CHR5,
MMC3B_PRG0,
MMC3B_PRG1
};
extern char mmc3_shadow;
void mmc3_reset(void);
void mmc3_config(MMC3MPrgMode pmode, MMC3MChrMode cmode);
inline void mmc3_bank(MMC3BankReg reg, char bank);
void mmc3_bank_prg(char bank);
void mmc3_bank_chr0(char bank);
void mmc3_bank_chr1(char bank);
#pragma compile("mmc3.c")
#endif

View File

@ -641,7 +641,7 @@ __export struct Boot
void * nmi, * reset, * irq;
} boot = {
nmi,
(void *)0x8000,
(void *)0xff80,
nullptr
};

View File

@ -103,6 +103,10 @@ bool Compiler::ParseSource(void)
mCompilationUnits->mSectionLowCode = mLinker->AddSection(Ident::Unique("lowcode"), LST_DATA);
break;
case TMACH_NES:
case TMACH_NES_NROM_H:
case TMACH_NES_NROM_V:
case TMACH_NES_MMC1:
case TMACH_NES_MMC3:
mCompilationUnits->mSectionStack->mSize = 256;
mCompilationUnits->mSectionHeap->mSize = 256;
mCompilationUnits->mSectionBoot = mLinker->AddSection(Ident::Unique("boot"), LST_DATA);
@ -239,7 +243,7 @@ bool Compiler::GenerateCode(void)
if (!regionStartup)
{
if (mCompilerOptions & COPT_TARGET_PRG)
if (mCompilerOptions & (COPT_TARGET_PRG | COPT_TARGET_NES))
{
switch (mTargetMachine)
{
@ -310,10 +314,22 @@ bool Compiler::GenerateCode(void)
else
regionStartup = mLinker->AddRegion(identStartup, 0x2000, 0x2100);
break;
case TMACH_NES:
case TMACH_NES_NROM_H:
case TMACH_NES_NROM_V:
regionStartup = mLinker->AddRegion(identStartup, 0xff80, 0xfffa);
regionStartup->mCartridgeBanks = 1;
break;
case TMACH_NES_MMC1:
regionStartup = mLinker->AddRegion(identStartup, 0xff80, 0xfffa);
regionStartup->mCartridgeBanks = 1ULL << 15;
break;
case TMACH_NES_MMC3:
regionStartup = mLinker->AddRegion(identStartup, 0xff80, 0xfffa);
regionStartup->mCartridgeBanks = 1ULL << 31;
break;
}
}
else if (mTargetMachine == TMACH_NES)
regionStartup = mLinker->AddRegion(identStartup, 0x8000, 0x8080);
else
regionStartup = mLinker->AddRegion(identStartup, 0x0800, 0x0900);
}
@ -377,14 +393,7 @@ bool Compiler::GenerateCode(void)
{
if (!regionMain)
{
if (mTargetMachine == TMACH_NES)
{
regionBoot = mLinker->AddRegion(identBoot, 0xfffa, 0x10000);
regionBoot->mSections.Push(mCompilationUnits->mSectionBoot);
regionRom = mLinker->AddRegion(identRom, 0x8080, 0xfffa);
regionMain = mLinker->AddRegion(identMain, 0x0200, 0x0800);
}
else if (!(mCompilerOptions & COPT_TARGET_PRG))
if (!(mCompilerOptions & (COPT_TARGET_PRG | COPT_TARGET_NES)))
regionMain = mLinker->AddRegion(identMain, 0x0900, 0x4700);
else if (regionBytecode)
{
@ -474,6 +483,32 @@ bool Compiler::GenerateCode(void)
case TMACH_ATARI:
regionMain = mLinker->AddRegion(identMain, 0x2080, 0xbc00);
break;
case TMACH_NES:
case TMACH_NES_NROM_H:
case TMACH_NES_NROM_V:
regionBoot = mLinker->AddRegion(identBoot, 0xfffa, 0x10000);
regionBoot->mCartridgeBanks = 1;
regionBoot->mSections.Push(mCompilationUnits->mSectionBoot);
regionRom = mLinker->AddRegion(identRom, 0x8000, 0xff80);
regionRom->mCartridgeBanks = 1;
regionMain = mLinker->AddRegion(identMain, 0x0200, 0x0800);
break;
case TMACH_NES_MMC1:
regionBoot = mLinker->AddRegion(identBoot, 0xfffa, 0x10000);
regionBoot->mCartridgeBanks = 1ULL << 15;
regionBoot->mSections.Push(mCompilationUnits->mSectionBoot);
regionRom = mLinker->AddRegion(identRom, 0xc000, 0xff80);
regionRom->mCartridgeBanks = 1ULL << 15;
regionMain = mLinker->AddRegion(identMain, 0x0200, 0x0800);
break;
case TMACH_NES_MMC3:
regionBoot = mLinker->AddRegion(identBoot, 0xfffa, 0x10000);
regionBoot->mCartridgeBanks = 1ULL << 31;
regionBoot->mSections.Push(mCompilationUnits->mSectionBoot);
regionRom = mLinker->AddRegion(identRom, 0xc000, 0xff80);
regionRom->mCartridgeBanks = 1ULL << 31;
regionMain = mLinker->AddRegion(identMain, 0x0200, 0x0800);
break;
}
}
}
@ -828,7 +863,7 @@ bool Compiler::WriteOutputFile(const char* targetPath, DiskImage * d64)
strcat_s(prgPath, "nes");
if (mCompilerOptions & COPT_VERBOSE)
printf("Writing <%s>\n", prgPath);
mLinker->WriteNesFile(prgPath);
mLinker->WriteNesFile(prgPath, mTargetMachine);
}
@ -859,7 +894,7 @@ bool Compiler::WriteOutputFile(const char* targetPath, DiskImage * d64)
printf("Writing <%s>\n", lblPath);
if (mCompilerOptions & COPT_TARGET_NES)
mLinker->WriteMlbFile(lblPath);
mLinker->WriteMlbFile(lblPath, mTargetMachine);
else
mLinker->WriteLblFile(lblPath);

View File

@ -54,6 +54,10 @@ enum TargetMachine
TMACH_PET_32K,
TMACH_PLUS4,
TMACH_NES,
TMACH_NES_NROM_H,
TMACH_NES_NROM_V,
TMACH_NES_MMC1,
TMACH_NES_MMC3,
TMACH_ATARI
};

View File

@ -86,7 +86,7 @@ void ByteCodeDisassembler::Disassemble(FILE* file, const uint8* memory, int bank
{
ByteCode bc = ByteCode(memory[start + i] / 2);
if (bank)
if (bank >= 0)
fprintf(file, "%02x:", bank);
fprintf(file, "%04x:\t", start + i);
@ -627,7 +627,7 @@ void NativeCodeDisassembler::DumpMemory(FILE* file, const uint8* memory, int ban
if (lobj->mSection->mType == LST_BSS)
{
if (bank)
if (bank >= 0)
fprintf(file, "%02x:", bank);
fprintf(file, "%04x : __ __ __ BSS\t%d\n", start, size);
@ -641,7 +641,7 @@ void NativeCodeDisassembler::DumpMemory(FILE* file, const uint8* memory, int ban
if (ip + n > start + size)
n = start + size - ip;
if (bank)
if (bank >= 0)
fprintf(file, "%02x:", bank);
fprintf(file, "%04x : __ __ __ BYT", ip);
@ -693,7 +693,7 @@ void NativeCodeDisassembler::Disassemble(FILE* file, const uint8* memory, int ba
fprintf(file, ".%s:\n", proc->mLinkerObject->mRanges[i].mIdent->mString);
}
if (bank)
if (bank >= 0)
fprintf(file, "%02x:", bank);
switch (d.mMode)

View File

@ -611,7 +611,7 @@ bool Linker::WriteBinFile(const char* filename)
return false;
}
bool Linker::WriteNesFile(const char* filename)
bool Linker::WriteNesFile(const char* filename, TargetMachine machine)
{
FILE* file;
fopen_s(&file, filename, "wb");
@ -619,12 +619,57 @@ bool Linker::WriteNesFile(const char* filename)
{
char header[16] = { 0x4e, 0x45, 0x53, 0x1a, 0x02, 0x01, 0x01, 0x00, 0x02, 0x00, 0x00 };
fwrite(header, 1, 16, file);
int done = fwrite(mMemory + 0x8000, 1, 0x8000, file);
done += fwrite(mCartridge[0], 1, 0x2000, file);
switch (machine)
{
case TMACH_NES:
header[6] = 0x08;
break;
case TMACH_NES_NROM_H:
header[6] = 0x00;
break;
case TMACH_NES_NROM_V:
header[6] = 0x01;
break;
case TMACH_NES_MMC1:
header[4] = 16;
header[5] = 16;
header[6] = 0x10;
break;
case TMACH_NES_MMC3:
header[4] = 32;
header[5] = 32;
header[6] = 0x48;
break;
}
int done = fwrite(header, 1, 16, file);
switch (machine)
{
case TMACH_NES:
case TMACH_NES_NROM_H:
case TMACH_NES_NROM_V:
fwrite(mCartridge[0] + 0x8000, 1, 0x8000, file);
fwrite(mCartridge[0], 1, 0x2000, file);
break;
case TMACH_NES_MMC1:
for(int i=0; i<15; i++)
fwrite(mCartridge[i] + 0x8000, 1, 0x4000, file);
fwrite(mCartridge[15] + 0xc000, 1, 0x4000, file);
for (int i = 0; i < 16; i++)
fwrite(mCartridge[i], 1, 0x2000, file);
break;
case TMACH_NES_MMC3:
for (int i = 0; i < 31; i++)
fwrite(mCartridge[i] + 0x8000, 1, 0x4000, file);
fwrite(mCartridge[31] + 0xc000, 1, 0x4000, file);
for (int i = 0; i < 32; i++)
fwrite(mCartridge[i], 1, 0x2000, file);
break;
}
fclose(file);
return done == 0x8000 + 0x2000;
return done == 16;
}
else
return false;
@ -944,7 +989,29 @@ bool Linker::WriteMapFile(const char* filename)
return false;
}
bool Linker::WriteMlbFile(const char* filename)
int Linker::TranslateMlbAddress(int address, int bank, TargetMachine machine)
{
switch (machine)
{
default:
case TMACH_NES:
case TMACH_NES_NROM_H:
case TMACH_NES_NROM_V:
return address - 0x8000;
case TMACH_NES_MMC1:
if (bank == 15)
return 15 * 0x4000 + address - 0xc000;
else
return bank * 0x4000 + address - 0x8000;
case TMACH_NES_MMC3:
if (bank == 31)
return 31 * 0x4000 + address - 0xc000;
else
return bank * 0x4000 + address - 0x8000;
}
}
bool Linker::WriteMlbFile(const char* filename, TargetMachine machine)
{
FILE* file;
fopen_s(&file, filename, "wb");
@ -964,6 +1031,12 @@ bool Linker::WriteMlbFile(const char* filename)
if ((obj->mFlags & LOBJF_REFERENCED) && obj->mIdent && obj->mSize > 0)
{
int bank = -1;
if (obj->mRegion->mCartridgeBanks)
{
do { bank++; } while (!((1ULL << bank) & obj->mRegion->mCartridgeBanks));
}
if (obj->mSection->mType == LST_BSS)
{
if (obj->mRanges.Size() > 0)
@ -978,27 +1051,27 @@ bool Linker::WriteMlbFile(const char* filename)
}
else if (obj->mType == LOT_DATA)
{
if (!obj->mRegion->mCartridgeBanks)
if (obj->mAddress >= 0x8000)
{
if (obj->mRanges.Size() > 0)
{
for (int i = 0; i < obj->mRanges.Size(); i++)
fprintf(file, "P:%04x-%04x:%s@%s\n", obj->mAddress + obj->mRanges[i].mOffset - 0x8000, obj->mAddress + obj->mRanges[i].mOffset + obj->mRanges[i].mSize - 0x8000 - 1, obj->mIdent->mString, obj->mRanges[i].mIdent->mString);
fprintf(file, "P:%04x-%04x:%s@%s\n", TranslateMlbAddress(obj->mAddress + obj->mRanges[i].mOffset, bank, machine), TranslateMlbAddress(obj->mAddress + obj->mRanges[i].mOffset + obj->mRanges[i].mSize - 1, bank, machine), obj->mIdent->mString, obj->mRanges[i].mIdent->mString);
}
fprintf(file, "P:%04x-%04x:%s\n", obj->mAddress - 0x8000, obj->mAddress - 0x8000 + obj->mSize - 1, obj->mIdent->mString);
fprintf(file, "P:%04x-%04x:%s\n", TranslateMlbAddress(obj->mAddress, bank, machine), TranslateMlbAddress(obj->mAddress + obj->mSize - 1, bank, machine), obj->mIdent->mString);
}
}
else if (obj->mType == LOT_NATIVE_CODE)
{
if (!obj->mRegion->mCartridgeBanks)
if (obj->mAddress >= 0x8000)
{
if (obj->mRanges.Size() > 0)
{
for (int i = 0; i < obj->mRanges.Size(); i++)
fprintf(file, "P:%04x:%s@%s\n", obj->mAddress + obj->mRanges[i].mOffset - 0x8000, obj->mIdent->mString, obj->mRanges[i].mIdent->mString);
fprintf(file, "P:%04x:%s@%s\n", TranslateMlbAddress(obj->mAddress + obj->mRanges[i].mOffset, bank, machine), obj->mIdent->mString, obj->mRanges[i].mIdent->mString);
}
fprintf(file, "P:%04x:%s\n", obj->mAddress - 0x8000, obj->mIdent->mString);
fprintf(file, "P:%04x:%s\n", TranslateMlbAddress(obj->mAddress, bank, machine), obj->mIdent->mString);
}
}
}
@ -1052,7 +1125,7 @@ bool Linker::WriteAsmFile(const char* filename)
switch (obj->mType)
{
case LOT_BYTE_CODE:
mByteCodeDisassembler.Disassemble(file, mMemory, 0, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this);
mByteCodeDisassembler.Disassemble(file, mMemory, -1, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this);
break;
case LOT_NATIVE_CODE:
if (obj->mRegion->mCartridgeBanks)
@ -1063,7 +1136,7 @@ bool Linker::WriteAsmFile(const char* filename)
mNativeDisassembler.Disassemble(file, mCartridge[i], i, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this);
}
else
mNativeDisassembler.Disassemble(file, mMemory, 0, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this);
mNativeDisassembler.Disassemble(file, mMemory, -1, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this);
break;
case LOT_DATA:
if (obj->mRegion->mCartridgeBanks)
@ -1074,7 +1147,7 @@ bool Linker::WriteAsmFile(const char* filename)
mNativeDisassembler.DumpMemory(file, mCartridge[i], i, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this, obj);
}
else
mNativeDisassembler.DumpMemory(file, mMemory, 0, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this, obj);
mNativeDisassembler.DumpMemory(file, mMemory, -1, obj->mAddress, obj->mSize, obj->mProc, obj->mIdent, this, obj);
break;
}
}

View File

@ -6,6 +6,7 @@
#include "Errors.h"
#include "Disassembler.h"
#include "DiskImage.h"
#include "CompilerTypes.h"
class InterCodeProcedure;
@ -238,8 +239,10 @@ public:
bool WriteLblFile(const char* filename);
bool WriteCrtFile(const char* filename);
bool WriteBinFile(const char* filename);
bool WriteNesFile(const char* filename);
bool WriteMlbFile(const char* filename);
bool WriteNesFile(const char* filename, TargetMachine machine);
bool WriteMlbFile(const char* filename, TargetMachine machine);
int TranslateMlbAddress(int address, int bank, TargetMachine machine);
uint64 mCompilerOptions;

View File

@ -3702,63 +3702,66 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
}
else if (mMode == ASMIM_INDIRECT_Y)
{
if (data.mRegs[mAddress].mMode == NRDM_ZERO_PAGE && data.mRegs[mAddress + 1].mMode == NRDM_ZERO_PAGE && data.mRegs[mAddress].mValue + 1 == data.mRegs[mAddress + 1].mValue)
if (!(mFlags & NCIF_VOLATILE))
{
mFlags |= NICT_ZPFLIPPED;
mAddress = data.mRegs[mAddress].mValue;
if (mType == ASMIT_LDA)
data.mRegs[CPU_REG_A].Reset();
}
else if (data.mRegs[mAddress].mMode == NRDM_IMMEDIATE_ADDRESS && data.mRegs[mAddress + 1].mMode == NRDM_IMMEDIATE_ADDRESS && data.mRegs[mAddress].mLinkerObject == data.mRegs[mAddress + 1].mLinkerObject)
{
mMode = ASMIM_ABSOLUTE_Y;
mLinkerObject = data.mRegs[mAddress].mLinkerObject;
mAddress = data.mRegs[mAddress + 1].mValue;
if (mType == ASMIT_LDA)
data.mRegs[CPU_REG_A].Reset();
}
else if (mType == ASMIT_LDA)
{
if (!(mFlags & NCIF_VOLATILE))
if (data.mRegs[mAddress].mMode == NRDM_ZERO_PAGE && data.mRegs[mAddress + 1].mMode == NRDM_ZERO_PAGE && data.mRegs[mAddress].mValue + 1 == data.mRegs[mAddress + 1].mValue)
{
if (data.mRegs[CPU_REG_A].mMode == NRDM_INDIRECT_Y && data.mRegs[CPU_REG_A].mValue == mAddress)
mFlags |= NICT_ZPFLIPPED;
mAddress = data.mRegs[mAddress].mValue;
if (mType == ASMIT_LDA)
data.mRegs[CPU_REG_A].Reset();
}
else if (data.mRegs[mAddress].mMode == NRDM_IMMEDIATE_ADDRESS && data.mRegs[mAddress + 1].mMode == NRDM_IMMEDIATE_ADDRESS && data.mRegs[mAddress].mLinkerObject == data.mRegs[mAddress + 1].mLinkerObject)
{
mMode = ASMIM_ABSOLUTE_Y;
mLinkerObject = data.mRegs[mAddress].mLinkerObject;
mAddress = data.mRegs[mAddress + 1].mValue;
if (mType == ASMIT_LDA)
data.mRegs[CPU_REG_A].Reset();
}
else if (mType == ASMIT_LDA)
{
if (!(mFlags & NCIF_VOLATILE))
{
if (mLive & LIVE_CPU_REG_Z)
if (data.mRegs[CPU_REG_A].mMode == NRDM_INDIRECT_Y && data.mRegs[CPU_REG_A].mValue == mAddress)
{
mType = ASMIT_ORA;
mMode = ASMIM_IMMEDIATE;
mAddress = 0;
if (mLive & LIVE_CPU_REG_Z)
{
mType = ASMIT_ORA;
mMode = ASMIM_IMMEDIATE;
mAddress = 0;
}
else
{
mType = ASMIT_NOP;
mMode = ASMIM_IMPLIED;
}
changed = true;
}
else if (data.mRegs[CPU_REG_X].SameData(*this))
{
mType = ASMIT_TXA;
mMode = ASMIM_IMPLIED;
data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_X];
changed = true;
}
else if (data.mRegs[CPU_REG_Y].SameData(*this))
{
mType = ASMIT_TYA;
mMode = ASMIM_IMPLIED;
data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_Y];
changed = true;
}
else
{
mType = ASMIT_NOP;
mMode = ASMIM_IMPLIED;
data.mRegs[CPU_REG_A].mMode = NRDM_INDIRECT_Y;
data.mRegs[CPU_REG_A].mValue = mAddress;
data.mRegs[CPU_REG_A].mFlags = mFlags;
}
changed = true;
}
else if (data.mRegs[CPU_REG_X].SameData(*this))
{
mType = ASMIT_TXA;
mMode = ASMIM_IMPLIED;
data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_X];
changed = true;
}
else if (data.mRegs[CPU_REG_Y].SameData(*this))
{
mType = ASMIT_TYA;
mMode = ASMIM_IMPLIED;
data.mRegs[CPU_REG_A] = data.mRegs[CPU_REG_Y];
changed = true;
}
else
{
data.mRegs[CPU_REG_A].mMode = NRDM_INDIRECT_Y;
data.mRegs[CPU_REG_A].mValue = mAddress;
data.mRegs[CPU_REG_A].mFlags = mFlags;
}
data.mRegs[CPU_REG_A].Reset();
}
else
data.mRegs[CPU_REG_A].Reset();
}
if (ChangesAddress())
@ -25143,6 +25146,27 @@ bool NativeCodeBasicBlock::BitFieldForwarding(const NativeRegisterDataSet& data)
}
}
#endif
if (i + 1 < mIns.Size() &&
mIns[i + 0].mType == ASMIT_TXA && !(mIns[i + 0].mLive & LIVE_CPU_REG_X) &&
mIns[i + 1].mType == ASMIT_ORA && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 1)
{
if (mNDataSet.mRegs[CPU_REG_X].mMask & 1)
{
if (mNDataSet.mRegs[CPU_REG_X].mValue & 1)
{
mIns[i + 1].mAddress = 0;
changed = true;
}
else
{
mIns[i + 0].mType = ASMIT_INX; mIns[i + 0].mLive |= LIVE_CPU_REG_X;
mIns[i + 1].mType = ASMIT_TXA; mIns[i + 1].mMode = ASMIM_IMPLIED;
changed = true;
}
}
}
bool skip = false;
if (i + 2 < mIns.Size() &&
@ -34896,7 +34920,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
}
else if (
mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ABSOLUTE)
mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ABSOLUTE && !(mIns[i + 1].mFlags & NCIF_VOLATILE))
{
proc->ResetPatched();
if (CheckSingleUseGlobalLoad(this, mIns[i + 0].mAddress, i + 2, mIns[i + 1], 2))
@ -37317,7 +37341,7 @@ void NativeCodeProcedure::RebuildEntry(void)
void NativeCodeProcedure::Optimize(void)
{
CheckFunc = !strcmp(mInterProc->mIdent->mString, "main");
CheckFunc = !strcmp(mInterProc->mIdent->mString, "mmc3_bank_prg");
#if 1
int step = 0;

View File

@ -293,7 +293,7 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags)
dec->mIdent = mScanner->mTokenIdent;
if (mScope->Insert(dec->mIdent, dec))
mErrors->Error(dec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate name");
mErrors->Error(dec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate name", dec->mIdent);
mScanner->NextToken();
}

View File

@ -311,8 +311,22 @@ int main2(int argc, const char** argv)
else if (!strcmp(targetMachine, "nes"))
{
compiler->mTargetMachine = TMACH_NES;
compiler->mCompilerOptions |= COPT_EXTENDED_ZERO_PAGE;
compiler->AddDefine(Ident::Unique("__NES__"), "1");
}
else if (!strcmp(targetMachine, "nes_nrom_h"))
{
compiler->mTargetMachine = TMACH_NES_NROM_H;
}
else if (!strcmp(targetMachine, "nes_nrom_v"))
{
compiler->mTargetMachine = TMACH_NES_NROM_V;
}
else if (!strcmp(targetMachine, "nes_mmc1"))
{
compiler->mTargetMachine = TMACH_NES_MMC1;
}
else if (!strcmp(targetMachine, "nes_mmc3"))
{
compiler->mTargetMachine = TMACH_NES_MMC3;
}
else if (!strcmp(targetMachine, "atari"))
{
@ -323,10 +337,27 @@ int main2(int argc, const char** argv)
compiler->mErrors->Error(loc, EERR_COMMAND_LINE, "Invalid target machine option", targetMachine);
if (compiler->mTargetMachine == TMACH_NES)
if (compiler->mTargetMachine >= TMACH_NES && compiler->mTargetMachine <= TMACH_NES_MMC3)
{
compiler->mCompilerOptions |= COPT_TARGET_NES;
compiler->mCompilerOptions |= COPT_EXTENDED_ZERO_PAGE;
compiler->mCompilerOptions |= COPT_NATIVE;
compiler->AddDefine(Ident::Unique("OSCAR_TARGET_NES"), "1");
switch (compiler->mTargetMachine)
{
default:
case TMACH_NES:
case TMACH_NES_NROM_H:
case TMACH_NES_NROM_V:
break;
case TMACH_NES_MMC1:
compiler->AddDefine(Ident::Unique("__NES_MMC1__"), "1");
break;
case TMACH_NES_MMC3:
compiler->AddDefine(Ident::Unique("__NES_MMC3__"), "1");
break;
}
compiler->AddDefine(Ident::Unique("__NES__"), "1");
}
else if (!strcmp(targetFormat, "prg"))
{

View File

@ -190,6 +190,12 @@
}
"Entry"
{
"MsmKey" = "8:_2CC169DCBB0B4CC0BFE38AE63B285359"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_2D828D0247F144CDB0112B2AD4004C2C"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@ -298,6 +304,12 @@
}
"Entry"
{
"MsmKey" = "8:_492AD1ED992D44F1A65903A5232C0426"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_494DB63135144419A8E0E6037E1B3237"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@ -850,6 +862,12 @@
}
"Entry"
{
"MsmKey" = "8:_CDBE2B8738C843CBB146767FBEE9A828"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_D0E45B48D76B4407B0BDE4378C1DB2C7"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@ -994,6 +1012,12 @@
}
"Entry"
{
"MsmKey" = "8:_ED5FED616EA64689AB793E5D8BD3F13D"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_ED872D39D58443D590B7C80604BC0FF4"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
@ -1731,6 +1755,26 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2CC169DCBB0B4CC0BFE38AE63B285359"
{
"SourcePath" = "8:..\\include\\nes\\mmc1.c"
"TargetName" = "8:mmc1.c"
"Tag" = "8:"
"Folder" = "8:_9F35D1516FB34C30A2C5C1CA12501231"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2D828D0247F144CDB0112B2AD4004C2C"
{
"SourcePath" = "8:..\\samples\\scrolling\\tunnel.c"
@ -2091,6 +2135,26 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_492AD1ED992D44F1A65903A5232C0426"
{
"SourcePath" = "8:..\\include\\nes\\mmc3.h"
"TargetName" = "8:mmc3.h"
"Tag" = "8:"
"Folder" = "8:_9F35D1516FB34C30A2C5C1CA12501231"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_494DB63135144419A8E0E6037E1B3237"
{
"SourcePath" = "8:..\\include\\c128\\bank1.c"
@ -3931,6 +3995,26 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CDBE2B8738C843CBB146767FBEE9A828"
{
"SourcePath" = "8:..\\include\\nes\\mmc1.h"
"TargetName" = "8:mmc1.h"
"Tag" = "8:"
"Folder" = "8:_9F35D1516FB34C30A2C5C1CA12501231"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D0E45B48D76B4407B0BDE4378C1DB2C7"
{
"SourcePath" = "8:..\\include\\stdlib.h"
@ -4411,6 +4495,26 @@
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_ED5FED616EA64689AB793E5D8BD3F13D"
{
"SourcePath" = "8:..\\include\\nes\\mmc3.c"
"TargetName" = "8:mmc3.c"
"Tag" = "8:"
"Folder" = "8:_9F35D1516FB34C30A2C5C1CA12501231"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_ED872D39D58443D590B7C80604BC0FF4"
{
"SourcePath" = "8:..\\samples\\kernalio\\fileread.c"
@ -4963,7 +5067,7 @@
"Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:oscar64"
"ProductCode" = "8:{85311ED7-CC4D-4512-840D-20C87C74DAC0}"
"PackageCode" = "8:{84A20228-DD88-421A-9DE4-33A058638C87}"
"PackageCode" = "8:{9C4FC9E1-982E-42B2-B9D0-8D5984BC0B2B}"
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
"AspNetVersion" = "8:2.0.50727.0"
"RestartWWWService" = "11:FALSE"