Engenharia Reversa do Mega Drive Portátil da TecToy

Recentemente, por conta das notícias sobre o novo Mega Drive que a TecToy vai lançar no Brasil, acabei descobrindo a existência de um produto anterior, lançado na década passada: o MDPLAY. Trata-se de uma versão portátil do Mega Drive que, além de já vir com alguns jogos na memória interna, permite também carregar jogos a partir de ROMs salvas em um cartão SD. E a tela é um LCD colorido de 320x240 pixels.

Fiquei empolgado com a possibilidade de usar o cartão SD para carregar jogos, pois isso facilitaria a criação de jogos homebrew sem precisar usar um cartucho de desenvolvimento (everdrive) ou ter que gravar EPROMs. Vi alguns vídeos no YouTube e notei que o portátil possui um menu de seleção de jogos e logo minha cabeça já começou a rodopiar tentando entender se o menu também é um programa rodando na CPU do megadrive (Motorola 68000) ou se seria feito de alguma outra forma.

Depois de muito buscar, descobri que existem muitos consoles como esse da TecToy sendo vendidos com as mais diversas marcas ao redor do mundo. Aparentemente alguém projetou e fabricou o sisteminha na Ásia e várias outras empresas meramente “empacotaram” o produto com seu branding local. Por dentro todos esses aparelhos são muito parecidos entre si:

Minha meta inicial era conseguir um dump da ROM interna do console para eu poder analizar o arquivo binário. Como não achei nada na internet, resolvi comprar o meu próprio MDPLAY no Mercado Livre. Mas enquanto o produto não chegava, eu acabei achando um fórum gringo onde um cara dizia ter feito o dump de um aparelho similar chamado DCAT16:

http://gendev.spritesmind.net/forum/viewtopic.php?t=2460

Uma informação curiosa dessa postagem foi o fato da ROM extraída funcionar parcialmente em emuladores. Fiz o download do arquivo e testei eu mesmo no MAME. E, de fato, consigo ouvir música e quando pressiono os botões, percebo efeitos sonoros. A tela, entretanto, permanece toda preta, exceto em raros momentos em que pode-se ver alguns bloquinhos coloridos piscando, mas com os gráficos completamente corrompidos. Não dá pra identificar nenhum elemento do jogo no MAME.

Então a minha conclusão foi de que a implementação do chip de vídeo do MDPLAY é retro-compatível com o MegaDrive original, mas inclui um modo de vídeo adicional com algum tipo de vantagem em relação ao legado. Imagino que tenham criado isso para poderem ter uma maior profundidade de bits na paleta de cores e, com isso, implementar um menu de seleção “mais bonito” pros critérios de qualidade dos usuários de hoje em dia. :smiley:

Bem… parece que arranjei mais uma sarna pra me coçar! Alguém (eu?) precisa implementar suporte a esse novo modo de vídeo no MAME para que o MDPLAY possa ser emulado corretamente! A seguir vou mostrar o passo a passo da minha abordagem para esse desafio.

Pra começo de conversa, se eu quero entender como funciona o novo modo de vídeo, eu preciso antes entender como se programa o vídeo de um megadrive tradicional. Imagino que qualquer coisa nova deve herdar diversas características similares em relação ao que veio antes. Dito isso, comecei a estudar o VDP (video display processor) do Mega. Tem um documento muito bom sobre isso aqui:

http://md.squee.co/VDP

Um conceito fundamental sobre como funciona o vídeo do Megadrive é o fato das imagens de fundo serem montadas por meio de um arranjo de “tiles” (blocos) de 8x8 pixels cada. Então, como a tela tem resolução 320x240, isso significa que ela é formada por 30 faixas de 40 blocos cada. Ou seja, na horizontal, 40 blocos de 8 pixels de largura formam os 408 = 320 pixels de largura da tela. O mesmo raciocínio pode ser feito na vertical, onde 30 blocos de 8 pixels de altura compõem as 308=240 linhas da tela.

Então existe uma região da memória RAM de vídeo (VRAM) onde são armazenados os desenhos de cada um dos bloquinhos disponíveis. E numa outra região da VRAM é escrito o “tilemap”, ou seja, uma sequência de números selecionando qual bloquinho é exibido em cada parte da tela. Então efetivamente esse tipo de abordagem se assemelha muito a um quebra-cabeças, onde juntamos peças para formar uma imagem. Com a diferença que podemos usar várias vezes a mesma peça, caso a imagem que queremos exibir contenha repetições. E está justamente aí a razão pela qual se usava esse tipo de técnica em muitos computadores antigos, consoles de video game e máquinas de fliperama: com isso é possível economizar espaço em memória (que era um item escasso e caro naquela época).

Além disso, no Mega Drive original os desenhos de cada um dos tiles ocupavam 32 bytes. A razão para tal é que cada pixel usava 4 bits para determinar sua cor. Um bloco de 8x8 pixels tem um total de 64 pixels e, portanto, 64*4 = 256 bits de informação, o que corresponde a 256/8 = 32 bytes. Com 4 bits por pixel (4 bpp) temos 16 combinações possíveis (2 elevado à 4ª potência dá 16). Isso significa que cada pixel podia ter uma de 16 opções de cores de uma paleta selecionada de uma outra forma que não vem ao caso aqui. O importante é não esquecer que cada 32 bytes de uma certa região da memória RAM de vídeo, corresponde ao desenho de um bloquinho, e que cada bloquinho pode usar 16 cores.

Bom… e como é que funciona no modo de video novo do MDPLAY? Bem… a priori eu não sei, mas vamos descobrir na marra!

Pouca gente sabe, mas o MAME oferece um debugger que permite inspecionar a execução dos jogos passo-a-passo, na linguagem assembly dos processadores usados em cada máquina. Além disso, permite também o registro de breakpoints (endereços em que a execução é automaticamente interrompida para analizarmos algo de interesse), watchpoints (monitoramento de acessos a endereços específicos de memória) e várias outras coisas super úteis como as janelas de visualização do conteúdo da memória (é como um editor hexadecimal, mas o conteúdo pode ser observado dinamicamente conforme o programa está sendo executado no emulador).

Usando essas ferramentas eu pude notar que logo no início do programa, o jogo configura algumas transferências de dados via DMA (direct memory access). Para ver exatamente em quais endereços os dados estavam sendo escritos eu fiz uma pequena modificação no código-fonte do MAME, para ele imprimir no console de texto um log contendo: (1) tamanho do bloco de dados a serem transferidos via DMA e (2) endereço de destino onde os dados serão armazenados.

E o resultado foi muito bom: observei 30 transferências com 40 entradas de dados cada. De imediato saquei que se tratam dos 40x30 blocos de uma tela! Observando os valores na janela de inspeção de conteúdo da VRAM, notei que eles ocupam a região de memória começando no endereço 0x4000, mas também há valores não-nulos em outras regiões da memória. Oras… alguma dessas outras regiões deve corresponder aos desenhos dos bloquinhos. Em particular, a partir do endereço 0x0000 da VRAM, temos uma sequência de valores um tanto peculiar (e que também foram armazenados alí logo no começo do programa via DMA):

As 3 primeiras linhas dessa janela correspondem a 48 bytes com o valor zero (00). Minha intuição diz que isso tudo corresponde ao desenho do primeiro bloquinho (bloco #0) que deve ser inteiro preto e deve ser usado para não mostrar nada na tela em determinadas situações. Se forem realmente 48 bytes por bloco, então isso significa um total de 488 = 384 bits. E com 88 pixels, temos 384/64 = 6 bits por pixel. (e já adianto que essa interpretação se mostrou correta no fim das contas!)

Agora resta a questão: como estão organizados esses dados? A forma óbvia e canônica seria armazenar a cor do pixel x:0, y:0 nos primeiros 6 bits (ou seja, 75% do primeiro byte) e então o segundo pixel teria sua cor armazenada nos 2 bits restantes do primeiro byte e em metade (4 bits) do segundo byte. E assim por diante. Fiz um programinha em python para interpretar essa sequência de valores da VRAM segundo esse critério de decodificação, mas não resultou em nada que parecesse fazer sentido visualmente. Concluí que os dados devem estar embaralhados.

Para confirmar (ou refutar) a minha teoria de que são usados 48 bytes por tile, eu resolvi partir para uma inspeção do comportamento do dispositivo de verdade. Eu precisaria alterar a ROM para enviar dados diferentes para a VRAM e então observar o que aparece na tela e tentar concluir qual é a relação entre os dados e os pixels exibidos. Usando um editor hexadecimal (o hexdump, via linha de comando) eu consegui achar a sequência “10 81 41 08 0C 30 …” armazenada a partir do endereço 0x8d9e6 da ROM:

Os 48 bytes nulos correspondem a um bloco preto e os primeiro 48 bytes não nulos são o desenho do bloco #1. Escrevi um pequeno programa em python para escrever zero em todo o bloco #1, carreguei a ROM resultante no MDPLAY por meio do cartão SD e o resultado foi:

Toda essa região preta corresponde a múltiplos usos do tile #1. Provavelmente por que é toda a região de céu limpo (sem nuvens) na imagem. Restaurei a ROM original e repeti o procedimento sobrescrevendo então os dados do bloco #2, e o resultado foi:

Mais interessante! Parece que esse pedaço da imagem tem um padrão de cores único. O tile #2 é usado apenas nessa posição. Esse parace ser nosso melhor setup para começar a tentar desvendar como está organizada a estrutura de dados da imagem de um bloquinho.

Escrevi um outro script python que preenche o bloco com valor zero, exceto em um bit especifico em cada linha.

Foram geradas 6 ROMs. Cada ROM posiciona bits 1 em cada uma das 8 posições de cada um dos 6 bytes que formam uma linha de um tile. Usei um microscópio-USB para ver em detalhes o resultado de cada um desses blocos de dados. Esse é o meu setup:

Seguem abaixo cada um dos blocos de dados das 6 ROMs de teste e as fotografias correspondentes:

Com base nesses testes é obvio que (não, não é óbvio! Eu levei umas 3 horas pra entender esse negócio!) o layout dos blocos segue esse padrão:

Com isso consegui escrever um outro script python que desenha um triângulo e um padrão xadrez no bloquinho usando duas cores (azul celeste e vermelho escuro):

A parte relevante desse código é a função patch_rom:

E o trecho que de fato codifica os valores dos pixels:

O próximo passo foi fazer um decoder para visualizar no PC os desenhos dos bloquinhos. E depois descobrir onde na ROM fica o tilemap e também fazer um visualizador para a imagem completa. Mas isso fica pruma próxima postagem, por que ainda não está pronto. Deixo aqui apenas um teaser de como está (pela metade) o decodificador de frame completo. Note que a paleta de cores está incorreta:

Happy Hacking,
Felipe “Juca” Sanches

5 curtidas

Consegui hoje pela manhã identificar o formato de dados da paleta de cores, o endereço dentro da ROM onde a paleta da primeira tela é armazenada e o método de upload da paleta para o VDP (o método de upload é identico ao usado no Mega Drive clássico, o resto é tudo diferente).

Pretendo fazer um relato detalhado de qual foi a técnica que usei pra desvendar essa parte do sistema, mas por enquanto vou apenas postar aqui um novo screenshot do meu script python que renderiza os gráficos desse novo modo de vídeo usado no MDPLAY:

A paleta tem 64 cores e cada cor é definida por um valor de 32 bits sendo 8 bits de vermelho, 8 bits de verde e 16 bits de azul. Achei um pouco exagerada a quantidade de bits. É bem possível que metade dos bits do azul sejam no fim das contas ignorados. Mas os dados estão lá com essa resolução na tabela de cores da paleta. Depois eu conto mais!

Happy Hacking,
Felipe “Juca” Sanches

4 curtidas

Que baita trabalho de engenharia reversa, @FSanches ! Gosto também do jeito didático como vc descreve o processo todo. Me bateu uma baita saudade dos meus projetinhos lendo essa postagem toda. Abraços!

1 curtida

Segue abaixo um relato das técnicas que usei para descobrir como funciona a configuração de paleta de cores deste modo de vídeo.

Visão geral sobre os mecanismos de acesso à VRAM

O VPD (video display processor) do Mega Drive possui memória RAM própria onde são armazenados dados das imagens a serem exibidas. Entre esses dados há uma região denominada CRAM (Color RAM) que guarda os valores de intensidade de vermelho, verde e azul de cada uma das cores disponíveis na paleta.

Em alguns modelos de computador, periféricos mapeiam sua memória dedicada em um intervalo de endereços do espaço de endereçamento da CPU principal do sistema. É isso que ocorre, por exemplo, com a memória de vídeo de placas VGA em um IBM-PC: toda a região de alguns kbytes a partir do endereço 0xA0000 no barramento do processador x86 corresponde à memória de vídeo da placa VGA e não a RAM genérica do sistema.

Já no caso do Mega Drive isso é feito de uma forma diferente. Ao invés de toda a memória do VDP ser disponibilizada em um bloco de endereços do Motorola 68000, o que acontece de fato é que existe apenas um par de endereços usado como canal de comunicação entre a CPU e o VDP. Esses endereços são 0xC00000 para a porta de dados e 0xC00004 para a porta de comandos.

Para escrever algo na memória interna da VDP, o procedimento básico é escrever o endereço desejado na porta de dados e, em seguida, o valor a ser armazenado é escrito na porta de comandos. Um detalhe a mais é o fato de existirem vários tipos de memória interna no VDP como VRAM (tilemaps e os gráficos de cada tile em si), VSRAM (dados para scrolling vertical) e CRAM (dados da paleta de cores). Então além de fornecer o endereço, precisamos também selecionar o tipo de memória desejada. Ambas informações são definitas na porta de dados, seguindo o formato descrito abaixo:

Fonte: http://md.squee.co/VDP

Os 16 bits com nomes de A00 até A15 indicam o valor do endereço, enquanto os 6 bits denominados pela sigla CD selecionam o tipo de memória segundo a seguinte regra:

Fonte: http://md.squee.co/VDP

Sendo assim, para selecionar a operação de escrita no endereço zero da memória CRAM, os bits CD precisam ser 000011 e todos os demais devem ser zero. Isso corresponde (segundo o formato descrito acima) ao valor 11000000 00000000 00000000 00000000, que é 0xC0000000 em notação hexadecimal.

ATENÇÃO! Eu sei que esses valores são bem confusos por que são, coincidentemente, muito parecidos. Mas essas são coisas completamente distintas e indepentendes:

  • Endereço 0xC00000 da CPU Motorola 68k => porta de dados do VDP

  • Valor 0xC0000000 escrito na porta de comandos do VDP => Seleção do endereço 0x0000 da CRAM

Desvendando a paleta de cores

Partindo da suposição de que a carga de paleta de cores no modo de vídeo novo do MDPLAY deve seguir procedimento similar à do Mega Drive original, utilizei um comando muito bem elaborado para registrar um watch-point no debugger do MAME:

wpset C00004,1,w, wpdata==C000

O significado deste comando é:

  • Pause a execução do emulador no momento em que a posição de memória C00004 da CPU principal (Motorola 68k) receber uma escrita de dado. (ou seja, uma escrita na porta de comandos do VDP)
  • Desde que o dado que está sendo escrito comece com o valor C000 (ou seja, é uma seleção de endereço da CRAM)

A primeira vez que a execução é interrompida é logo no comecinho do programa, quando a paleta de cores está sendo inicializada com um monte de zeros (que podemos supor que correspondam à cor preta):

Veja aqui uma análise detalhada desta parte do programa
26E: moveq  #$1F, D3
270: move.l D0, (A3)
272: dbra   D3, $270

Esta é uma estrutura clássica de loop utilizando a instrução dbra (decrement and branch) onde o registrador D3 (inicializado com o valor 0x1F = 31) define a quantidade de vezes que o loop será executado (contando de 0x00 a 0x1F temos 32 loops).

Como o registrador D0 nesta circunstância vale zero e o registrador A3 vale 0x00C00000, a instrução move.l D0, (A3) está fazendo a escrita do valor zero na porta de dados do VDP.

Ou seja, 32 valores nulos são escritos no início da CRAM, deixando a paleta cheia de cores repetidas (cor preta, sendo R=0, G=0 e B=0).

Precisamente como as informações de vermelho, verde e azul são codificadas nós ainda não sabemos a essa altura, mas como o valor é mulo em todos os bits, dá pra fazer o palpite com uma certa segurança de que a cores resultantes terão 0% de intensidade em todas as suas componentes.


Por serem todas as cores inicializadas com zero, este não é ainda o melhor local para desvendarmos a estrutura dos dados da paleta de cores. Então minha estratégia foi soltar a emulação (pressionando a tecla F5) até que uma próxima escrita na CRAM seja detectada:

O novo trecho também contém uma rotina que envia zeros para a CRAM, mas dessa vez trata-se de um loop maior (executado 0x400 = 1024 vezes). Vamos ver qual é a próxima rotina então. Pressinando F5 mais uma vez, o emulador finalmente prossegue sua execução até encontrar esse código:

Essa é a rotina que contém a resposta para a nossa pergunta. Como está já muito tarde vou dormir. Mas em breve faço mais uma postagem destrinchando essa parte do código e explicando o que exatamente ele faz. Por enquanto, divirtam-se com o desafio! :smiley:

Happy Hacking,
Felipe “Juca” Sanches

1 curtida


5890: move.l #$c0000000, $c00004.l
589A: moveq #$0, D1
589C: move.l D1, D0
589E: lsl.l #2, D0
58A0: move.l (A2,D0.l), D0
58A4: and.l D2, D0
58A6: move.l D0, (A3)
58A8: addq.l #1, D1
58AA: cmpi.l #$1ff, D1
58B0: ble $589c

Esse código é equivalente a:

#define VDP_DATA_PORT 0xC00000
#define VDP_CMD_PORT 0xC00004
#define CRAM_WRITE(addr) ((0b11 << 30) |
                          ((addr & 0x3FFF) <> 14))

#define PALETTE_DATA 0xFFB5A0 //Endereço armazenado no registrador A2

*(VDP_CMD_PORT) = CRAM_WRITE(0x0000);
uint32 index = 0; //registrador D1
uint32 color_value; //registrador D0
uint32 mask_value = 0x01010001;
loop:
color_value = PALETTE[4*index] & mask_value;
*(VDP_DATA_PORT) = color_value;
index += 1;
if (index <= 0x1FF) goto loop;

O trecho de código acima nos diz que os dados da paleta de cores têm um total de 512 valores de 32bits, dado que o loop é executado 512 vezes (de 0x000 até 0x1FF) e a cada loop um valor de 32bits é escrito na CRAM (color RAM). Pra mim isso soa um pouco estranho dado que, com 6 bits por pixel, deveríamos ter 64 cores na paleta. Se cada cor ocupar 32 bits, teremos 512 cores. Suponho então que haja 8 paletas de 64 cores de 32 bits cada. Mas, se for isso mesmo, não tenho a menor idéia de como uma das 8 paletas é selecionada.

O pulo do gato dessa rotina está naquele valor misterioso 0x01010001.

Soltei a execução do emulador e reparei que ele cai novamente nessa rotina, mas com um valor de máscara diferente: 0x03030003. E depois, a cada nova execução da rotina, é usado um outro valor. Segue abaixo a lista de todos os valores de máscara utilizados em execuções sucessivas dessa rotina:

0x01010001
0x03030003
0x07070007
0x0F0F000F
0x1F1F001F
0x3F3F003F
0x7F7F007F
0xFFFF01FF
0xFFFF03FF
0xFFFF07FF
0xFFFF0FFF
0xFFFF1FFF
0xFFFF3FFF
0xFFFF7FFF
0xFFFFFFFF

O que esta sucessão de valores faz é, basicamente, converter as cores da paleta de modo a criar um efeito de fade-in. A primeira máscara pega apenas o bit menos relevante de cada componente de cor e zera o resto. O segundo valor de máscara preserva apenas os 2 bits menos significativos. E assim por diante, até que todos os 8 bits de cada componente de cor sejam enviados por completo para o VDP.

Com isso, conseguimos perceber que há um valor de 8 bits no primeiro byte, outro no segundo e outro no quarto. Só depois que foi feito o fade-in nesses 3 valores é que as máscaras fazer o “fade-in” do valor do byte 3. Eu não sei o que é esse valor. Inicialmente achei que ele fosse uma extensão para 16 bits da componente d ecor do byte 4. Mas depois algumas pessoas me sugeriram a hipótese de que esse pode ser um canal alfa (indicando transparência). Vai levar um tempo até eu determinar o que é realmente o significado desse valor.

Minha primeira suposição quando aos bytes 1, 2 e 4 era de que eles correspondiam, respectivamente às componentes R, G e B (vermelho, verde e azul). Mas depois percebi que na verdade a sequencia usada é G, R e B. E foi com essa interpretação dos valores (e usando a paleta número zero das 8 disponíveis) que eu consegui decodificar por completo o splash screen do jogo “Cross The Road” como visto na imagem que postei alguns dias atrás.

Happy Hacking,
Felipe “Juca” Sanches

Atualização rápida

Ao longo dessa semana passada eu iniciei a implementação de um driver de emulação do MDPLAY no MAME. Não está perfeito ainda (óbvio!) mas já dá pra ver as telas de fundo dos jogos com alguns glitches que ainda não consegui diagnosticar:

Também escrevi um script que codifica um PNG de 64 cores e sobrescreve a imagem do jogo Cross The Road. Veja na imagem abaixo um exemplo da ROM alterada rodando no MDPLAY com uma nova imagem de fundo:

Happy Hacking!
Felipe “Juca” Sanches

Sobre o script codificador de imagens

Para testar o script codificador de imagens eu utilizei a imagem do GNU tocando flauta. Essa imagem é famosa entre os usuários de GNU/Linux e ativistas de software livre:

Eu só espelhei o GNU, pra colocá-lo do lado esquerdo da tela, usei um fundo branco de 320x240 pixels posicionando o GNU no cantinho e converti a imagem para PNG de 64 cores usando o GIMP. Depois meu script python codificou a imagem de acordo com a estrutuda de dados dos tiles do VDP extendido do MDPLAY e, então, fez o patch binário na ROM do joguinho “Cross the Road”.

inicialmente eu ia usar uma imagem que ocupasse a tela toda, uma fotografia de um passarinho qualquer. Mas o resultado codificado excedia o espaço disponível na ROM do jogo e iria provavelmente sobrescrever trechos de código executável do jogo. Se eu estivesse fazendo do zero meu próprio jogo acho que seria OK usar uma imagem qualquer de minha escolha, pois eu poderia alocar na ROM todo o espaço necessário para tal.

Mas nesse caso, a área da ROM alocada para o splash screen original do “Cross the Road” limitou a complexidade da imagem que podemos colocar no lugar dela. Usando um fundo majoritariamente branco, eu uso o mesmo bloquinho branco em toda a tela, exceto no desenho do GNU no canto inferior esquerdo. O resto dos desenhos que você vê alí são parte do segundo plano de tiles, que eu não alterei, até mesmo por que ainda não tenho certeza de como funciona.

Provavelmente o segundo plano deve ser codificado de forma idêntica ao primeiro sendo apenas armazenado em um endereço de memória diferente na VRAM. Existem registradores que apontam esses endereços, então não deve ser difícil de implementar esse próximo passo de renderização no emulador. Um bônus provável é que ao desenhar a segunda camada vamos ter que lidar com o conceito de transparência. E aí talvez de uma vez por todas eu possa confirmar (ou refutar) a teoria de que o quarto byte na codificação de cores corresponde a um canal alfa (opacidade).

Assim que eu fizer esses próximos testes, postarei por aqui, com certeza.

Happy Hacking!
Felipe “Juca” Sanches

Adicionei ao emulador a renderização da segunda camada de tiles. Ainda não lidei com a questão do possível canal alfa na paleta. Em vez disso, simplesmente determinei que a segunda camada deve apenas desenhar um pixel caso o índice da cor seja não-nulo. O resultado obtido foi razoável:

Dá pra ver que a segunda camada também sofre com alguns glitches e que sua paleta de cores está errada. Tentei rapidamente trocar para uma das outras 8 paletas disponíveis, mas ainda não obtive sucesso.

De passo em passo tenho certeza que cedo ou tarde eu consigo desvendar por completo como isso tudo funciona…

Consegui achar as paletas de cores do segundo plano de tiles tanto da tela de abertura quanto da tela de jogo. O tilemap do fundo usa a paleta número zero em ambos os casos. Já o segundo plano usa a paleta número 1 para a tela de abertura, exibindo o título do jogo (“Cross The Road”) e a nuvem onde aparece a mensagem “press start”, mas não a mensagem em si, que talvez seja desenhada usando sprites, que eu ainda não estou renderizando:

E a paleta número 2 é usada para o segundo plano de tiles da tela do jogo em si, exibindo os elementos gráficos indicando quantidade de vidas restantes, pontuação, contagem regressiva do tempo de jogo, e as mensagens “LEVEL 1”, “READY” e “GAME OVER”:

Dado que em cada circunstância uma paleta diferente pode ser utilizada, isso significa que precisamos ter um mecanismo de configuração para selecionar a paleta desejada. Tipicamente isso é feito pro meio de escrita em registradores do VDP. Observei os valores dos registradores do VDP usando o debugger do MAME e os valores não mudam entre a tela de abertura e a tela do jogo. Portanto o mecanismo deve ser outro. Talvez exista algum registrador mapeado direto no espaço de endereçamento do Motorola 68000. Vou continuar investigando…

Publiquei hoje um vídeo no meu canal do YouTube contando um pouco sobre esse projeto. A maior parte das coisas que eu menciono no vídeo já foram discutidas em mais detalhes por aqui, mas tem uma coisa ou outra que deve ser novidade. E o vídeo serve também como um resumão do que rolou até agora:

Happy Hacking Video Blog

Episódio #006 - Destrinchando o MDPLAY

Insight

Ao que tudo indica, o tilemap está sobrescrevendo os padrões dos bloquinhos.
Há suspeitas de que o VDP do MDPLAY tenha um barramento interno de 32
bits para a VRAM. Então, ao invés de fazer transferências DMA com o
dobro do tamanho do intervalo de endereços, talvez a solução correta
seja usar o mesmo intervalo de endereços do DMA do mega-drive original,
mas com dados de 32 bits em vez de 16 bits por posição de memória.