Mapper019.sflp

  • タグ:
  • タグはありません
/*
	Mapper 019
	Namcot 106/163
		PRG-ROM 16KB banks 2 (4) 8 16 32 max 512KB
		CHR-ROM 8KB banks 16 32 max 256KB
		CHR-RAM (nes.nsf)
*/

%i "n106/n106_core.h"

circuit Mapper019
{
	// PRG-ROM
	input ROM_SELn;
	instrin prg_read, prg_write;
	input prg_A<15>, prg_Din<8>;
	output prg_Dout<8>;
	output IRQn;

	// CHR-ROM
	instrin chr_read, chr_write; // RDn, WEn
	input chr_A<14>, chr_Din<8>; // chr_A13n
	output chr_Dout<8>;
	output VRAM_CSn, VRAM_A10;

	instrin Phi; // 1.789MHz
	output usound<11>, ssound<14>;

	instrout exram_read(exram_adrs);
	output exram_adrs<13>; // EX_RAM 8KB
	output exram_wdata<8>;
	instrout exram_write(exram_adrs, exram_wdata);
	input exram_rdata<8>;

	// 外部RAMへのアクセス
	instrout prg_ram_read(prg_ram_adrs);
	output prg_ram_adrs<19>; // PRG_ROM max 512KB
//	output prg_ram_wdata<8>;
//	instrout prg_ram_write(prg_ram_adrs, prg_ram_wdata);
	input prg_ram_rdata<8>;

	instrout chr_ram_read(chr_ram_adrs);
	output chr_ram_adrs<18>; // CHR_ROM max 256KB
	output chr_ram_wdata<8>;
	instrout chr_ram_write(chr_ram_adrs, chr_ram_wdata);
	input chr_ram_rdata<8>;

	instrin ready, init;
	instrin hblank;

	input n16kRomBanks<6>, n8kVRomBanks<6>, fMirroringType;

	reg_wr prg_bank4<6>, prg_bank5<6>, prg_bank6<6>, prg_bank7<6>;
	reg_wr chr_bank0<8>, chr_bank1<8>, chr_bank2<8>, chr_bank3<8>;
	reg_wr chr_bank4<8>, chr_bank5<8>, chr_bank6<8>, chr_bank7<8>;
	reg_wr chr_bank8<8>, chr_bank9<8>, chr_bank10<8>, chr_bank11<8>;

	instrself map_rom, map_exrom, map_exram;

	reg_ws IRQn_reg;

	n106_core n106;

	reg_wr regs0, regs1;
	reg_wr irq_counter_L<8>, irq_counter_H<8>, irq_enabled;

	reg_wr prg_mask<6>, chr_mask<8>;
	sel prg_read_bank<6>, chr_bank<8>;
	sel irq_counter_s<16>;

	par{
		if(ROM_SELn==0b0){
			map_rom();
		}
		else any{
			prg_A<14:13>==0b10 : map_exrom();
			prg_A<14:13>==0b11 : map_exram();
		}

		any{
			map_exrom : any{
				prg_A<12:10>==0b010 : par{ // $4800
					prg_Dout = n106.io_Dout;
				}
			}
			map_exram : prg_Dout = exram_rdata;
			map_rom : prg_Dout = prg_ram_rdata;
		}

		if(chr_A<13>==0b0){
			// chr_bank<8> + chr_A<10> = <18>
		//	sel chr_read_bank<8>;
			switch(chr_A<12:10>){
				case 0b000: chr_bank = chr_bank0;
				case 0b001: chr_bank = chr_bank1;
				case 0b010: chr_bank = chr_bank2;
				case 0b011: chr_bank = chr_bank3;
				case 0b100: chr_bank = chr_bank4;
				case 0b101: chr_bank = chr_bank5;
				case 0b110: chr_bank = chr_bank6;
				case 0b111: chr_bank = chr_bank7;
			}
			VRAM_CSn = 0b1;
		}
		else{ // NameTable or CHR-ROM
			switch(chr_A<11:10>){
				case 0b00: par{
					if(/&chr_bank8<7:5>){
						VRAM_CSn = 0b0;
						VRAM_A10 = chr_bank8<0>;
					}
					else{
						VRAM_CSn = 0b1;
						chr_bank = chr_bank8;
					}
				}
				case 0b01: par{
					if(/&chr_bank9<7:5>){
						VRAM_CSn = 0b0;
						VRAM_A10 = chr_bank9<0>;
					}
					else{
						VRAM_CSn = 0b1;
						chr_bank = chr_bank9;
					}
				}
				case 0b10: par{
					if(/&chr_bank10<7:5>){
						VRAM_CSn = 0b0;
						VRAM_A10 = chr_bank10<0>;
					}
					else{
						VRAM_CSn = 0b1;
						chr_bank = chr_bank10;
					}
				}
				case 0b11: par{
					if(/&chr_bank11<7:5>){
						VRAM_CSn = 0b0;
						VRAM_A10 = chr_bank11<0>;
					}
					else{
						VRAM_CSn = 0b1;
						chr_bank = chr_bank11;
					}
				}
			}
		}

		chr_Dout = chr_ram_rdata;

		IRQn = IRQn_reg;

		usound = // <11>
			0b00 || n106.sound || 0b00;

		ssound = // <14s>
		   0b00000000000000;
	}

	instruct ready n106.ready();

	instruct init par{
		prg_bank4 := 0b000000;
		prg_bank5 := 0b000001;
		prg_bank6 := 0b111110; //(n16kRomBanks - 0b000001)<4:0> || 0b0;
		prg_bank7 := 0b111111; //(n16kRomBanks - 0b000001)<4:0> || 0b1;
		prg_mask  := (n16kRomBanks - 0b000001)<4:0> || 0b1;
		irq_counter_L := 0;
		irq_counter_H := 0;
		irq_enabled := 0;
		chr_bank0 := 0x00;
		chr_bank1 := 0x01;
		chr_bank2 := 0x02;
		chr_bank3 := 0x03;
		chr_bank4 := 0x04;
		chr_bank5 := 0x05;
		chr_bank6 := 0x06;
		chr_bank7 := 0x07;
		chr_mask := (n8kVRomBanks - 0b000001)<4:0> || 0b111;
		if(fMirroringType){
			chr_bank8 := 0x00;
			chr_bank9 := 0x01;
			chr_bank10 := 0x00;
			chr_bank11 := 0x01;
		}
		else{
			chr_bank8 := 0x00;
			chr_bank9 := 0x00;
			chr_bank10 := 0x01;
			chr_bank11 := 0x01;
		}
		regs0 := 0b0;
		regs1 := 0b0;
	}

	instruct prg_read any{
		map_exrom : par{
			switch(prg_A<12:11>){
				case 0b01: par{ // $4800
					n106.io_read(0b0);
				}
				case 0b10: par{ // $5000
					prg_Dout = irq_counter_L;
				}
				case 0b11: par{ // $5800
					prg_Dout = 0b0 || irq_counter_H<6:0>;
				}
				default: prg_Dout = 0b0 || prg_A<14:8>;
			}
		}
		map_rom : par{
			// prg_bank<6> + prg_A<13> = <19>
		//	sel prg_read_bank<6>;
			switch(prg_A<14:13>){
				case 0b00: prg_read_bank = prg_bank4;
				case 0b01: prg_read_bank = prg_bank5;
				case 0b10: prg_read_bank = prg_bank6;
				case 0b11: prg_read_bank = prg_bank7;
			}
			prg_ram_read((prg_read_bank & prg_mask) || prg_A<12:0>);
		}
		map_exram : exram_read(prg_A<12:0>);
	}

	instruct prg_write any{
		map_exrom : par{
			switch(prg_A<12:11>){
				case 0b01: par{ // $4800
					n106.io_write(0b0, prg_Din);
				}
				case 0b10: par{ // $5000
					irq_counter_L := prg_Din;
					IRQn_reg := 0b1;
				}
				case 0b11: par{ // $5800
					irq_counter_H := 0b0 || prg_Din<6:0>;
					irq_enabled := prg_Din<7>;
					IRQn_reg := 0b1;
				}
			}
		}
		map_rom : par{
			switch(prg_A<14:11>){
				case 0b0000: par{ // $8000
					if((prg_Din<7:5>!=0b111) | regs0) chr_bank0 := prg_Din;
					else chr_bank0 := 0x00;
				}
				case 0b0001: par{ // $8800
					if((prg_Din<7:5>!=0b111) | regs0) chr_bank1 := prg_Din;
					else chr_bank1 := 0x01;
				}
				case 0b0010: par{ // $9000
					if((prg_Din<7:5>!=0b111) | regs0) chr_bank2 := prg_Din;
					else chr_bank2 := 0x02;
				}
				case 0b0011: par{ // $9800
					if((prg_Din<7:5>!=0b111) | regs0) chr_bank3 := prg_Din;
					else chr_bank3 := 0x03;
				}
				case 0b0100: par{ // $A000
					if((prg_Din<7:5>!=0b111) | regs1) chr_bank4 := prg_Din;
					else chr_bank4 := 0x04;
				}
				case 0b0101: par{ // $A800
					if((prg_Din<7:5>!=0b111) | regs1) chr_bank5 := prg_Din;
					else chr_bank5 := 0x05;
				}
				case 0b0110: par{ // $B000
					if((prg_Din<7:5>!=0b111) | regs1) chr_bank6 := prg_Din;
					else chr_bank6 := 0x06;
				}
				case 0b0111: par{ // $B800
					if((prg_Din<7:5>!=0b111) | regs1) chr_bank7 := prg_Din;
					else chr_bank7 := 0x07;
				}
				case 0b1000: par{ // $C000
					chr_bank8 := prg_Din;
				}
				case 0b1001: par{ // $C800
					chr_bank9 := prg_Din;
				}
				case 0b1010: par{ // $D000
					chr_bank10 := prg_Din;
				}
				case 0b1011: par{ // $D800
					chr_bank11 := prg_Din;
				}
				case 0b1100: par{ // $E000
					prg_bank4 := prg_Din<5:0>;
				}
				case 0b1101: par{ // $E800
					prg_bank5 := prg_Din<5:0>;
					regs0 := prg_Din<6>;
					regs1 := prg_Din<7>;
				}
				case 0b1110: par{ // $F000
					prg_bank6 := prg_Din<5:0>;
				}
				case 0b1111: par{ // $F800
					n106.io_write(0b1, prg_Din);
				}
			}
		}
		map_exram : /*if(fSaveRAMenable)*/ exram_write(prg_A<12:0>, prg_Din);
	}

	instruct chr_read par{
		if(VRAM_CSn==0b1){
			chr_ram_read((chr_bank & chr_mask) || chr_A<9:0>);
		}
	}

	instruct chr_write par{
		if(VRAM_CSn==0b1){
			chr_ram_write((chr_bank & chr_mask) || chr_A<9:0>, chr_Din);
		}
	}

	instruct Phi n106.run();

	instruct hblank par{
		if(irq_enabled){
			if(irq_counter_H<7>){
				irq_counter_L := 0xFF;
				irq_counter_H := 0x7F;
				IRQn_reg := 0b0;
				irq_enabled := 0b0;
			}
			else{
				irq_counter_s = (irq_counter_H||irq_counter_L) + 0x0071;
				irq_counter_L := irq_counter_s<7:0>;
				irq_counter_H := irq_counter_s<15:8>;
			}
		}
	}

}