Entendendo o chip mapper do master system.

Dentre os consoles da década de 80 e 90, o Master System da Sega é um ótimo ponto de partida para aqueles que desejam aprender sobre mappers e cartuchos de consoles retro.

A utilização do processador Z80 possibilitou dispor de todo o barramento de endereço para o cartucho, abrindo muitas possibilidades para configuração de memória no cartuchos.

A maioria dos jogos produzidos para esse console, utiliza de chip mapper para aumentar o espaço de memória que pode ser gerenciado pelo console e nesse post, vamos entender o funcionamento de um Chip Mapper para o master system com suporte a memória de até 512 Kilobytes.

1 - Protótipo

Vídeo curto do protótipo em funcionamento.

Para o teste de bancada foi utilizado uma memória AM29F040 de 512kB e uma CPLD EPM3064, desmontei uma pcb original da tectoy para utilizar nos testes.

2 - Seleção do chip mapper.

Embora nos estes em protoboard tenha sido utilizado o EPM3064, na pcb versão final foi utilizado o XC9572XL versão com 64 pinos. A escolha desse chip foi por custo, número de pinos e disponibilidade no mercado, tendo macrocell de sobra para utilização no mapper do sms.

3 - Lógica de funcionamento

Na implementação lógica do chip mapper, o endereçamento total de $FFFF do Z80 foi dividido em 4 slots de $4000 bytes, sendo os três primeiros utilizados pelo mapper e o quarto e último sendo reservado para memória interna do console.

Registradores foram utilizados para parametrização do mapper, que ocorre durante uma escrita nos seguintes endereços: $FFFC, $FFFD, $FFFE e $FFFF. Esses endereços estão mapeados na região do quarto slot $C000-$FFFF, região destinada a memória interna do console, e por este motivo, mesmo que o mapper não implemente a leitura desses registradores, uma tentativa de leitura retornará o último valor escrito, pois a memória interna irá conter o valor.

Para controlar o acesso a memória de salve, utiliza-se o registrador no endereço $FFFC, no chip mapper oficial da SEGA é utilizado vários bits, porém aqui por simplicidade usaremos apenas um bits. Quando o bit 4 desse registrador está em nível lógico 1, a memória de salve fica disponível para acesso no endereço $8000-$BFFF, comumente chamado de slot 2, não permitindo acesso a memória ROM. Para preservar o vetor de interrupção que fica localizado no início do primeiro banco da memória rom, não é possível mover o registrador $FFFD fora do banco 0, desse modo, todos os acessos no slot 0 $0000-$3FFF retorna os primeiros 16384 bytes da memória ROM. No mapper original apenas os $01FF do banco é fixo e não o banco todo.

Os demais registradores $FFFE e $FFFF representam os slots 1 e 2 respectivamente, onde parte da memória ROM pode ser mapeada, permitindo ao console acessar $4000 bytes, e dessa forma superar o limite de 65536 bytes imposto pelo espaço de endereçamento do processador Z80.

4 - Codificação

O código para descrição do comportamento do mapper foi elaborado em VHDL, segue alguns trechos abaixo: O mapper pode ser dividido em 3 partes, registrador, seletor do slot e em caso de cart com salve, ram / rom select. Array para armazenar o valor atual do mapper contido nos registradores internos do mapper, vale lembrar que esses valores também estarão na sram interna do console.

signal slot1 : std_logic_vector(4 downto 0);
signal slot2 : std_logic_vector(4 downto 0);
mapAddress   : std_logic_vector(4 downto 0);
ram_enable   : std_logic;

Uma escrita ocorre no falling edge do we, faz-se necessário a utilização da checagem do pino ce já que o z80 utiliza o mesmo barramento e pino we/oe para acesso a memória rom/sram e dispositivos I/O tais como video, joystic etc…, diferenciando apenas pela utilização do pino ce para quando acessa memoria rom e sram região do cartucho.

if (rst = '0') then 
  slot1 <= "00001"; 
  slot2 <= "00010"; 
  ram_enable <= '0'; 
elsif falling_edge (we) then
if ce = '0' then
case smsAddr(15 downto 14) is
when x"FFFC" => ram_enable <= smsData(3);
when x"FFFE" => slot1 <= smsData(4 downto 0);
when x"FFFF" => slot2 <= smsData(4 downto 0); ... ...

A escolha do slot, ocorre de forma automática, sendo indexado pelas pinos de  endereço A15~A14:

  • 00 slot0
  • 01 slot1 
  • 10 slot2
  • 11 SRAM interna
  ...
case smsAddr(15 downto 14) is
  when "01" => mapAddress <= slot1; 
when "10" => mapAddress <= slot2; ... end case;

Por ultimo, temos a seleção entre rom e ram:

process(smsAddr, ram_enable, smsCE)
begin
  romCE <= '1';
  ramCE <= '1'; 
case smsAddr(15 downto 14) is
when "00" => romCE <= smsCE;
when "01" => romCE <= smsCE; ... ...

5 - Esquemático

Durante a escolha do CPLD foi levado em consideração a necessidade de trabalho com potencial de 5.0V, embora o XC9572XL tenha core de 3.3V, ele é totalmente tolerante a input de 5.0V, e por este motivo foi utilizado no projeto. Já a memória rom, foi utilizado a flash 29F040 que funciona em 5.0V e para memória de salve temos duas possibilidades, a primeira é utilização de FM1808, uma memória FRAM sem a necessidade do uso de bateria, já na segunda, uma SRAM simples 62256 com uso de bateria.

6 - Placa de circuito impresso

A pcb do sms é pequena, mas não foi problema rotear os componentes na pcb, na parte de cima há pinos para programação da CPLD na placa, na parte de traz, jumps para seleção entre SRAM e FRAM.

7 - Conclusão

Agora você sabe como funciona um chip mapper para o Sega Master System.

Esse projeto foi melhorado e agora é possível rodar até 16mbits de rom, embora não conheça nenhum jogo maior que 8mbits, fica como opção aos novos desenvolvedores de jogo.

Em breve, você poderá adquirir a pcb, o arquivo de gravação da cpld e até mesmo o projeto inteiro na minha loja, aguarde. Disponível em: Projeto Cartucho Master System

Agora que concluir a escrita desse post, vou iniciar a escrita do post de um cartucho de Master System com SDcard e 8mbits de SRAM estilo Everdriver, aguardem.

Ah! É possível que você já tenha visto essa pcb em cartuchos vendidos de 2019 pra cá, deixa nos comentários sua experiência com essa placa.

8 - Referências

Comentários