In this post I will describe how to load colors into Sega’s palette in assembler.
The final result in the Exodus emulator will look like this:
To make the process easier, find a pdf on the Internet called Genesis Software Manual (1989) , it describes the whole process in great detail, in fact, this note is a commentary on the original manual.
In order to write colors to the VDP chip of the Sega emulator, you need to do the following things:
- Disable TMSS protection system
- Write correct parameters to VDP registers
- Write the desired colors to CRAM
For the assembly, we will use vasmm68k_mot and our favorite text editor, for example echo. The assembly is carried out by the command:
vasmm68k_mot -Fbin minimal.asm -o minimal.gen
The VDP chip communicates with the M68K through two ports in RAM – the control port and the data port.
- VDP registers can be set through the control port.
- Also, the control port is a pointer to that part of the VDP (VRAM, CRAM, VSRAM etc.) through which data is transmitted through the data port
Interesting information: Sega retained compatibility with Master System games, as indicated by MODE 4 from the developer’s manual, in it VDP switches to Master System mode.
Let’s declare ports of control and data:
vdp_control_port = $ C00004 vdp_data_port = $ C00000
Disable TMSS protection system
Protection against unlicensed games TMSS has several unlocking options, for example, it is required that the string “SEGA” be in the A1 address register before accessing the VDP.
MOVE.B A1, D0; We get the version of the hardware with the number from A1 to register D0 ANDI.B 0x0F, D0; We take the last bits by the mask so as not to break anything BEQ.B SkipTmss; If the version is 0, most likely it is a Japanese woman or an emulator without TMSS enabled, then go to the SkipTmss sabrutina MOVE.L "SEGA" A1; Or write the string SEGA to A1
Write correct parameters to VDP registers
Why set the correct parameters in the VDP registers at all? The idea is that VDP can do a lot, so before rendering, you need to initialize it with the necessary features, otherwise it just won’t understand what they want from it.
Each register is responsible for a specific setting / mode of operation. The Segov manual contains all the bits / flags for each of the 24 registers, a description of the registers themselves.
Let’s take ready-made parameters with comments from the bigevilcorporation blog:
VDPRegisters: VDPReg0: dc.b $ 14; 0: H interrupt on, palettes on VDPReg1: dc.b $ 74; 1: V interrupt on, display on, DMA on, Genesis mode on VDPReg2: dc.b $ 30; 2: Pattern table for Scroll Plane A at VRAM $ C000 ; (bits 3-5 = bits 13-15) VDPReg3: dc.b $ 00; 3: Pattern table for Window Plane at VRAM $ 0000 ; (disabled) (bits 1-5 = bits 11-15) VDPReg4: dc.b $ 07; 4: Pattern table for Scroll Plane B at VRAM $ E000 ; (bits 0-2 = bits 11-15) VDPReg5: dc.b $ 78; 5: Sprite table at VRAM $ F000 (bits 0-6 = bits 9-15) VDPReg6: dc.b $ 00; 6: Unused VDPReg7: dc.b $ 00; 7: Background color - bits 0-3 = color, ; bits 4-5 = palette VDPReg8: dc.b $ 00; 8: Unused VDPReg9: dc.b $ 00; 9: Unused VDPRegA: dc.b $ FF; 10: Frequency of Horiz. interrupt in Rasters ; (number of lines traveled by the beam) VDPRegB: dc.b $ 00; 11: External interrupts off, V scroll fullscreen, ; H scroll fullscreen VDPRegC: dc.b $ 81; 12: Shadows and highlights off, interlace off, ; H40 mode (320 x 224 screen res) VDPRegD: dc.b $ 3F; 13: Horiz. scroll table at VRAM $ FC00 (bits 0-5) VDPRegE: dc.b $ 00; 14: Unused VDPRegF: dc.b $ 02; 15: Autoincrement 2 bytes VDPReg10: dc.b $ 01; 16: Vert. scroll 32, Horiz. scroll 64 VDPReg11: dc.b $ 00; 17: Window Plane X pos 0 left ; (pos in bits 0-4, left / right in bit 7) VDPReg12: dc.b $ 00; 18: Window Plane Y pos 0 up ; (pos in bits 0-4, up / down in bit 7) VDPReg13: dc.b $ FF; 19: DMA length lo byte VDPReg14: dc.b $ FF; 20: DMA length hi byte VDPReg15: dc.b $ 00; 21: DMA source address lo byte VDPReg16: dc.b $ 00; 22: DMA source address mid byte VDPReg17: dc.b $ 80; 23: DMA source address hi byte, ; memory-to-VRAM mode (bits 6-7)
Ok, now let’s go to the control port and write all the flags to the VDP registers:
PrepareToFillVDPRegisters: move.l # VDPRegisters, a0; We write the address of the parameter table in A1 move.l # $ 18, d0; Cycle counter - 24 = 18 (HEX) in D0 move.l # $ 00008000, d1; Preparing a command to write to the VDP register at index 0, according to the manual - 1000 0000 0000 0000 (BIN) = 8000 (HEX) FillInitialStateForVDPRegistersLoop: move.b (a0) +, d1; We write in D1 the total value of the VDP register from the parameter table, for sending to the VDP control port move.w d1, vdp_control_port; We send the final command + value from D1 to the VDP control port add.w # $ 0100, d1; Raise the VDP register index by 1 (binary addition +1 to the index according to Sega's manual) dbra d0, FillInitialStateForVDPRegistersLoop; Decrease the register counter, continue the loop if necessary
The most difficult thing is to read the manual and understand in what format the data is fed to the control port, experienced developers will figure it out right away, but inexperienced ones … They will think a little and understand that the syntax for writing registers is as follows:
0B100 (5 bits – register index) (8 bits / byte – value)
0B1000001001000101 – write to the VDP register 2 (00010), the value of the flags 01000101.
Write the desired colors to CRAM
Next, we go to write two colors into the color memory CRAM (Color RAM). To do this, write to the control port a command to access the color at index 0 in CRAM and send the color to the date port. Everyone!
VDPControlPortEnableCRAMWriteAccessGreenColorAtIndex0: move.l # $ C0000000, vdp_control_port; Access to color at index 0 in CRAM through the control port move.w # 228, d0; Color in D0 move.w d0, vdp_data_port; Sending color to data port
After building and running in the emulator in Exodus, you should have the screen filled with color 228.
Let’s fill with another color, last byte 127.
VDPControlPortEnableCRAMWriteAccessGreenColorAtIndex127: move.l # $ C07f0000, vdp_control_port; Access to color by byte 127 in CRAM through the control port move.w # 69, d0; Color in D0 move.w d0, vdp_data_port; Sending color to data port
https://huguesjohnson.com/programming/genesis/palettes/ < br />
https: / /blog.bigevilcorporation.co.uk/2012/03/09/sega-megadrive-3-awaking-the-beast/