/*
 * Copyright (c) 2021-2023 Rupert Carmichael
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef SMSVDP_H
#define SMSVDP_H

#define SMS_VDP_WIDTH           256
#define SMS_VDP_HEIGHT          192
#define SMS_VDP_HEIGHT_EXT1     224
#define SMS_VDP_HEIGHT_EXT2     240
#define SMS_VDP_SCANLINES       262
#define SMS_VDP_SCANLINES_PAL   313

#define SMS_VDP_QUIRK_SMS1VDP  0x01
#define SMS_VDP_QUIRK_FRINT    0x02
#define SMS_VDP_QUIRK_PHOFFSET 0x04

#define GG_VIEWPORT_WIDTH       160
#define GG_VIEWPORT_HEIGHT      144
#define GG_XOFFSET               48
#define GG_YOFFSET               24
#define GG_YOFFSET_EXT           40

#define SIZE_VRAM 0x4000
#define SIZE_CRAM 0x40

typedef struct _smsvdp_t {
    uint8_t vram[SIZE_VRAM]; // 16K VRAM
    uint8_t cram[SIZE_CRAM]; // 32 byte (SMS) or 64 byte (GG) CRAM
    uint16_t tbl_col; // Address for Colour table
    uint16_t tbl_pgen; // Address for Pattern Generator table
    uint16_t tbl_pname; // Address for Pattern Name table
    uint16_t tbl_sattr; // Address for Sprite Attribute table
    uint16_t tbl_spgen; // Addresss for Sprite Generator table
    uint16_t line; // Line currently being drawn
    uint16_t cyc; // Master Cycle in current scanline
    uint16_t dot; // Dot currently being drawn
    uint16_t addr; // Memory Address - 14 bit address
    uint8_t code; // Code - 2 bits
    uint8_t ctrl[16]; // 16 Control Registers
    uint8_t stat; // Status Register - read only
    uint8_t rdbuf; // Read Buffer
    uint8_t alatch; // Address Latch
    uint8_t clatch; // CRAM Latch - Game Gear only
    uint8_t wlatch; // Write Latch
    uint8_t hscroll; // Horizontal Scroll Latch
    uint8_t hcount; // HCounter Value
    uint8_t lcount; // Line Interrupt Counter
    uint8_t int_fr_pending; // Frame Interrupt Pending
    uint8_t int_ln_pending; // Line Interrupt Pending
    uint8_t paused; // Set if the system is paused, unset if unpaused
} smsvdp_t;

void smsvdp_set_size_callback(void (*)(int, int, int, int));

void smsvdp_init(void);

void smsvdp_set_buffer(uint32_t*);
void smsvdp_set_palette(uint8_t);
void smsvdp_set_quirks(uint8_t);
void smsvdp_set_region(uint8_t);

int smsvdp_phaser_triggered(void);
void smsvdp_phaser_coords(int32_t, int32_t);

uint8_t smsvdp_rd_data(void);
uint8_t smsvdp_rd_stat(void);

void smsvdp_wr_hcount(void);
uint8_t smsvdp_rd_hcount(void);
uint8_t smsvdp_rd_vcount(void);

void smsvdp_wr_ctrl(uint8_t);
void smsvdp_wr_data(uint8_t);

int smsvdp_exec(void);

void smsvdp_state_load(uint8_t*);
void smsvdp_state_save(uint8_t*);

#endif
