Commits

spencercw committed fea88c6

Update the HDMA source and destination values after doing a transfer.

Undocumented behaviour is fun! Other minor fixes as well.

Comments (0)

Files changed (4)

gb_emulator/gb_memory.cpp

 		ioPorts[ptr] = val & 0xc7;
 		break;
 
+	// LCD control
+	case LCDC:
+		if (!(val & 0x80) && (ioPorts[ptr] & 0x80) && ioPorts[LCDC_Y] < 144)
+		{
+			clog << hex << setfill('0')
+			     << "turning off display outside VBLANK period.. hardware damage! pc=" << setw(4) << gb_.cpu_.pc
+			     << " ptr=" << setw(4) << ptr
+			     << " val=" << setw(2) << static_cast<unsigned>(val) << "\n";
+		}
+		ioPorts[ptr] = val;
+		break;
+
 	// LCD status
 	case LCD_STAT:
 		ioPorts[ptr] &= 0x07;
 					vram[destination + i] = gb_.mem_.read(source + i);
 				}
 
+				// Update the HMDA registers
+				source = (source + length) & 0xfff0;
+				destination = (destination + length) & 0x1ff0;
+
+				ioPorts[HDMA1] = static_cast<uint8_t>(source >> 8);
+				ioPorts[HDMA2] = static_cast<uint8_t>(source);
+				ioPorts[HDMA3] = static_cast<uint8_t>(destination >> 8);
+				ioPorts[HDMA4] = static_cast<uint8_t>(destination);
+
 				// Mark the transfer as completed
 				ioPorts[HDMA5] = 0xff;
 			}

gb_emulator/gb_video.cpp

 
 					// Check sprite covers this line
 					if (gb_.mem_.ioPorts[LCDC_Y] >= sprite[0] - 16 &&
-						gb_.mem_.ioPorts[LCDC_Y] < sprite[0] -
+						gb_.mem_.ioPorts[LCDC_Y] <  sprite[0] -
 							(gb_.mem_.ioPorts[LCDC] & LCDC_SPRITE_SIZE ? 0 : 8))
 					{
 						sprites[spritesCount++] = sprite;
 					if (gb_.mem_.ioPorts[LCDC] & LCDC_SPRITE_SIZE)
 						spriteIndex &= 0xfe;
 					spriteIndex *= 16;
-					if (sprites[i][3] & 0x08)
+					if (gb_.gbc_ && (sprites[i][3] & 0x08))
 						spriteIndex += VRAM_BANK_SIZE;
 					uint8_t *tile = &gb_.mem_.vram[spriteIndex];
 
 						else
 							tileLineIndex = 7  - tileLineIndex;
 					}
-					uint16_t tileLine = *(uint16_t *) &tile[tileLineIndex * 2];
+					uint16_t tileLine = *reinterpret_cast<uint16_t *>(&tile[tileLineIndex * 2]);
 
 					// Select the palette
 					uint8_t *palette = &gbcSpritePalette[(sprites[i][3] & 0x07) * 8];
 
 						// If the sprite is to be behind the background then the pixel is only drawn
 						// if the background colour is zero.
-						if ((sprites[i][3] & 0x80) && priorityMap[x])
+						if ((gb_.mem_.ioPorts[LCDC] & LCDC_BG_DISPLAY) &&
+							(priorityMap[x] == 2 || (priorityMap[x] == 1 && (sprites[i][3] & 0x80))))
 							continue;
 
 						uint8_t r = 0,
 				gb_.mem_.vram[gb_.mem_.hdmaDestination++] = gb_.mem_.read(gb_.mem_.hdmaSource++);
 			}
 
+			// Update the HMDA registers
+			gb_.mem_.hdmaSource &= 0xfff0;
+			gb_.mem_.hdmaDestination &= 0x1ff0;
+			
+			gb_.mem_.ioPorts[HDMA1] = static_cast<uint8_t>(gb_.mem_.hdmaSource >> 8);
+			gb_.mem_.ioPorts[HDMA2] = static_cast<uint8_t>(gb_.mem_.hdmaSource);
+			gb_.mem_.ioPorts[HDMA3] = static_cast<uint8_t>(gb_.mem_.hdmaDestination >> 8);
+			gb_.mem_.ioPorts[HDMA4] = static_cast<uint8_t>(gb_.mem_.hdmaDestination);
+
 			// Decrement the length value in the register, or mark as complete as appropriate. If
 			// the register is zero (meaning this was the last block of the transfer) then the
 			// decrement will overflow and set the register to 0xff, which incidentally is the value
 			if (x >= 160)
 				continue;
 
-			// Mark the pixel as drawn
+			// Mark the pixel as drawn. A value of 2 in the priority map indicates the background
+			// should be on top, even if the attributes for a sprite say otherwise
 			if (value)
-				priorityMap[x] = true;
+				priorityMap[x] = (attr & 0x80) ? 2 : 1;
 
 			if (gb_.gbc_)
 			{

gb_emulator/gb_video.hpp

 {
 public:
 	//! Pixel priority map.
-	bool priorityMap[160];
+	uint8_t priorityMap[160];
 	//! GameBoy Color background color palette.
 	uint8_t gbcBgPalette[GBC_PALETTE_SIZE];
 	//! GameBoy Color sprite color palette.

third_party/hqx/src/common.h

-/*
- * Copyright (C) 2003 Maxim Stepin ( maxst@hiend3d.com )
- *
- * Copyright (C) 2010 Cameron Zemek ( grom@zeminvaders.net)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+/*
+ * Copyright (C) 2003 Maxim Stepin ( maxst@hiend3d.com )
+ *
+ * Copyright (C) 2010 Cameron Zemek ( grom@zeminvaders.net)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
 #ifndef __HQX_COMMON_H_