From 29985288e625aa3d65b32610a9c89bafe2be06d0 Mon Sep 17 00:00:00 2001 From: dborth Date: Wed, 4 Mar 2009 06:53:25 +0000 Subject: [PATCH] Carl Kenner's VBA-M changes --- source/vba/gba/GBA.cpp | 2 +- source/vba/gba/GBAcpu.h | 3 +- source/vba/gba/GBAinline.h | 156 +++++++++++++++++++++++-------------- source/vba/gba/Mode0.cpp | 8 ++ source/vba/gba/Mode1.cpp | 9 +++ source/vba/gba/Mode2.cpp | 8 ++ source/vba/gba/Mode3.cpp | 7 ++ source/vba/gba/Mode4.cpp | 7 ++ source/vba/gba/Mode5.cpp | 8 ++ source/vba/gba/RTC.cpp | 80 +++++++++++++++++-- 10 files changed, 220 insertions(+), 68 deletions(-) diff --git a/source/vba/gba/GBA.cpp b/source/vba/gba/GBA.cpp index 451e3ee..b20b630 100644 --- a/source/vba/gba/GBA.cpp +++ b/source/vba/gba/GBA.cpp @@ -3552,7 +3552,7 @@ void CPULoop(int ticks) // read default joystick joy = systemReadJoypad(-1); P1 = 0x03FF ^ (joy & 0x3FF); - if(cpuEEPROMSensorEnabled) + //if(cpuEEPROMSensorEnabled) systemUpdateMotionSensor(); UPDATE_REG(0x130, P1); u16 P1CNT = READ16LE(((u16 *)&ioMem[0x132])); diff --git a/source/vba/gba/GBAcpu.h b/source/vba/gba/GBAcpu.h index 54a88c9..5a080b4 100644 --- a/source/vba/gba/GBAcpu.h +++ b/source/vba/gba/GBAcpu.h @@ -5,7 +5,8 @@ extern int armExecute(); extern int thumbExecute(); #ifdef __GNUC__ -# define INSN_REGPARM __attribute__((regparm(1))) +# define INSN_REGPARM /*nothing*/ + //# define INSN_REGPARM __attribute__((regparm(1))) # define LIKELY(x) __builtin_expect(!!(x),1) # define UNLIKELY(x) __builtin_expect(!!(x),0) #else diff --git a/source/vba/gba/GBAinline.h b/source/vba/gba/GBAinline.h index 97c4149..2e6b9fd 100644 --- a/source/vba/gba/GBAinline.h +++ b/source/vba/gba/GBAinline.h @@ -52,10 +52,10 @@ u8 inline CPUReadByteQuick( u32 addr ) { switch(addr >> 24 ) { - case 8: - case 9: - case 10: - case 12: + case 0x08: + case 0x09: + case 0x0A: + case 0x0C: #ifdef USE_VM return VMRead8( addr & 0x1FFFFFF ); #endif @@ -70,10 +70,10 @@ u16 inline CPUReadHalfWordQuick( u32 addr ) { switch(addr >> 24) { - case 8: - case 9: - case 10: - case 12: + case 0x08: + case 0x09: + case 0x0A: + case 0x0C: #ifdef USE_VM return VMRead16( addr & 0x1FFFFFF ); #endif @@ -88,10 +88,10 @@ u32 inline CPUReadMemoryQuick( u32 addr ) { switch(addr >> 24) { - case 8: - case 9: - case 10: - case 12: + case 0x08: + case 0x09: + case 0x0A: + case 0x0C: #ifdef USE_VM return VMRead32( addr & 0x1FFFFFF ); #endif @@ -119,7 +119,7 @@ static inline u32 CPUReadMemory(u32 address) u32 value; switch(address >> 24) { - case 0: + case 0x00: if(reg[15].I >> 24) { if(address < 0x4000) { #ifdef GBA_LOGGING @@ -135,13 +135,13 @@ static inline u32 CPUReadMemory(u32 address) } else value = READ32LE(((u32 *)&bios[address & 0x3FFC])); break; - case 2: + case 0x02: value = READ32LE(((u32 *)&workRAM[address & 0x3FFFC])); break; - case 3: + case 0x03: value = READ32LE(((u32 *)&internalRAM[address & 0x7ffC])); break; - case 4: + case 0x04: if((address < 0x4000400) && ioReadable[address & 0x3fc]) { if(ioReadable[(address & 0x3fc) + 2]) value = READ32LE(((u32 *)&ioMem[address & 0x3fC])); @@ -149,10 +149,10 @@ static inline u32 CPUReadMemory(u32 address) value = READ16LE(((u16 *)&ioMem[address & 0x3fc])); } else goto unreadable; break; - case 5: + case 0x05: value = READ32LE(((u32 *)&paletteRAM[address & 0x3fC])); break; - case 6: + case 0x06: address = (address & 0x1fffc); if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) { @@ -163,26 +163,41 @@ static inline u32 CPUReadMemory(u32 address) address &= 0x17fff; value = READ32LE(((u32 *)&vram[address])); break; - case 7: + case 0x07: value = READ32LE(((u32 *)&oam[address & 0x3FC])); break; - case 8: - case 9: - case 10: - case 11: - case 12: + case 0x08: + // Must be cartridge ROM, reading other sensors doesn't allow 32-bit access. + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: #ifdef USE_VM // Nintendo GC Virtual Memory value = VMRead32( address & 0x1FFFFFC ); #else value = READ32LE(((u32 *)&rom[address&0x1FFFFFC])); #endif break; - case 13: + case 0x0D: if(cpuEEPROMEnabled) // no need to swap this return eepromRead(address); goto unreadable; - case 14: + case 0x0E: + // Yoshi's Universal Gravitation (Topsy Turvy) + // Koro Koro + if(cpuEEPROMSensorEnabled) { + switch(address & 0x00008f00) { + case 0x8200: + return systemGetSensorX() & 255; + case 0x8300: + return (systemGetSensorX() >> 8)|0x80; + case 0x8400: + return systemGetSensorY() & 255; + case 0x8500: + return systemGetSensorY() >> 8; + } + } if(cpuFlashEnabled | cpuSramEnabled) // no need to swap this return flashRead(address); @@ -257,7 +272,7 @@ static inline u32 CPUReadHalfWord(u32 address) u32 value; switch(address >> 24) { - case 0: + case 0x00: if (reg[15].I >> 24) { if(address < 0x4000) { #ifdef GBA_LOGGING @@ -271,13 +286,13 @@ static inline u32 CPUReadHalfWord(u32 address) } else value = READ16LE(((u16 *)&bios[address & 0x3FFE])); break; - case 2: + case 0x02: value = READ16LE(((u16 *)&workRAM[address & 0x3FFFE])); break; - case 3: + case 0x03: value = READ16LE(((u16 *)&internalRAM[address & 0x7ffe])); break; - case 4: + case 0x04: if((address < 0x4000400) && ioReadable[address & 0x3fe]) { value = READ16LE(((u16 *)&ioMem[address & 0x3fe])); @@ -298,10 +313,10 @@ static inline u32 CPUReadHalfWord(u32 address) } else goto unreadable; break; - case 5: + case 0x05: value = READ16LE(((u16 *)&paletteRAM[address & 0x3fe])); break; - case 6: + case 0x06: address = (address & 0x1fffe); if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) { @@ -312,29 +327,49 @@ static inline u32 CPUReadHalfWord(u32 address) address &= 0x17fff; value = READ16LE(((u16 *)&vram[address])); break; - case 7: + case 0x07: value = READ16LE(((u16 *)&oam[address & 0x3fe])); break; - case 8: - case 9: - case 10: - case 11: - case 12: - if(address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8) - value = rtcRead(address); - else + case 0x08: + // Use existing case statement and faster test for potential speed improvement + // This is possibly the GPIO port that controls the real time clock, + // WarioWare Twisted! tilt sensors, rumble, and solar sensors. + if(address >= 0x80000c4 && address <= 0x80000c8) { + // this function still works if there is no real time clock + // and does a normal memory read in that case. + value = rtcRead(address & 0xFFFFFFE); + break; + } + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: #ifdef USE_VM // Nintendo GC Virtual Memory value = VMRead16( address & 0x1FFFFFE ); #else value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE])); #endif break; - case 13: + case 0x0D: if(cpuEEPROMEnabled) // no need to swap this return eepromRead(address); goto unreadable; - case 14: + case 0x0E: + // Yoshi's Universal Gravitation (Topsy Turvy) + // Koro Koro + if(cpuEEPROMSensorEnabled) { + switch(address & 0x00008f00) { + case 0x8200: + return systemGetSensorX() & 255; + case 0x8300: + return (systemGetSensorX() >> 8)|0x80; + case 0x8400: + return systemGetSensorY() & 255; + case 0x8500: + return systemGetSensorY() >> 8; + } + } if(cpuFlashEnabled | cpuSramEnabled) // no need to swap this return flashRead(address); @@ -385,7 +420,7 @@ static inline u16 CPUReadHalfWordSigned(u32 address) static inline u8 CPUReadByte(u32 address) { switch(address >> 24) { - case 0: + case 0x00: if (reg[15].I >> 24) { if(address < 0x4000) { #ifdef GBA_LOGGING @@ -398,42 +433,43 @@ static inline u8 CPUReadByte(u32 address) } else goto unreadable; } return bios[address & 0x3FFF]; - case 2: + case 0x02: return workRAM[address & 0x3FFFF]; - case 3: + case 0x03: return internalRAM[address & 0x7fff]; - case 4: + case 0x04: if((address < 0x4000400) && ioReadable[address & 0x3ff]) return ioMem[address & 0x3ff]; else goto unreadable; - case 5: + case 0x05: return paletteRAM[address & 0x3ff]; - case 6: + case 0x06: address = (address & 0x1ffff); if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) return 0; if ((address & 0x18000) == 0x18000) address &= 0x17fff; return vram[address]; - case 7: + case 0x07: return oam[address & 0x3ff]; - case 8: - case 9: - case 10: - case 11: - case 12: + case 0x08: + // the real time clock doesn't support byte reads, so don't bother checking for it. + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: #ifdef USE_VM // Nintendo GC Virtual Memory return VMRead8( address & 0x1FFFFFF ); #else return rom[address & 0x1FFFFFF]; #endif - case 13: + case 0x0D: if(cpuEEPROMEnabled) return eepromRead(address); goto unreadable; - case 14: - if(cpuSramEnabled | cpuFlashEnabled) - return flashRead(address); + case 0x0E: + // Yoshi's Universal Gravitation (Topsy Turvy) + // Koro Koro if(cpuEEPROMSensorEnabled) { switch(address & 0x00008f00) { case 0x8200: @@ -446,6 +482,8 @@ static inline u8 CPUReadByte(u32 address) return systemGetSensorY() >> 8; } } + if(cpuSramEnabled | cpuFlashEnabled) + return flashRead(address); // default default: unreadable: diff --git a/source/vba/gba/Mode0.cpp b/source/vba/gba/Mode0.cpp index c0d5812..9a2dd26 100644 --- a/source/vba/gba/Mode0.cpp +++ b/source/vba/gba/Mode0.cpp @@ -1,3 +1,11 @@ +/* +Mode 0 is the tiled graphics mode, with all the layers available. +There is no rotation or scaling in this mode. +It can be either 16 colours (with 16 different palettes) or 256 colours. +There are 1024 tiles available. + +These routines only render a single line at a time, because of the way the GBA does events. +*/ #include "GBA.h" #include "Globals.h" #include "GBAGfx.h" diff --git a/source/vba/gba/Mode1.cpp b/source/vba/gba/Mode1.cpp index 4cc3b07..fd15a03 100644 --- a/source/vba/gba/Mode1.cpp +++ b/source/vba/gba/Mode1.cpp @@ -1,3 +1,12 @@ +/* +Mode 1 is a tiled graphics mode, but with background layer 2 supporting scaling and rotation. +There is no layer 3 in this mode. +Layers 0 and 1 can be either 16 colours (with 16 different palettes) or 256 colours. +There are 1024 tiles available. +Layer 2 is 256 colours and allows only 256 tiles. + +These routines only render a single line at a time, because of the way the GBA does events. +*/ #include "GBA.h" #include "Globals.h" #include "GBAGfx.h" diff --git a/source/vba/gba/Mode2.cpp b/source/vba/gba/Mode2.cpp index 527a1ff..96999dc 100644 --- a/source/vba/gba/Mode2.cpp +++ b/source/vba/gba/Mode2.cpp @@ -1,3 +1,11 @@ +/* +Mode 2 is a 256 colour tiled graphics mode which supports scaling and rotation. +There is no background layer 0 or 1 in this mode. Only background layers 2 and 3. +There are 256 tiles available. +It does not support flipping. + +These routines only render a single line at a time, because of the way the GBA does events. +*/ #include "GBA.h" #include "Globals.h" #include "GBAGfx.h" diff --git a/source/vba/gba/Mode3.cpp b/source/vba/gba/Mode3.cpp index 1b1d0c6..fe5fb36 100644 --- a/source/vba/gba/Mode3.cpp +++ b/source/vba/gba/Mode3.cpp @@ -1,3 +1,10 @@ +/* +Mode 3 is a 15-bit (32768) colour bitmap graphics mode. +It has a single layer, background layer 2, the same size as the screen. +It doesn't support paging, scrolling, flipping, rotation or tiles. + +These routines only render a single line at a time, because of the way the GBA does events. +*/ #include "GBA.h" #include "Globals.h" #include "GBAGfx.h" diff --git a/source/vba/gba/Mode4.cpp b/source/vba/gba/Mode4.cpp index 1907948..6234613 100644 --- a/source/vba/gba/Mode4.cpp +++ b/source/vba/gba/Mode4.cpp @@ -1,3 +1,10 @@ +/* +Mode 4 is a 256 colour bitmap graphics mode with 2 swappable pages. +It has a single layer, background layer 2, the same size as the screen. +It doesn't support scrolling, flipping, rotation or tiles. + +These routines only render a single line at a time, because of the way the GBA does events. +*/ #include "GBA.h" #include "GBAGfx.h" #include "Globals.h" diff --git a/source/vba/gba/Mode5.cpp b/source/vba/gba/Mode5.cpp index dc72427..5f25b47 100644 --- a/source/vba/gba/Mode5.cpp +++ b/source/vba/gba/Mode5.cpp @@ -1,3 +1,11 @@ +/* +Mode 5 is a low resolution (160x128) 15-bit colour bitmap graphics mode +with 2 swappable pages! +It has a single layer, background layer 2, lower resolution than the screen. +It doesn't support scrolling, flipping, rotation or tiles. + +These routines only render a single line at a time, because of the way the GBA does events. +*/ #include "GBA.h" #include "Globals.h" #include "GBAGfx.h" diff --git a/source/vba/gba/RTC.cpp b/source/vba/gba/RTC.cpp index 7f3f598..5335ad2 100644 --- a/source/vba/gba/RTC.cpp +++ b/source/vba/gba/RTC.cpp @@ -8,6 +8,10 @@ #include #include +#include + +u8 systemGetSensorDarkness(); +int systemGetSensorZ(); enum RTCSTATE { IDLE, COMMAND, DATA, READDATA }; @@ -29,6 +33,8 @@ typedef struct { static RTCCLOCKDATA rtcClockData; static bool rtcEnabled = false; +int WarioRumbleMotor = 0; + void rtcEnable(bool e) { rtcEnabled = e; @@ -50,7 +56,26 @@ u16 rtcRead(u32 address) return rtcClockData.byte1; break; case 0x80000c4: - return rtcClockData.byte0; + + // Boktai Solar Sensor + if (rtcClockData.byte1 == 7) { + if (rtcClockData.reserved[11] >= systemGetSensorDarkness()) { + rtcClockData.reserved[10] = 0; + rtcClockData.reserved[11] = 0; + return 8; + } else return 0; + + // WarioWare Twisted Tilt Sensor + } else if (rtcClockData.byte1 == 0x0b) { + //sprintf(DebugStr, "Reading Twisted Sensor bit %d", rtcClockData.reserved[11]); + u16 v = systemGetSensorZ(); + return ((v >> rtcClockData.reserved[11]) & 1) << 2; + + // Real Time Clock + } else { + //sprintf(DebugStr, "Reading RTC %02x, %02x, %02x", rtcClockData.byte0, rtcClockData.byte1, rtcClockData.byte2); + return rtcClockData.byte0; + } break; } } @@ -75,12 +100,52 @@ bool rtcWrite(u32 address, u16 value) return false; if(address == 0x80000c8) { - rtcClockData.byte2 = (u8)value; // enable ? + rtcClockData.byte2 = (u8)value; // bit 0 = enable reading from 0x80000c4 c6 and c8 } else if(address == 0x80000c6) { - rtcClockData.byte1 = (u8)value; // read/write - } else if(address == 0x80000c4) { - if(rtcClockData.byte2 & 1) { - if(rtcClockData.state == IDLE && rtcClockData.byte0 == 1 && value == 5) { + rtcClockData.byte1 = (u8)value; // 0=read/1=write (for each of 4 low bits) + if (!(value & 8)) WarioRumbleMotor = 0; + } else if(address == 0x80000c4) { // 4 bits of I/O Port Data (upper bits not used) + + // WarioWare Twisted rumble + if(rtcClockData.byte1 & 8) { + WarioRumbleMotor = value & 8; + } else { + WarioRumbleMotor = 0; // rumble is off when not writing to that pin + } + + // Boktai solar sensor + if (rtcClockData.byte1 == 7) { + if (value & 2) { + // reset counter to 0 + rtcClockData.reserved[11]=0; + rtcClockData.reserved[10]=0; + } + if ((value & 1) && (!(rtcClockData.reserved[10] & 1))) { + // increase counter, ready to do another read + if (rtcClockData.reserved[11]<255) rtcClockData.reserved[11]++; + } + rtcClockData.reserved[10] = value & rtcClockData.byte1; + } + + // WarioWare Twisted rotation sensor + if (rtcClockData.byte1 == 0xb) { + if (value & 2) { + // clock goes high in preperation for reading a bit + rtcClockData.reserved[11]--; + } + if (value & 1) { + // start ADC conversion + rtcClockData.reserved[11] = 15; + } + + rtcClockData.byte0 = value & rtcClockData.byte1; + + // Real Time Clock + } + /**/ + + if(rtcClockData.byte2 & 1) { // if reading is enabled + if(rtcClockData.state == IDLE && rtcClockData.byte0 == 1 && value == 5) { rtcClockData.state = COMMAND; rtcClockData.bits = 0; rtcClockData.command = 0; @@ -178,7 +243,7 @@ bool rtcWrite(u32 address, u16 value) } } break; - default: + default: break; } } else @@ -199,6 +264,7 @@ void rtcReset() rtcClockData.dataLen = 0; rtcClockData.bits = 0; rtcClockData.state = IDLE; + rtcClockData.reserved[11] = 0; } void rtcSaveGame(gzFile gzFile)