view vdp.h @ 1925:039553703c20

Don't apply address and cd register changes to the 'live' registers until pending flag is cleared, but do preserve the upper address bits in the latch. Fixes regression in Overdrive 2 while preserving fix to Mona in 344 bytes
author Michael Pavone <pavone@retrodev.com>
date Mon, 13 Apr 2020 20:43:25 -0700
parents 2d462aa78349
children c3c62dbf1ceb
line wrap: on
line source

/*
 Copyright 2013 Michael Pavone
 This file is part of BlastEm.
 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
*/
#ifndef VDP_H_
#define VDP_H_

#include <stdint.h>
#include <stdio.h>
#include "system.h"
#include "serialize.h"

#define VDP_REGS 24
#define CRAM_SIZE 64
#define SHADOW_OFFSET CRAM_SIZE
#define HIGHLIGHT_OFFSET (SHADOW_OFFSET+CRAM_SIZE)
#define MODE4_OFFSET (HIGHLIGHT_OFFSET+CRAM_SIZE)
#define MIN_VSRAM_SIZE 40
#define MAX_VSRAM_SIZE 64
#define VRAM_SIZE (64*1024)
#define BORDER_LEFT 13
#define BORDER_RIGHT 14
#define HORIZ_BORDER (BORDER_LEFT+BORDER_RIGHT)
#define LINEBUF_SIZE (320+HORIZ_BORDER) //H40 + full border
#define SCROLL_BUFFER_SIZE 32
#define BORDER_BOTTOM 13 //TODO: Replace with actual value
#define MAX_DRAWS_H32_MODE4 8
#define MAX_SPRITES_LINE 20
#define MAX_SPRITES_LINE_H32 16
#define MAX_SPRITES_FRAME 80
#define MAX_SPRITES_FRAME_H32 64
#define SAT_CACHE_SIZE (MAX_SPRITES_FRAME * 4)

#define FBUF_SHADOW 0x0001
#define FBUF_HILIGHT 0x0010
#define FBUF_MODE4 0x0100
#define DBG_SHADOW 0x10
#define DBG_HILIGHT 0x20
#define DBG_PRIORITY 0x8
#define DBG_SRC_MASK 0x7
#define DBG_SRC_A 0x1
#define DBG_SRC_W 0x2
#define DBG_SRC_B 0x3
#define DBG_SRC_S 0x4
#define DBG_SRC_BG 0x0

#define MCLKS_LINE 3420

#define FLAG_DOT_OFLOW     0x01
#define FLAG_CAN_MASK      0x02
#define FLAG_MASKED        0x04
#define FLAG_WINDOW        0x08
#define FLAG_PENDING       0x10
#define FLAG_READ_FETCHED  0x20
#define FLAG_DMA_RUN       0x40
#define FLAG_DMA_PROG      0x80

#define FLAG2_VINT_PENDING   0x01
#define FLAG2_HINT_PENDING   0x02
#define FLAG2_READ_PENDING   0x04
#define FLAG2_SPRITE_COLLIDE 0x08
#define FLAG2_REGION_PAL     0x10
#define FLAG2_EVEN_FIELD     0x20
#define FLAG2_BYTE_PENDING   0x40
#define FLAG2_PAUSE          0x80

#define DISPLAY_ENABLE 0x40

enum {
	REG_MODE_1=0,
	REG_MODE_2,
	REG_SCROLL_A,
	REG_WINDOW,
	REG_SCROLL_B,
	REG_SAT,
	REG_STILE_BASE,
	REG_BG_COLOR,
	REG_X_SCROLL,
	REG_Y_SCROLL,
	REG_HINT,
	REG_MODE_3,
	REG_MODE_4,
	REG_HSCROLL,
	REG_BGTILE_BASE,
	REG_AUTOINC,
	REG_SCROLL,
	REG_WINDOW_H,
	REG_WINDOW_V,
	REG_DMALEN_L,
	REG_DMALEN_H,
	REG_DMASRC_L,
	REG_DMASRC_M,
	REG_DMASRC_H
} vdp_regs;

//Mode reg 1
#define BIT_VSCRL_LOCK 0x80
#define BIT_HSCRL_LOCK 0x40
#define BIT_COL0_MASK  0x20
#define BIT_HINT_EN    0x10
#define BIT_SPRITE_8PX 0x08
#define BIT_PAL_SEL    0x04
#define BIT_MODE_4     BIT_PAL_SEL
#define BIT_HVC_LATCH  0x02
#define BIT_DISP_DIS   0x01

//Mode reg 2
#define BIT_128K_VRAM  0x80
#define BIT_DISP_EN    0x40
#define BIT_VINT_EN    0x20
#define BIT_DMA_ENABLE 0x10
#define BIT_PAL        0x08
#define BIT_MODE_5     0x04
#define BIT_SPRITE_SZ  0x02

//Mode reg 3
#define BIT_EINT_EN    0x10
#define BIT_VSCROLL    0x04

//Mode reg 4
#define BIT_H40        0x01
#define BIT_HILIGHT    0x8
#define BIT_DOUBLE_RES 0x4
#define BIT_INTERLACE  0x2

//Test register
#define TEST_BIT_DISABLE 0x40

typedef struct {
	uint16_t address;
	int16_t x_pos;
	uint8_t pal_priority;
	uint8_t h_flip;
	uint8_t width;
	uint8_t height;
} sprite_draw;

typedef struct {
	uint8_t size;
	uint8_t index;
	int16_t y;
} sprite_info;

#define FIFO_SIZE 4

typedef struct {
	uint32_t cycle;
	uint32_t address;
	uint16_t value;
	uint8_t  cd;
	uint8_t  partial;
} fifo_entry;

enum {
	VDP_DEBUG_PLANE,
	VDP_DEBUG_VRAM,
	VDP_DEBUG_CRAM,
	VDP_DEBUG_COMPOSITE,
	VDP_NUM_DEBUG_TYPES
};

typedef struct {
	system_header  *system;
	//pointer to current line in framebuffer
	uint32_t       *output;
	//pointer to current framebuffer
	uint32_t       *fb;
	uint8_t        *done_composite;
	uint32_t       *debug_fbs[VDP_NUM_DEBUG_TYPES];
	uint32_t       output_pitch;
	uint32_t       debug_fb_pitch[VDP_NUM_DEBUG_TYPES];
	fifo_entry     fifo[FIFO_SIZE];
	int32_t        fifo_write;
	int32_t        fifo_read;
	uint32_t       address;
	uint32_t       address_latch;
	uint32_t       serial_address;
	uint32_t       colors[CRAM_SIZE*4];
	uint32_t       debugcolors[1 << (3 + 1 + 1 + 1)];//3 bits for source, 1 bit for priority, 1 bit for shadow, 1 bit for hilight
	uint16_t       cram[CRAM_SIZE];
	uint32_t       frame;
	uint32_t       vsram_size;
	uint8_t        cd;
	uint8_t        cd_latch;
	uint8_t	       flags;
	uint8_t        regs[VDP_REGS];
	//cycle count in MCLKs
	uint32_t       cycles;
	uint32_t       pending_vint_start;
	uint32_t       pending_hint_start;
	uint32_t       top_offset;
	uint16_t       vsram[MAX_VSRAM_SIZE];
	uint16_t       vscroll_latch[2];
	uint16_t       vcounter;
	uint16_t       inactive_start;
	uint16_t       border_top;
	uint16_t       border_bot;
	uint16_t       hscroll_a;
	uint16_t       hscroll_a_fine;
	uint16_t       hscroll_b;
	uint16_t       hscroll_b_fine;
	uint16_t       h40_lines;
	uint16_t       output_lines;
	sprite_draw    sprite_draw_list[MAX_SPRITES_LINE];
	sprite_info    sprite_info_list[MAX_SPRITES_LINE];
	uint8_t        sat_cache[SAT_CACHE_SIZE];
	uint16_t       col_1;
	uint16_t       col_2;
	uint16_t       hv_latch;
	uint16_t       prefetch;
	uint16_t       test_port;
	//stores 2-bit palette + 4-bit palette index + priority for current sprite line
	uint8_t        linebuf[LINEBUF_SIZE];
	uint8_t        compositebuf[LINEBUF_SIZE];
	uint8_t        layer_debug_buf[LINEBUF_SIZE];
	uint8_t        hslot; //hcounter/2
	uint8_t	       sprite_index;
	uint8_t        sprite_draws;
	int8_t         slot_counter;
	int8_t         cur_slot;
	uint8_t        sprite_x_offset;
	uint8_t        max_sprites_frame;
	uint8_t        max_sprites_line;
	uint8_t        fetch_tmp[2];
	uint8_t        v_offset;
	uint8_t        hint_counter;
	uint8_t        flags2;
	uint8_t        double_res;
	uint8_t        buf_a_off;
	uint8_t        buf_b_off;
	uint8_t        pending_byte;
	uint8_t        state;
	uint8_t        cur_buffer;
	uint8_t        tmp_buf_a[SCROLL_BUFFER_SIZE];
	uint8_t        tmp_buf_b[SCROLL_BUFFER_SIZE];
	uint8_t        enabled_debuggers;
	uint8_t        debug_fb_indices[VDP_NUM_DEBUG_TYPES];
	uint8_t        debug_modes[VDP_NUM_DEBUG_TYPES];
	uint8_t        pushed_frame;
	uint8_t        vdpmem[];
} vdp_context;



vdp_context *init_vdp_context(uint8_t region_pal, uint8_t has_max_vsram);
void vdp_free(vdp_context *context);
void vdp_run_context_full(vdp_context * context, uint32_t target_cycles);
void vdp_run_context(vdp_context * context, uint32_t target_cycles);
//runs from current cycle count to VBLANK for the current mode, returns ending cycle count
uint32_t vdp_run_to_vblank(vdp_context * context);
//runs until the target cycle is reached or the current DMA operation has completed, whicever comes first
void vdp_run_dma_done(vdp_context * context, uint32_t target_cycles);
uint8_t vdp_load_gst(vdp_context * context, FILE * state_file);
uint8_t vdp_save_gst(vdp_context * context, FILE * outfile);
int vdp_control_port_write(vdp_context * context, uint16_t value);
void vdp_control_port_write_pbc(vdp_context * context, uint8_t value);
int vdp_data_port_write(vdp_context * context, uint16_t value);
void vdp_data_port_write_pbc(vdp_context * context, uint8_t value);
void vdp_test_port_write(vdp_context * context, uint16_t value);
uint16_t vdp_control_port_read(vdp_context * context);
uint16_t vdp_data_port_read(vdp_context * context);
uint8_t vdp_data_port_read_pbc(vdp_context * context);
void vdp_latch_hv(vdp_context *context);
uint16_t vdp_hv_counter_read(vdp_context * context);
void vdp_adjust_cycles(vdp_context * context, uint32_t deduction);
uint32_t vdp_next_hint(vdp_context * context);
uint32_t vdp_next_vint(vdp_context * context);
uint32_t vdp_next_vint_z80(vdp_context * context);
uint32_t vdp_next_nmi(vdp_context *context);
void vdp_int_ack(vdp_context * context);
void vdp_print_sprite_table(vdp_context * context);
void vdp_print_reg_explain(vdp_context * context);
void latch_mode(vdp_context * context);
uint32_t vdp_cycles_to_frame_end(vdp_context * context);
void write_cram_internal(vdp_context * context, uint16_t addr, uint16_t value);
void vdp_check_update_sat_byte(vdp_context *context, uint32_t address, uint8_t value);
void vdp_pbc_pause(vdp_context *context);
void vdp_release_framebuffer(vdp_context *context);
void vdp_reacquire_framebuffer(vdp_context *context);
void vdp_serialize(vdp_context *context, serialize_buffer *buf);
void vdp_deserialize(deserialize_buffer *buf, void *vcontext);
void vdp_force_update_framebuffer(vdp_context *context);
void vdp_toggle_debug_view(vdp_context *context, uint8_t debug_type);
void vdp_inc_debug_mode(vdp_context *context);
//to be implemented by the host system
uint16_t read_dma_value(uint32_t address);

#endif //VDP_H_