//--------------------------------------------------------------------------- // NEOPOP : Emulator as in Dreamland // // Copyright (c) 2001-2002 by neopop_uk //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. See also the license.txt file for // additional informations. //--------------------------------------------------------------------------- #include "neopop.h" #include "mem.h" #include "gfx.h" #include "interrupt.h" #include "dma.h" namespace MDFN_IEN_NGP { NGPGFX_CLASS::NGPGFX_CLASS(void) { layer_enable_setting = 1 | 2 | 4; for (int x = 0; x < 4096; x++) { int r = (x & 0xF) * 17; int g = ((x >> 4) & 0xF) * 17; int b = ((x >> 8) & 0xF) * 17; ColorMap[x] = b | g << 8 | r << 16 | 0xff000000; } } NGPGFX_CLASS::~NGPGFX_CLASS() { } void NGPGFX_CLASS::reset(void) { memset(SPPLT, 0x7, sizeof(SPPLT)); memset(SCRP1PLT, 0x7, sizeof(SCRP1PLT)); memset(SCRP2PLT, 0x7, sizeof(SCRP2PLT)); raster_line = 0; S1SO_H = 0; S1SO_V = 0; S2SO_H = 0; S2SO_V = 0; WBA_H = 0; WBA_V = 0; WSI_H = 0xFF; WSI_V = 0xFF; C_OVR = 0; BLNK = 0; PO_H = 0; PO_V = 0; P_F = 0; BG_COL = 0x7; CONTROL_2D = 0; CONTROL_INT = 0; SCREEN_PERIOD = 0xC6; K2GE_MODE = 0; delayed_settings(); } void NGPGFX_CLASS::power(void) { reset(); memset(ScrollVRAM, 0, sizeof(ScrollVRAM)); memset(CharacterRAM, 0, sizeof(CharacterRAM)); memset(SpriteVRAM, 0, sizeof(SpriteVRAM)); memset(SpriteVRAMColor, 0, sizeof(SpriteVRAMColor)); memset(ColorPaletteRAM, 0, sizeof(ColorPaletteRAM)); } void NGPGFX_CLASS::delayed_settings(void) { //Window dimensions winx = WBA_H; winy = WBA_V; winw = WSI_H; winh = WSI_V; //Scroll Planes (Confirmed delayed) scroll1x = S1SO_H; scroll1y = S1SO_V; scroll2x = S2SO_H; scroll2y = S2SO_V; //Sprite offset (Confirmed delayed) scrollsprx = PO_H; scrollspry = PO_V; //Plane Priority (Confirmed delayed) planeSwap = P_F & 0x80; //Background colour register (Confirmed delayed) bgc = BG_COL; //2D Control register (Confirmed delayed) oowc = CONTROL_2D & 7; negative = CONTROL_2D & 0x80; } bool NGPGFX_CLASS::hint(void) { //H_Int / Delayed settings if ((raster_line < SCREEN_HEIGHT - 1 || raster_line == SCREEN_PERIOD)) { delayed_settings(); //Get delayed settings //Allowed? if (CONTROL_INT & 0x40) return (1); } return (0); } bool NGPGFX_CLASS::draw(MDFN_Surface *surface, bool skip) { bool ret = 0; //Draw the scanline if (raster_line < SCREEN_HEIGHT && !skip) { if (!K2GE_MODE) draw_scanline_colour(layer_enable_setting, raster_line); else draw_scanline_mono(layer_enable_setting, raster_line); uint32 *dest = surface->pixels + surface->pitch32 * raster_line; for (int x = 0; x < SCREEN_WIDTH; x++) dest[x] = ColorMap[cfb_scanline[x] & 4095]; } raster_line++; //V_Int? if (raster_line == SCREEN_HEIGHT) { BLNK = 1; ret = 1; if (CONTROL_INT & 0x80) // (statusIFF() <= 4 TestIntHDMA(5, 0x0B); } //End of V_Int if (raster_line == SCREEN_PERIOD + 1) //Last scanline + 1 { raster_line = 0; C_OVR = 0; BLNK = 0; } return (ret); } void NGPGFX_CLASS::SetLayerEnableMask(uint64 mask) { layer_enable_setting = mask; } //extern uint32 ngpc_soundTS; void NGPGFX_CLASS::write8(uint32 address, uint8 data) { //if(address >= 0x8032 && address <= 0x8035) // printf("%08x %02x %d\n", address, data, ngpc_soundTS); if (address >= 0x9000 && address <= 0x9fff) ScrollVRAM[address - 0x9000] = data; else if (address >= 0xa000 && address <= 0xbfff) CharacterRAM[address - 0xa000] = data; else if (address >= 0x8800 && address <= 0x88ff) SpriteVRAM[address - 0x8800] = data; else if (address >= 0x8c00 && address <= 0x8c3f) SpriteVRAMColor[address - 0x8c00] = data & 0x0f; else if (address >= 0x8200 && address <= 0x83ff) ColorPaletteRAM[address - 0x8200] = data; else switch (address) { //default: printf("HuhW: %08x\n", address); break; case 0x8000: CONTROL_INT = data & 0xC0; break; case 0x8002: WBA_H = data; break; case 0x8003: WBA_V = data; break; case 0x8004: WSI_H = data; break; case 0x8005: WSI_V = data; break; case 0x8006: SCREEN_PERIOD = data; break; case 0x8012: CONTROL_2D = data & 0x87; break; case 0x8020: PO_H = data; break; case 0x8021: PO_V = data; break; case 0x8030: P_F = data & 0x80; break; case 0x8032: S1SO_H = data; break; case 0x8033: S1SO_V = data; break; case 0x8034: S2SO_H = data; break; case 0x8035: S2SO_V = data; break; case 0x8101: SPPLT[0] = data & 0x7; break; case 0x8102: SPPLT[1] = data & 0x7; break; case 0x8103: SPPLT[2] = data & 0x7; break; case 0x8105: SPPLT[3] = data & 0x7; break; case 0x8106: SPPLT[4] = data & 0x7; break; case 0x8107: SPPLT[5] = data & 0x7; break; case 0x8109: SCRP1PLT[0] = data & 0x7; break; case 0x810a: SCRP1PLT[1] = data & 0x7; break; case 0x810b: SCRP1PLT[2] = data & 0x7; break; case 0x810d: SCRP1PLT[3] = data & 0x7; break; case 0x810e: SCRP1PLT[4] = data & 0x7; break; case 0x810f: SCRP1PLT[5] = data & 0x7; break; case 0x8111: SCRP2PLT[0] = data & 0x7; break; case 0x8112: SCRP2PLT[1] = data & 0x7; break; case 0x8113: SCRP2PLT[2] = data & 0x7; break; case 0x8115: SCRP2PLT[3] = data & 0x7; break; case 0x8116: SCRP2PLT[4] = data & 0x7; break; case 0x8117: SCRP2PLT[5] = data & 0x7; break; case 0x8118: BG_COL = data & 0xC7; break; case 0x87e0: if (data == 0x52) { puts("GEreset"); reset(); } break; case 0x87e2: K2GE_MODE = data & 0x80; break; } } void NGPGFX_CLASS::write16(uint32 address, uint16 data) { write8(address, data & 0xFF); write8(address + 1, data >> 8); } #if 0 namespace TLCS900H { extern uint32 pc; }; #endif uint8 NGPGFX_CLASS::read8(uint32 address) { #if 0 if(address >= 0x8200 && address <= 0xbfff) { printf("[GFX] Read8: %08x -- %08x\n", address, TLCS900H::pc); if(pc == 0x0028dd3d) //21) { TLCS900H::pc = 0x28DD15; for(int x = 0; x < 256; x++) puts(TLCS900h_disassemble()); abort(); } } #endif if (address >= 0x9000 && address <= 0x9fff) return (ScrollVRAM[address - 0x9000]); else if (address >= 0xa000 && address <= 0xbfff) return (CharacterRAM[address - 0xa000]); else if (address >= 0x8800 && address <= 0x88ff) return (SpriteVRAM[address - 0x8800]); else if (address >= 0x8c00 && address <= 0x8c3f) return (SpriteVRAMColor[address - 0x8c00]); else if (address >= 0x8200 && address <= 0x83ff) return (ColorPaletteRAM[address - 0x8200]); else switch (address) { //default: printf("Huh: %08x\n", address); break; case 0x8000: return (CONTROL_INT); case 0x8002: return (WBA_H); case 0x8003: return (WBA_V); case 0x8004: return (WSI_H); case 0x8005: return (WSI_V); case 0x8006: return (SCREEN_PERIOD); case 0x8008: return ((uint8)((abs(TIMER_HINT_RATE - (int)timer_hint)) >> 2)); //RAS.H read (Simulated horizontal raster position) case 0x8009: return (raster_line); case 0x8010: return ((C_OVR ? 0x80 : 0x00) | (BLNK ? 0x40 : 0x00)); case 0x8012: return (CONTROL_2D); case 0x8020: return (PO_H); case 0x8021: return (PO_V); case 0x8030: return (P_F); case 0x8032: return (S1SO_H); case 0x8033: return (S1SO_V); case 0x8034: return (S2SO_H); case 0x8035: return (S2SO_V); case 0x8101: return (SPPLT[0]); break; case 0x8102: return (SPPLT[1]); break; case 0x8103: return (SPPLT[2]); break; case 0x8105: return (SPPLT[3]); break; case 0x8106: return (SPPLT[4]); break; case 0x8107: return (SPPLT[5]); break; case 0x8108: return (SCRP1PLT[0]); break; case 0x8109: return (SCRP1PLT[1]); break; case 0x810a: return (SCRP1PLT[2]); break; case 0x810d: return (SCRP1PLT[3]); break; case 0x810e: return (SCRP1PLT[4]); break; case 0x810f: return (SCRP1PLT[5]); break; case 0x8111: return (SCRP2PLT[0]); break; case 0x8112: return (SCRP2PLT[1]); break; case 0x8113: return (SCRP2PLT[2]); break; case 0x8115: return (SCRP2PLT[3]); break; case 0x8116: return (SCRP2PLT[4]); break; case 0x8117: return (SCRP2PLT[5]); break; case 0x8118: return (BG_COL); case 0x87e2: return (K2GE_MODE); } return (0); } uint16 NGPGFX_CLASS::read16(uint32 address) { uint16 ret; ret = read8(address); ret |= read8(address + 1) << 8; return (ret); } }