Самостоятелно направи касети за dendy
След моята статия за самосвал патрони (които все още са оставени на Хабре по някаква причина), аз много пъти ме помоли да ви кажа как да се събират и записват касети за NES / самата Famicom. Да, това е един много банален въпрос, дори в старите броеве на списание "Радио" за него може да се прочете, но напредъкът не стои на едно място. Помислете за този проблем от гледна точка на съвременните компоненти на. Особено, по мое мнение, той е идеален за проучване на основите на работа с FPGAs, по този въпрос, аз се учи.
Старт, може би, е необходимо да се разпореди, че са били продадени на касетите и да продължат да се продават в нашите магазини, презаписване, уви, няма да работи (в действителност, някои може, но повече за това друг път). Причината е, че те инсталира обикновен EPROM памет, която може да се запише само веднъж. Въпреки това, нищо не пречи на създадете свой собствен от нулата патрон.
Позволете ми да ви напомня, че касетата е включен директно в процесора и гумата PPU автобус и съответно на първа инстанция съдържа два чипа с памет на едновременен достъп: PRG - процесор го има достъп, и тя съдържа подробно код на играта, както и CHR - PPU работи с него (графичен процесор) и съдържа изображение. Какво означава той да може лесно да бъде ROM и RAM, когато данните вече е записано в хода на играта.
По този начин, най-лесният патрона може да се направи от всеки две чипове памет паралелно свързване, независимо дали това е най-малко на EPROM, макар и флаш. В този случай, нищо повече нужда от чембероваъчната. Например, тя изглежда като това е първият ми самостоятелно направени патрон:
Въпреки това, такъв патрон може да се запише само най-проста игра. По-тежка вече използват патрони картографи за увеличаване на максималния размер на игри. Ще се опитам да обясня как се работи.
Но повечето от игрите, която използва по-сложни чипове, които са специално предназначени за тази цел.
Те са склонни да бъдат в състояние да превключвате между различните банки имат различни области на паметта за управление на допълнителна памет, за да се генерира прекъсване, а понякога дори и за разширяване на изчислителна мощност на конзолата.
Нека се опитаме да се симулира четящото устройство за работа с помощта на FPGAs. Аз пиша код на езика на Verilog. Той не е осветен, аз се извинявам за това.
Първо ще опишем нашите регистри, които съхраняват текущото състояние:
рег [2: 0] bank_select;
рег prg_mode;
рег chr_mode;
рег [7: 0] R [0: 7];
рег огледало;
рег [7: 6] ram_protect;
рег [7: 0] irq_latch;
рег [7: 0] irq_counter;
рег [2: 0] a12_low_time;
рег irq_reload;
рег irq_reload_clear;
рег irq_enabled;
винаги @ (posedge romsel)
започвам
// Но само ако това е рекорд
ако (cpu_rw_in == 0)
започвам
// разгледа състоянието на A14, A13 и A0, актуализирайте съответните регистри
случай ()
3'b000: // започне $ 8000- $ 9FFE, дори и
bank_select <= cpu_data_in[2:0];
prg_mode <= cpu_data_in[6];
chr_mode <= cpu_data_in[7];
край
3'b001: г [bank_select] <= cpu_data_in; // $8001-$9FFF, odd
3'b010: Дублиране <= cpu_data_in[0]; // $A000-$BFFE, even
3'b011: ram_protect <= cpu_data_in[7:6]; // $A001-$BFFF, odd
3'b100: irq_latch <= cpu_data_in; // $C000-$DFFE, even
3'b101: irq_reload <= 1; // $C001-$DFFF, odd
3'b110: irq_enabled <= 0; // $E000-$FFFE, even
3'b111: irq_enabled <= 1; // $E001-$FFFF, odd
endcase
край
ако (irq_reload_clear)
irq_reload <= 0;
край
Сега, опишете какво трябва да бъде избран на банката по отношение на съответната част от паметта в зависимост от нашите регистри.
те са включени в съответствие с таблицата по-долу:
Къде $ 8000 # 40 $ - това е нашата prg_mode и -2 и -1 - е предпоследната и последната банка, съответно. Оказва се следния код:
// PRG банкиране
винаги @ (*)
започвам
случай ()
// $ 8000- $ 9FFF
3'b000: cpu_addr_out [18:13] <= r[6][5:0];
3'b001: cpu_addr_out [18:13] <= 6’b111110; // Предпоследний банк
// $ A000- $ BFFF
3'b010,
3'b011: cpu_addr_out [18:13] <= r[7][5:0];
// $ C000- $ DFFF
3'b100: cpu_addr_out [18:13] <= 6’b111110; // Предпоследний банк
3'b101: cpu_addr_out [18:13] <= r[6][5:0];
// $ E000- $ FFFF - винаги последната банка
подразбиране: cpu_addr_out [18:13] <= 6’b111111;
endcase
// A12 в MMC3 изход е винаги както на входа, тя отива директно в паметта
cpu_addr_out [12] <= cpu_addr_in[12];
край
Сега CHR. Има такава схема:
Къде $ 8000 # 40 $ - то chr_mode. Тя получава както следва:
// CHR банкиране
винаги @ (*)
започвам
ако (ppu_addr_in [12] == chr_mode)
ppu_addr_out [17:10] <= ;
още
ppu_addr_out [17:10] <= r[2+ppu_addr_in[11:10]];
// Максималният размер на CHR MMC3 - 256 килобайта, така че А18 е винаги 0.
ppu_addr_out [18] <= 0;
край
Mirroring режим е описан само един ред. В зависимост от това ние затваряме изход патрон CIRAM A10 или до A10 на. или на A11:
възлага ppu_ciram_a10 = огледало. ppu_addr_in [11]. ppu_addr_in [10];
По-сложно. MMC3 може да генерира прекъсване, когато определена линия, очертана на екрана. Това е много полезно, както и игри често използват. Линия на екрана се разглеждат в светлината на магистрали A12 от PPU. Когато сигналът на A12 типични промени настройките от логическа 0 до логическа 1 само веднъж на линия, с изключение на краткосрочните преходи до 0. И те не трябва да приемем, че всичко е малко по-сложно:
// Enable прекъсва само когато A12 на ниско ниво
винаги @ (*)
започвам
ако (! irq_enabled)
започвам
irq_ready = 0;
IRQ <= 1’bZ;
сложи край на друго, ако (irq_enabled ! Irq_value)
irq_ready = 1;
иначе, ако (irq_ready irq_value)
IRQ <= 1’b0;
край
// Сам брояч
винаги @ (posedge ppu_addr_in [12])
започвам
ако (a12_low_time == 3) // ниско A12 време трябва да бъде най-малко три цикъла на процесора
започвам
ако ((irq_reload ! Irq_reload_clear) || (Irq_counter == 0))
започвам
irq_counter = irq_latch;
ако (irq_reload) irq_reload_clear <= 1;
сложи край на друг
irq_counter = irq_counter-1;
ако (irq_counter == 0 irq_enabled)
irq_value = 1;
още
irq_value = 0;
край
ако (! irq_reload) irq_reload_clear <= 0;
край
// ниско Време A12 трябва да е поне 3 цикъла на процесора
винаги @ (posedge м2, posedge ppu_addr_in [12])
започвам
ако (ppu_addr_in [12])
a12_low_time <= 0;
иначе, ако (a12_low_time <3)
a12_low_time <= a12_low_time + 1;
край
възлага cpu_wr_out = cpu_rw_in || ram_protect [6];
възлага cpu_rd_out =
cpu_rw_in;
възлага cpu_sram_ce =! (cpu_addr_in [14] cpu_addr_in [13] m2 romsel ram_protect [7]);
В действителност, да се съберат на патрона за всяка една конкретна игра е много проста, защото само най-необходимите елементи, необходими за инсталиране. Но за да се направи универсална касета много slozhnee.Esli настроен FPGA до 128 макроклетки, флаш 512 килобайти за PRG, флаш 512 килобайти за CHR, SRAM 32 килобайта за CHR, SRAM 32 килобайта като допълнителна памет, която се поддържа от батерия за захранване игри, които са в състояние да се спаси, а след това ще отидат за около 90% -95% от игрите. Шофиране zamorochennye получи доста дълго време ли ръчно да се направи на дъската за всичко. Между другото, при избора на компоненти, които не е необходимо да се забравя, че Famicom / Dendy pyativoltovye нива. Китайците са сега много често игнорират.
Първото преразглеждане на универсалната си патрон изглеждаше нещо като това:
Е, както и програма за запис на игри, разбира се, написа:
Както можете да видите, че не е толкова трудно, ако седнете за известно време и да разберат принципите на работа.