diff options
Diffstat (limited to 'backends/platform/ds/arm9/source/dsmain.cpp')
-rw-r--r-- | backends/platform/ds/arm9/source/dsmain.cpp | 3888 |
1 files changed, 3888 insertions, 0 deletions
diff --git a/backends/platform/ds/arm9/source/dsmain.cpp b/backends/platform/ds/arm9/source/dsmain.cpp new file mode 100644 index 0000000000..b42d9ed15e --- /dev/null +++ b/backends/platform/ds/arm9/source/dsmain.cpp @@ -0,0 +1,3888 @@ +/* ScummVMDS - Scumm Interpreter DS Port + * Copyright (C) 2002-2004 The ScummVM project and Neil Millstone + * + * 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. + * + * 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 General Public License for more details. + * + * You should have received a copy of the GNU 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. + * + */ + + +#include <nds.h> + +#include <ARM9/console.h> //basic print funcionality + +#include <stdlib.h> +#include "dsmain.h" +#include "string.h" +#include "system.h" +#include "osystem_ds.h" +#include "icons_raw.h" +#include "gba_nds_fat.h" +#include "disc_io.h" +#include "config-manager.h" +#include "engines/scumm/scumm.h" +#include "keyboard_raw.h" +#include "keyboard_pal_raw.h" +#define V16(a, b) ((a << 12) | b) +#include "touchkeyboard.h" +#include "registers_alt.h" +//#include "compact_flash.h" +#include "dsoptions.h" + +namespace DS { + +// From console.c in NDSLib + +//location of cursor +extern u8 row; +extern u8 col; + +// Mouse mode +enum MouseMode { + MOUSE_LEFT, MOUSE_RIGHT, MOUSE_HOVER, MOUSE_NUM_MODES +}; + +// Defines +#define FRAME_TIME 17 +#define SCUMM_GAME_HEIGHT 142 +#define SCUMM_GAME_WIDTH 232 + +int textureID; +u16* texture; + +int frameCount; +int currentTimeMillis; + +// Timer Callback +int callbackInterval; +int callbackTimer; +OSystem::TimerProc callback; + +// Scaled +bool scaledMode; +int scX; +int scY; + +int subScX; +int subScY; +int subScTargetX; +int subScTargetY; +int subScreenWidth = SCUMM_GAME_WIDTH; +int subScreenHeight = SCUMM_GAME_HEIGHT; +int subScreenScale = 256; + + + +// Sound +int bufferSize; +s16* soundBuffer; +int bufferFrame; +int bufferRate; +int bufferSamples; +bool soundHiPart; + +// Events +int lastEventFrame; +bool indyFightState; +bool indyFightRight; + +OSystem::SoundProc soundCallback; +void* soundParam; +int lastCallbackFrame; +bool bufferFirstHalf; +bool bufferSecondHalf; + +// Saved buffers +u8* savedBuffer = NULL; +bool highBuffer; +bool displayModeIs8Bit; + +// Game id +u8 gameID; + +bool consoleEnable = true; +bool gameScreenSwap = false; + +MouseMode mouseMode; + +// Sprites +SpriteEntry sprites[128]; +SpriteEntry spritesMain[128]; +int tweak; + +// Shake +int shakePos = 0; + +// Keyboard +bool keyboardEnable = false; +bool leftHandedMode = false; +bool keyboardIcon = false; + +// Touch +int touchScX, touchScY, touchX, touchY; + +// Dragging +int dragStartX, dragStartY; +bool dragging = false; +int dragScX, dragScY; + +// Interface styles +char gameName[32]; + +// 8-bit surface size +int gameWidth = 320; +int gameHeight = 200; + +enum controlType { + CONT_SCUMM_ORIGINAL, + CONT_SCUMM_SAMNMAX, + CONT_SKY, + CONT_SIMON, +}; + +struct gameListType { + char gameId[16]; + controlType control; +}; + +#define NUM_SUPPORTED_GAMES 15 + +gameListType gameList[NUM_SUPPORTED_GAMES] = { + // Unknown game - use normal SCUMM controls + {"unknown", CONT_SCUMM_ORIGINAL}, + + // SCUMM games + {"maniac", CONT_SCUMM_ORIGINAL}, + {"zak", CONT_SCUMM_ORIGINAL}, + {"loom", CONT_SCUMM_ORIGINAL}, + {"indy3", CONT_SCUMM_ORIGINAL}, + {"atlantis", CONT_SCUMM_ORIGINAL}, + {"monkey", CONT_SCUMM_ORIGINAL}, + {"monkey2", CONT_SCUMM_ORIGINAL}, + {"tentacle", CONT_SCUMM_ORIGINAL}, + {"samnmax", CONT_SCUMM_SAMNMAX}, + + // Non-SCUMM games + {"sky", CONT_SKY}, + {"simon1", CONT_SIMON}, + {"simon2", CONT_SIMON}, + {"gob1", CONT_SCUMM_ORIGINAL}, + {"queen", CONT_SCUMM_ORIGINAL} +}; + +gameListType* currentGame = NULL; + +// Stylus +#define ABS(x) ((x)>0?(x):-(x)) + +bool penDown; +bool penHeld; +bool penReleased; +bool penDownLastFrame; +f32 penX, penY; +int keysDownSaved; +int keysReleasedSaved; + +bool penDownSaved; +bool penReleasedSaved; +int penDownFrames; +int touchXOffset = 0; +int touchYOffset = 0; + +u16 savedPalEntry255 = RGB15(31, 31, 31); + + +extern "C" int scummvm_main(int argc, char *argv[]); +void updateStatus(); + +TransferSound soundControl; + +//plays an 8 bit mono sample at 11025Hz +void playSound(const void* data, u32 length, bool loop, bool adpcm, int rate) +{ + + if (!IPC->soundData) { + soundControl.count = 0; + } + + soundControl.data[soundControl.count].data = data; + soundControl.data[soundControl.count].len = length | (loop? 0x80000000: 0x00000000); + soundControl.data[soundControl.count].rate = rate; // 367 samples per frame + soundControl.data[soundControl.count].pan = 64; + soundControl.data[soundControl.count].vol = 127; + soundControl.data[soundControl.count].format = adpcm? 2: 0; + + soundControl.count++; + + DC_FlushAll(); + IPC->soundData = &soundControl; +} + +void stopSound(int channel) { + playSound(NULL, 0, false, false, -channel); +} + +void updateOAM() { + DC_FlushAll(); + dmaCopy(sprites, OAM_SUB, 128 * sizeof(SpriteEntry)); + dmaCopy(spritesMain, OAM, 128 * sizeof(SpriteEntry)); +} + +void setGameSize(int width, int height) { + gameWidth = width; + gameHeight = height; +} + +int getGameWidth() { + return gameWidth; +} + +int getGameHeight() { + return gameHeight; +} + +void initSprites() { + for(int i = 0; i < 128; i++) { + sprites[i].attribute[0] = ATTR0_DISABLED; + sprites[i].attribute[1] = 0; + sprites[i].attribute[2] = 0; + sprites[i].attribute[3] = 0; + } + + for(int i = 0; i < 128; i++) { + spritesMain[i].attribute[0] = ATTR0_DISABLED; + spritesMain[i].attribute[1] = 0; + spritesMain[i].attribute[2] = 0; + spritesMain[i].attribute[3] = 0; + } + + updateOAM(); +} + + +void saveGameBackBuffer() { +#ifdef DISABLE_SCUMM + if (savedBuffer == NULL) savedBuffer = new u8[gameWidth * gameHeight]; + for (int r = 0; r < 200; r++) { + memcpy(savedBuffer + (r * gameWidth), ((u8 *) (get8BitBackBuffer())) + (r * 512), gameWidth); + } +#endif +} + +void restoreGameBackBuffer() { +#ifdef DISABLE_SCUMM + if (savedBuffer) { + for (int r = 0; r < 200; r++) { + memcpy(((u8 *) (BG_GFX_SUB)) + (r * 512), savedBuffer + (r * gameWidth), gameWidth); + memcpy(((u8 *) (get8BitBackBuffer())) + (r * 512), savedBuffer + (r * gameWidth), gameWidth); + } + delete savedBuffer; + savedBuffer = NULL; + } +#endif + +#ifndef DISABLE_SCUMM + memset(get8BitBackBuffer(), 0, 512 * 256); + memset(BG_GFX_SUB, 0, 512 * 256); + if (Scumm::g_scumm) { + Scumm::g_scumm->markRectAsDirty(Scumm::kMainVirtScreen, 0, gameWidth - 1, 0, gameHeight - 1, 1); + Scumm::g_scumm->markRectAsDirty(Scumm::kTextVirtScreen, 0, gameWidth - 1, 0, gameHeight - 1, 1); + Scumm::g_scumm->markRectAsDirty(Scumm::kVerbVirtScreen, 0, gameWidth - 1, 0, gameHeight - 1, 1); + } +#endif + +} + + +void initGame() { + // This is a good time to check for left handed mode since the mode change is done as the game starts. + // There's probably a better way, but hey. +// consolePrintf("initing game\n"); + + setOptions(); + + //strcpy(gameName, ConfMan.getActiveDomain().c_str()); + strcpy(gameName, ConfMan.get("gameid").c_str()); +// consolePrintf("\n\n\n\nCurrent game: '%s' %d\n", gameName, gameName[0]); + + currentGame = &gameList[0]; // Default game + + for (int r = 0; r < NUM_SUPPORTED_GAMES; r++) { + if (!stricmp(gameName, gameList[r].gameId)) { + currentGame = &gameList[r]; +// consolePrintf("Game list num: %d\n", currentGame); + } + } + + +} + +void setLeftHanded(bool enable) { + leftHandedMode = enable; +} + +void setTouchXOffset(int x) { + touchXOffset = x; +} + +void setTouchYOffset(int y) { + touchYOffset = y; +} + +void setUnscaledMode(bool enable) { + scaledMode = !enable; +} + +void displayMode8Bit() { + + u16 buffer[32 * 32]; + + setKeyboardEnable(false); + + if (!displayModeIs8Bit) { + for (int r = 0; r < 32 * 32; r++) { + buffer[r] = ((u16 *) SCREEN_BASE_BLOCK_SUB(4))[r]; + } + } + + + + videoSetMode(MODE_5_2D | (consoleEnable? DISPLAY_BG0_ACTIVE: 0) | DISPLAY_BG3_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP); + videoSetModeSub(MODE_3_2D /*| DISPLAY_BG0_ACTIVE*/ | DISPLAY_BG3_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP); //sub bg 0 will be used to print text + + vramSetBankA(VRAM_A_MAIN_BG_0x6000000); + vramSetBankB(VRAM_B_MAIN_BG_0x6020000); + + vramSetBankC(VRAM_C_SUB_BG_0x6200000); + vramSetBankD(VRAM_D_MAIN_BG_0x6040000); + + vramSetBankH(VRAM_H_LCD); + + BG3_CR = BG_BMP8_512x256 | BG_BMP_BASE(8); + + + + BG3_XDX = (int) (((float) (gameWidth) / 256.0f) * 256); + BG3_XDY = 0; + BG3_YDX = 0; + BG3_YDY = (int) ((200.0f / 192.0f) * 256); + + SUB_BG3_CR = BG_BMP8_512x256; + + + + SUB_BG3_XDX = (int) (subScreenWidth / 256.0f * 256); + SUB_BG3_XDY = 0; + SUB_BG3_YDX = 0; + SUB_BG3_YDY = (int) (subScreenHeight / 192.0f * 256); + + + // Do text stuff + BG0_CR = BG_MAP_BASE(0) | BG_TILE_BASE(1); + BG0_Y0 = 0; + + // Restore palette entry used by text in the front-end + PALETTE_SUB[255] = savedPalEntry255; + + consoleInitDefault((u16*)SCREEN_BASE_BLOCK(0), (u16*)CHAR_BASE_BLOCK(1), 16); + consolePrintSet(0, 23); + + if (!displayModeIs8Bit) { + for (int r = 0; r < 32 * 32; r++) { + ((u16 *) SCREEN_BASE_BLOCK(0))[r] = buffer[r]; + } +// dmaCopyHalfWords(3, (u16 *) SCREEN_BASE_BLOCK(0), buffer, 32 * 32 * 2); + } + + + if (!displayModeIs8Bit) restoreGameBackBuffer(); + displayModeIs8Bit = true; + + POWER_CR &= ~POWER_SWAP_LCDS; + + keyboardEnable = false; + initGame(); + +} + +void setGameID(int id) { + gameID = id; +} + +void dummyHandler() { + REG_IF = IRQ_VBLANK; +} + +void checkSleepMode() { + if (IPC->performArm9SleepMode) { + + consolePrintf("ARM9 Entering sleep mode\n"); + + int intSave = REG_IE; + irqSet(IRQ_VBLANK, dummyHandler); +// int irqHandlerSave = (int) IRQ_HANDLER; + REG_IE = IRQ_VBLANK; + //IRQ_HANDLER = dummyHandler; + + int powerSave = POWER_CR; + POWER_CR &= ~POWER_ALL; + + while (IPC->performArm9SleepMode) { + swiWaitForVBlank(); + } + + POWER_CR = powerSave; +// IRQ_HANDLER = (void (*)()) irqHandlerSave; + irqSet(IRQ_VBLANK, VBlankHandler); + REG_IE = intSave; + + consolePrintf("ARM9 Waking from sleep mode\n"); + } +} + +void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor) { + if (currentGame->control != CONT_SCUMM_SAMNMAX) + return; + + uint16 border = RGB15(24,24,24) | 0x8000; + + + int off = 48*64; + memset(SPRITE_GFX_SUB+off, 0, 64*64*2); + + int pos = 190 - (w+2); + + + + // make border + for (uint i=0; i<w+2; i++) { + SPRITE_GFX_SUB[off+i] = border; + SPRITE_GFX_SUB[off+(31)*64+i] = border; + } + for (uint i=1; i<31; i++) { + SPRITE_GFX_SUB[off+(i*64)] = border; + SPRITE_GFX_SUB[off+(i*64)+(w+1)] = border; + } + + int offset = (32 - h) >> 1; + + for (uint y=0; y<h; y++) { + for (uint x=0; x<w; x++) { + int color = icon[y*w+x]; + if (color == keycolor) { + SPRITE_GFX_SUB[off+(y+1+offset)*64+(x+1)] = 0x8000; // black background + } else { + SPRITE_GFX_SUB[off+(y+1+offset)*64+(x+1)] = BG_PALETTE[color] | 0x8000; + } + } + } + + sprites[1].attribute[0] = ATTR0_BMP | 150; + sprites[1].attribute[1] = ATTR1_SIZE_64 | pos; + sprites[1].attribute[2] = ATTR2_ALPHA(1) | 48; +} + + + + +void displayMode16Bit() { + + u16 buffer[32 * 32 * 2]; + + + if (displayModeIs8Bit) { + saveGameBackBuffer(); + for (int r = 0; r < 32 * 32; r++) { + buffer[r] = ((u16 *) SCREEN_BASE_BLOCK(0))[r]; + } + } + + + videoSetMode(MODE_5_2D | /*DISPLAY_BG0_ACTIVE |*/ DISPLAY_BG3_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP); + videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE |/* DISPLAY_BG1_ACTIVE |*/ DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP); //sub bg 0 will be used to print text + + vramSetBankA(VRAM_A_MAIN_BG); + vramSetBankB(VRAM_B_MAIN_BG); + vramSetBankC(VRAM_C_MAIN_BG); + vramSetBankD(VRAM_D_MAIN_BG); + vramSetBankH(VRAM_H_SUB_BG); + + BG3_CR = BG_BMP16_512x256; + highBuffer = false; + + BG3_XDX = (int) (1.25f * 256); + BG3_XDY = 0; + BG3_YDX = 0; + BG3_YDY = (int) ((200.0f / 192.0f) * 256); + + memset(BG_GFX, 0, 512 * 256 * 2); + + savedPalEntry255 = PALETTE_SUB[255]; + PALETTE_SUB[255] = RGB15(31,31,31);//by default font will be rendered with color 255 + + // Do text stuff + SUB_BG0_CR = BG_MAP_BASE(4) | BG_TILE_BASE(0); + SUB_BG0_Y0 = 0; + + consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(4), (u16*)CHAR_BASE_BLOCK_SUB(0), 16); + + if (displayModeIs8Bit) { + //dmaCopyHalfWords(3, (u16 *) SCREEN_BASE_BLOCK_SUB(0), buffer, 32 * 32 * 2); + for (int r = 0; r < 32 * 32; r++) { + ((u16 *) SCREEN_BASE_BLOCK_SUB(4))[r] = buffer[r]; + } + } + + consolePrintSet(0, 23); + consolePrintf("\n"); + + // Show keyboard + SUB_BG1_CR = BG_TILE_BASE(1) | BG_MAP_BASE(12); + //drawKeyboard(1, 12); + + POWER_CR &= ~POWER_SWAP_LCDS; + + + + displayModeIs8Bit = false; +} + + +void displayMode16BitFlipBuffer() { + if (!displayModeIs8Bit) { + u16* back = get16BitBackBuffer(); + +// highBuffer = !highBuffer; +// BG3_CR = BG_BMP16_512x256 | BG_BMP_RAM(highBuffer? 1: 0); + + for (int r = 0; r < 512 * 256; r++) { + *(BG_GFX + r) = *(back + r); + } + } +} + +void setShakePos(int shakePos) { + shakePos = shakePos; +} + + +u16* get16BitBackBuffer() { + return BG_GFX + 0x20000; +} + +u16* get8BitBackBuffer() { + return BG_GFX + 0x10000; // 16bit qty! +} + +void setSoundProc(OSystem::SoundProc proc, void* param) { +// consolePrintf("Set sound callback"); + soundCallback = proc; + soundParam = param; +} + +// The sound system in ScummVM seems to always return stereo interleaved samples. +// Here, I'm treating an 11Khz stereo stream as a 22Khz mono stream, which works sorta ok, but is +// a horrible bodge. Any advice on how to change the engine to output mono would be greatly +// appreciated. +void doSoundCallback() { + if ((soundCallback)) { + lastCallbackFrame = frameCount; + + for (int r = IPC->playingSection; r < IPC->playingSection + 4; r++) { + int chunk = r & 3; + + if (IPC->fillNeeded[chunk]) { + IPC->fillNeeded[chunk] = false; + DC_FlushAll(); + soundCallback(soundParam, (byte *) (soundBuffer + ((bufferSamples >> 2) * chunk)), bufferSamples >> 1); + IPC->fillNeeded[chunk] = false; + DC_FlushAll(); + } + + } + + } +} + +void doTimerCallback() { + if (callback) { + if (callbackTimer <= 0) { + callbackTimer += callbackInterval; + callback(callbackInterval); + } + } +} + +void soundUpdate() { + if ((bufferFrame == 0)) { +// playSound(soundBuffer, (bufferSamples * 2), true); + } +// consolePrintf("%x\n", IPC->test); + + + if (bufferFrame == 0) { +// bufferFirstHalf = true; + } + if (bufferFrame == bufferSize >> 1) { + //bufferSecondHalf = true; + } + + bufferFrame++; + if (bufferFrame == bufferSize) { + bufferFrame = 0; + } +} + +void memoryReport() { + int r = 0; + int* p; + do { + p = (int *) malloc(r * 8192); + free(p); + r++; + } while ((p) && (r < 512)); + + int t = -1; + void* block[1024]; + do { + t++; + block[t] = (int *) malloc(4096); + } while ((t < 1024) && (block[t])); + + for (int q = 0; q < t; q++) { + free(block[q]); + } + + consolePrintf("Free: %dK, Largest: %dK\n", t * 4, r * 8); +} + + +void addIndyFightingKeys() { + OSystem_DS* system = OSystem_DS::instance(); + OSystem::Event event; + + event.type = OSystem::EVENT_KEYDOWN; + event.kbd.flags = 0; + + if ((getKeysDown() & KEY_L)) { + indyFightRight = false; + } + + if ((getKeysDown() & KEY_R)) { + indyFightRight = true; + } + + if ((getKeysDown() & KEY_UP)) { + event.kbd.keycode = '8'; + event.kbd.ascii = '8'; + system->addEvent(event); + } + if ((getKeysDown() & KEY_LEFT)) { + event.kbd.keycode = '4'; + event.kbd.ascii = '4'; + system->addEvent(event); + } + if ((getKeysDown() & KEY_RIGHT)) { + event.kbd.keycode = '6'; + event.kbd.ascii = '6'; + system->addEvent(event); + } + if ((getKeysDown() & KEY_DOWN)) { + event.kbd.keycode = '2'; + event.kbd.ascii = '2'; + system->addEvent(event); + } + + if (indyFightRight) { + + if ((getKeysDown() & KEY_X)) { + event.kbd.keycode = '9'; + event.kbd.ascii = '9'; + system->addEvent(event); + } + if ((getKeysDown() & KEY_A)) { + event.kbd.keycode = '6'; + event.kbd.ascii = '6'; + system->addEvent(event); + } + if ((getKeysDown() & KEY_B)) { + event.kbd.keycode = '3'; + event.kbd.ascii = '3'; + system->addEvent(event); + } + + } else { + + if ((getKeysDown() & KEY_X)) { + event.kbd.keycode = '7'; + event.kbd.ascii = '7'; + system->addEvent(event); + } + if ((getKeysDown() & KEY_A)) { + event.kbd.keycode = '4'; + event.kbd.ascii = '4'; + system->addEvent(event); + } + if ((getKeysDown() & KEY_B)) { + event.kbd.keycode = '1'; + event.kbd.ascii = '1'; + system->addEvent(event); + } + + } + + + if ((getKeysDown() & KEY_Y)) { + event.kbd.keycode = '5'; + event.kbd.ascii = '5'; + system->addEvent(event); + } +} + + +void setKeyboardEnable(bool en) { + if (en == keyboardEnable) return; + keyboardEnable = en; + u16* backupBank = (u16 *) 0x6040000; + + if (keyboardEnable) { + + + DS::drawKeyboard(1, 12, backupBank); + + + SUB_BG1_CR = BG_TILE_BASE(1) | BG_MAP_BASE(12); + + if (displayModeIs8Bit) { + SUB_DISPLAY_CR |= DISPLAY_BG1_ACTIVE; // Turn on keyboard layer + SUB_DISPLAY_CR &= ~DISPLAY_BG3_ACTIVE; // Turn off game layer + } else { + SUB_DISPLAY_CR |= DISPLAY_BG1_ACTIVE; // Turn on keyboard layer + SUB_DISPLAY_CR &= ~DISPLAY_BG0_ACTIVE; // Turn off console layer + } + lcdSwap(); + } else { + + + // Restore the palette that the keyboard has used + for (int r = 0; r < 256; r++) { + BG_PALETTE_SUB[r] = BG_PALETTE[r]; + } + + + //restoreVRAM(1, 12, backupBank); + + if (displayModeIs8Bit) { + // Copy the sub screen VRAM from the top screen - they should always be + // the same. + for (int r = 0; r < (512 * 256) >> 1; r++) { + BG_GFX_SUB[r] = get8BitBackBuffer()[r]; + } + + SUB_DISPLAY_CR &= ~DISPLAY_BG1_ACTIVE; // Turn off keyboard layer + SUB_DISPLAY_CR |= DISPLAY_BG3_ACTIVE; // Turn on game layer + } else { + SUB_DISPLAY_CR &= ~DISPLAY_BG1_ACTIVE; // Turn off keyboard layer + SUB_DISPLAY_CR |= DISPLAY_BG0_ACTIVE; // Turn on console layer + } + + lcdSwap(); + } +} + +bool getKeyboardEnable() { + return keyboardEnable; +} + +bool getIsDisplayMode8Bit() { + return displayModeIs8Bit; +} + +void addEventsToQueue() { + OSystem_DS* system = OSystem_DS::instance(); + OSystem::Event event; + + + + + if (system->isEventQueueEmpty()) { + +/* + if (getKeysDown() & KEY_L) { + tweak--; + consolePrintf("Tweak: %d\n", tweak); + IPC->tweakChanged = true; + } + + + if (getKeysDown() & KEY_R) { + tweak++; + consolePrintf("Tweak: %d\n", tweak); + IPC->tweakChanged = true; + } + */ + if ((keysHeld() & KEY_L) && (keysHeld() & KEY_R)) { + memoryReport(); + } + + if (displayModeIs8Bit) { + + if (!indyFightState) { + + + if ((getKeysDown() & KEY_B) && (!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) { + // consolePrintf("Pressing Esc"); + + event.type = OSystem::EVENT_KEYDOWN; + event.kbd.keycode = 27; + event.kbd.ascii = 27; + event.kbd.flags = 0; + system->addEvent(event); + } + + } + + + + if ((!getIndyFightState()) && (getKeysDown() & KEY_Y)) { + consoleEnable = !consoleEnable; + if (displayModeIs8Bit) { + displayMode8Bit(); + } else { + displayMode16Bit(); + } + } + + + if (!((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (!getIndyFightState())) { + + if ((getKeysDown() & KEY_A) && (!indyFightState)) { + gameScreenSwap = !gameScreenSwap; + } + + if (!getPenHeld() || (mouseMode != MOUSE_HOVER)) { + if (getKeysDown() & KEY_LEFT) { + mouseMode = MOUSE_LEFT; + } + if (getKeysDown() & KEY_RIGHT) { + if (currentGame->control != CONT_SCUMM_SAMNMAX) { + mouseMode = MOUSE_RIGHT; + } else { + // If we're playing sam and max, click and release the right mouse + // button to change verb + OSystem::Event event; + + event.type = OSystem::EVENT_RBUTTONDOWN; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + + event.type = OSystem::EVENT_RBUTTONUP; + system->addEvent(event); + } + } + if (getKeysDown() & KEY_UP) { + mouseMode = MOUSE_HOVER; + } + } + + + + } + + if ((getKeysDown() & KEY_SELECT)) { + //scaledMode = !scaledMode; + //scY = 4; + showOptionsDialog(); + } + + + } + + if (!getIndyFightState() && !((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (getKeysDown() & KEY_X)) { + setKeyboardEnable(!keyboardEnable); + } + + updateStatus(); + + OSystem::Event event; + + if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) { + event.type = OSystem::EVENT_MOUSEMOVE; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + //consolePrintf("x=%d y=%d \n", getPenX(), getPenY()); + } + + if (!keyboardEnable) { + if ((mouseMode != MOUSE_HOVER) || (!displayModeIs8Bit)) { + if (getPenDown() && (!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) { + event.type = ((mouseMode == MOUSE_LEFT) || (!displayModeIs8Bit))? OSystem::EVENT_LBUTTONDOWN: OSystem::EVENT_RBUTTONDOWN; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + } + + if (getPenReleased()) { + event.type = mouseMode == MOUSE_LEFT? OSystem::EVENT_LBUTTONUP: OSystem::EVENT_RBUTTONUP; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + } + } else { + // In hover mode, D-pad left and right click the mouse when the pen is on the screen + + if (getPenHeld()) { + if (getKeysDown() & KEY_LEFT) { + event.type = OSystem::EVENT_LBUTTONDOWN; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + } + /* if (getKeysReleased() & KEY_LEFT) { + event.type = OSystem::EVENT_LBUTTONUP; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + }*/ + + if (getKeysDown() & KEY_RIGHT) { + event.type = OSystem::EVENT_RBUTTONDOWN; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + } + /*if (getKeysReleased() & KEY_RIGHT) { + event.type = OSystem::EVENT_RBUTTONUP; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + }*/ + } + } + + if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R)) && (displayModeIs8Bit)) { + // Controls specific to the control method + + + if (currentGame->control == CONT_SKY) { + // Extra controls for Benieth a Steel Sky + if ((getKeysDown() & KEY_DOWN)) { + penY = 0; + penX = 0; // Show inventory by moving mouse onto top line + } + } + + if (currentGame->control == CONT_SIMON) { + // Extra controls for Simon the Sorcerer + if ((getKeysDown() & KEY_DOWN)) { + OSystem::Event event; + + event.type = OSystem::EVENT_KEYDOWN; + event.kbd.keycode = '#'; // F10 or # - show hotspots + event.kbd.ascii = '#'; + event.kbd.flags = 0; + system->addEvent(event); +// consolePrintf("F10\n"); + } + } + + if (currentGame->control == CONT_SCUMM_ORIGINAL) { + // Extra controls for Scumm v1-5 games + if ((getKeysDown() & KEY_DOWN)) { + OSystem::Event event; + + event.type = OSystem::EVENT_KEYDOWN; + event.kbd.keycode = '.'; // Full stop - skips current dialogue line + event.kbd.ascii = '.'; + event.kbd.flags = 0; + system->addEvent(event); + } + + if (indyFightState) { + addIndyFightingKeys(); + } + + } + + } + } + + if (!displayModeIs8Bit) { + // Front end controls + + if (leftHandedSwap(getKeysDown()) & KEY_UP) { + event.type = OSystem::EVENT_KEYDOWN; + event.kbd.keycode = SDLK_UP; + event.kbd.ascii = 0; + event.kbd.flags = 0; + system->addEvent(event); + + event.type = OSystem::EVENT_KEYUP; + system->addEvent(event); + } + + if (leftHandedSwap(getKeysDown()) & KEY_DOWN) { + event.type = OSystem::EVENT_KEYDOWN; + event.kbd.keycode = SDLK_DOWN; + event.kbd.ascii = 0; + event.kbd.flags = 0; + system->addEvent(event); + + event.type = OSystem::EVENT_KEYUP; + system->addEvent(event); + } + + if (leftHandedSwap(getKeysDown()) & KEY_A) { + event.type = OSystem::EVENT_KEYDOWN; + event.kbd.keycode = SDLK_RETURN; + event.kbd.ascii = 0; + event.kbd.flags = 0; + system->addEvent(event); + + event.type = OSystem::EVENT_KEYUP; + system->addEvent(event); + } + + } + + + if ((getKeysDown() & KEY_START)) { + event.type = OSystem::EVENT_KEYDOWN; + event.kbd.keycode = 319; // F5 + event.kbd.ascii = 319; + event.kbd.flags = 0; + system->addEvent(event); +/* + event.type = OSystem::EVENT_KEYUP; + event.kbd.keycode = 319; // F5 + event.kbd.ascii = 319; + system->addEvent(event);*/ + +// consolePrintf("Pressing F5"); + } + + + if (keyboardEnable) { + DS::addKeyboardEvents(); + } + + consumeKeys(); + + consumePenEvents(); + + } +} + +void updateStatus() { + int offs; + + if (displayModeIs8Bit) { + switch (mouseMode) { + case MOUSE_LEFT: { + offs = 16; + break; + } + case MOUSE_RIGHT: { + offs = 32; + break; + } + case MOUSE_HOVER: { + offs = 0; + break; + } + default: { + // Nothing! + offs = 0; + break; + } + } + + + sprites[0].attribute[0] = ATTR0_BMP | 150; + sprites[0].attribute[1] = ATTR1_SIZE_32 | 208; + sprites[0].attribute[2] = ATTR2_ALPHA(1)| offs; + + if (indyFightState) { + sprites[2].attribute[0] = ATTR0_BMP | 150; + sprites[2].attribute[1] = ATTR1_SIZE_32 | (190 - 32) | (indyFightRight? 0: ATTR1_FLIP_X); + sprites[2].attribute[2] = ATTR2_ALPHA(1)| 48; + } else { + sprites[2].attribute[0] = ATTR0_DISABLED; + sprites[2].attribute[1] = 0; + sprites[2].attribute[2] = 0; + } + } else { + sprites[0].attribute[0] = ATTR0_DISABLED; + sprites[1].attribute[0] = ATTR0_DISABLED; + sprites[2].attribute[0] = ATTR0_DISABLED; + sprites[3].attribute[0] = ATTR0_DISABLED; + } + + if ((keyboardIcon) && (!keyboardEnable) && (!displayModeIs8Bit)) { + spritesMain[0].attribute[0] = ATTR0_BMP | 160; + spritesMain[0].attribute[1] = ATTR1_SIZE_32 | 0; + spritesMain[0].attribute[2] = ATTR2_ALPHA(1) | 64; + } else { + spritesMain[0].attribute[0] = ATTR0_DISABLED; + spritesMain[0].attribute[1] = 0; + spritesMain[0].attribute[2] = 0; + spritesMain[0].attribute[3] = 0; + } + +} + +void soundBufferEmptyHandler() { + REG_IF = IRQ_TIMER2; + + if (soundHiPart) { +// bufferSecondHalf = true; + } else { +// bufferFirstHalf = true; + } + + soundHiPart = !soundHiPart; +} + +void setMainScreenScroll(int x, int y) { + if (gameScreenSwap) { + SUB_BG3_CX = x + (((frameCount & 1) == 0)? 64: 0); + SUB_BG3_CY = y; + } else { + BG3_CX = x + (((frameCount & 1) == 0)? 64: 0); + BG3_CY = y; + + touchX = x >> 8; + touchY = y >> 8; + } +} + +void setMainScreenScale(int x, int y) { + if (gameScreenSwap) { + SUB_BG3_XDX = x; + SUB_BG3_XDY = 0; + SUB_BG3_YDX = 0; + SUB_BG3_YDY = y; + } else { + BG3_XDX = x; + BG3_XDY = 0; + BG3_YDX = 0; + BG3_YDY = y; + + touchScX = x; + touchScY = y; + } +} + +void setZoomedScreenScroll(int x, int y) { + if (gameScreenSwap) { + BG3_CX = x + (((frameCount & 1) == 0)? 64: 0); + BG3_CY = y; + + touchX = x >> 8; + touchY = y >> 8; + } else { + SUB_BG3_CX = x + (((frameCount & 1) == 0)? 64: 0); + SUB_BG3_CY = y; + } +} + +void setZoomedScreenScale(int x, int y) { + if (gameScreenSwap) { + BG3_XDX = x; + BG3_XDY = 0; + BG3_YDX = 0; + BG3_YDY = y; + + touchScX = x; + touchScY = y; + } else { + SUB_BG3_XDX = x; + SUB_BG3_XDY = 0; + SUB_BG3_YDX = 0; + SUB_BG3_YDY = y; + } +} + +void VBlankHandler(void) { +// BG_PALETTE[0] = RGB15(31, 31, 31); +// if (*((int *) (0x023FFF00)) != 0xBEEFCAFE) { + // consolePrintf("Guard band overwritten!"); +// } + +// consolePri ntf("X:%d Y:%d\n", getPenX(), getPenY()); + + + IPC->tweak = tweak; + soundUpdate(); + + + + + if ((!gameScreenSwap) && (!(getKeysHeld() & KEY_L) && !(getKeysHeld() & KEY_R))) { + if (currentGame) { + if (currentGame->control != CONT_SCUMM_SAMNMAX) { + if (getPenHeld() && (getPenY() < SCUMM_GAME_HEIGHT)) { + setTopScreenTarget(getPenX(), getPenY()); + } + } else { + if (getPenHeld()) { + setTopScreenTarget(getPenX(), getPenY()); + } + } + } + } + + + penUpdate(); + keysUpdate(); + + + frameCount++; + + + + if (callback) { + callbackTimer -= FRAME_TIME; + } + + if ((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) { + + if ((!dragging) && (getPenHeld()) && (penDownFrames > 5)) { + dragging = true; + dragStartX = penX; + dragStartY = penY; + + if (gameScreenSwap) { + dragScX = subScTargetX; + dragScY = subScTargetY; + } else { + dragScX = scX; + dragScY = scY; + } + + + } + + if ((dragging) && (!getPenHeld())) { + dragging = false; + } + + if (dragging) { + + if (gameScreenSwap) { + subScTargetX = dragScX + ((dragStartX - penX) << 8); + subScTargetY = dragScY + ((dragStartY - penY) << 8); + } else { + scX = dragScX + ((dragStartX - penX)); + scY = dragScY + ((dragStartY - penY)); + } + +// consolePrintf("X:%d Y:%d\n", dragStartX - penX, dragStartY - penY); + } + } + + +/* if ((frameCount & 1) == 0) { + SUB_BG3_CX = subScX; + } else { + SUB_BG3_CX = subScX + 64; + } + + SUB_BG3_CY = subScY + (shakePos << 8);*/ + + /*SUB_BG3_XDX = (int) (subScreenWidth / 256.0f * 256); + SUB_BG3_XDY = 0; + SUB_BG3_YDX = 0; + SUB_BG3_YDY = (int) (subScreenHeight / 192.0f * 256);*/ + + + if ((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) { + if ((getKeysHeld() & KEY_A) && (subScreenScale < 256)) { + subScreenScale += 3; + } + + if ((getKeysHeld() & KEY_B) && (subScreenScale > 128)) { + subScreenScale -=3; + } + + int xCenter = subScTargetX + ((subScreenWidth >> 1) << 8); + int yCenter = subScTargetY + ((subScreenHeight >> 1) << 8); + + subScreenWidth = SCUMM_GAME_WIDTH * subScreenScale >> 8; + subScreenHeight = SCUMM_GAME_HEIGHT * subScreenScale >> 8; + + subScTargetX = xCenter - ((subScreenWidth >> 1) << 8); + subScTargetY = yCenter - ((subScreenHeight >> 1) << 8); + + + + + if (subScTargetX < 0) subScTargetX = 0; + if (subScTargetX > (gameWidth - subScreenWidth) << 8) subScTargetX = (gameWidth - subScreenWidth) << 8; + + if (subScTargetY < 0) subScTargetY = 0; + if (subScTargetY > (gameHeight - subScreenHeight) << 8) subScTargetY = (gameHeight - subScreenHeight) << 8; + } + + subScX += (subScTargetX - subScX) >> 2; + subScY += (subScTargetY - subScY) >> 2; + + if (displayModeIs8Bit) { + + if ((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) { + + int offsX = 0, offsY = 0; + + + if (getKeysHeld() & KEY_LEFT) { + offsX -= 1; + } + + if (getKeysHeld() & KEY_RIGHT) { + offsX += 1; + } + + if (getKeysHeld() & KEY_UP) { + offsY -= 1; + } + + if (getKeysHeld() & KEY_DOWN) { + offsY += 1; + } + + if (((gameScreenSwap) && (getKeysHeld() & KEY_L)) || ((!gameScreenSwap) && (getKeysHeld() & KEY_R))) { + subScTargetX += offsX << 8; + subScTargetY += offsY << 8; + } else { + scX += offsX; + scY += offsY; + } + } + + if (!scaledMode) { + + if (scX + 256 > gameWidth - 1) { + scX = gameWidth - 1 - 256; + } + + if (scX < 0) { + scX = 0; + } + + if (scY + 192 > gameHeight - 1) { + scY = gameHeight - 1 - 192; + } + + if (scY < 0) { + scY = 0; + } + + setZoomedScreenScroll(subScX, subScY); + setZoomedScreenScale(subScreenWidth, (subScreenHeight * 256) / 192); + + + setMainScreenScroll(scX << 8, (scY << 8) + (shakePos << 8)); + setMainScreenScale(256, 256); // 1:1 scale + + } else { + + if (scY > gameHeight - 192 - 1) { + scY = gameHeight - 192 - 1; + } + + if (scY < 0) { + scY = 0; + } + + setZoomedScreenScroll(subScX, subScY); + setZoomedScreenScale(subScreenWidth, (subScreenHeight * 256) / 192); + + setMainScreenScroll(64, (scY << 8) + (shakePos << 8)); + setMainScreenScale(320, 256); // 1:1 scale + + } + } else { + setZoomedScreenScroll(0, 0); + setZoomedScreenScale(320, 256); + + setMainScreenScroll(0, 0); + setMainScreenScale(320, 256); // 1:1 scale + } + + // Enable on screen keyboard when pen taps icon + if ((keyboardIcon) && (penX < 32) && (penY > 160) && (penHeld)) { + setKeyboardEnable(true); + } + + if (keyboardEnable) { + if (DS::getKeyboardClosed()) { + setKeyboardEnable(false); + } + } + + updateOAM(); + + //PALETTE[0] = RGB15(0, 0, 0); + REG_IF = IRQ_VBLANK; +} + +int getMillis() { + return currentTimeMillis; +// return frameCount * FRAME_TIME; +} + +void setTimerCallback(OSystem::TimerProc proc, int interval) { +// consolePrintf("Set timer proc %x, int %d\n", proc, interval); + callback = proc; + callbackInterval = interval; + callbackTimer = interval; +} + +void timerTickHandler() { + REG_IF = IRQ_TIMER0; + if ((callback) && (callbackTimer > 0)) { + callbackTimer--; + } + currentTimeMillis++; +} + +void setTalkPos(int x, int y) { +// if (gameID != Scumm::GID_SAMNMAX) { +// setTopScreenTarget(x, 0); +// } else { + setTopScreenTarget(x, y); +// } +} + +void setTopScreenTarget(int x, int y) { + subScTargetX = (x - (subScreenWidth >> 1)); + subScTargetY = (y - (subScreenHeight >> 1)); + + if (subScTargetX < 0) subScTargetX = 0; + if (subScTargetX > gameWidth - subScreenWidth) subScTargetX = gameWidth - subScreenWidth; + + if (subScTargetY < 0) subScTargetY = 0; + if (subScTargetY > gameHeight - subScreenHeight) subScTargetY = gameHeight - subScreenHeight; + + subScTargetX <<=8; + subScTargetY <<=8; +} + +void initHardware() { + // Guard band +//((int *) (0x023FFF00)) = 0xBEEFCAFE; + + + penInit(); + + powerON(POWER_ALL); +/* vramSetBankA(VRAM_A_MAIN_BG); + vramSetBankB(VRAM_B_MAIN_BG); + vramSetBankC(VRAM_C_SUB_BG); */ + vramSetBankI(VRAM_I_SUB_SPRITE); + vramSetBankG(VRAM_G_MAIN_SPRITE); + + currentTimeMillis = 0; + + +/* + // Set up a millisecond counter + TIMER0_CR = 0; + TIMER0_DATA = 0xFFFF; + TIMER0_CR = TIMER_ENABLE | TIMER_CASCADE; +*/ + + + + PALETTE[255] = RGB15(0,31,0); + + // Allocate save buffer for game screen +// savedBuffer = new u8[320 * 200]; + displayMode16Bit(); + + memset(BG_GFX, 0, 512 * 256 * 2); + scaledMode = true; + scX = 0; + scY = 0; + subScX = 0; + subScY = 0; + subScTargetX = 0; + subScTargetY = 0; + + //lcdSwap(); + POWER_CR &= ~POWER_SWAP_LCDS; + + frameCount = 0; + callback = NULL; + +// vramSetBankH(VRAM_H_SUB_BG); + + +// // Do text stuff + //BG0_CR = BG_MAP_BASE(0) | BG_TILE_BASE(1); +// BG0_Y0 = 48; + + PALETTE[255] = RGB15(31,31,31);//by default font will be rendered with color 255 + + //consoleInit() is a lot more flexible but this gets you up and running quick +// consoleInitDefault((u16*)SCREEN_BASE_BLOCK(0), (u16*)CHAR_BASE_BLOCK(1), 16); + //consolePrintSet(0, 6); + + //irqs are nice + irqInit(); +// irqInitHandler(); + irqSet(IRQ_VBLANK, VBlankHandler); + irqSet(IRQ_TIMER0, timerTickHandler); + irqSet(IRQ_TIMER2, soundBufferEmptyHandler); + + irqEnable(IRQ_VBLANK); + irqEnable(IRQ_TIMER0); + irqEnable(IRQ_TIMER2); + + + // Set up a millisecond timer + TIMER0_CR = 0; + TIMER0_DATA = (u32) TIMER_FREQ(1000); + TIMER0_CR = TIMER_ENABLE | TIMER_DIV_1 | TIMER_IRQ_REQ; + REG_IME = 1; + + PALETTE[255] = RGB15(0,0,31); + + initSprites(); + +// videoSetModeSub(MODE_3_2D | DISPLAY_BG0_ACTIVE | DISPLAY_BG3_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP); //sub bg 0 will be used to print text + + // Convert texture from 24bit 888 to 16bit 1555, remembering to set top bit! + u8* srcTex = (u8 *) icons_raw; + for (int r = 32 * 160 ; r >= 0; r--) { + SPRITE_GFX_SUB[r] = 0x8000 | (srcTex[r * 3] >> 3) | ((srcTex[r * 3 + 1] >> 3) << 5) | ((srcTex[r * 3 + 2] >> 3) << 10); + SPRITE_GFX[r] = 0x8000 | (srcTex[r * 3] >> 3) | ((srcTex[r * 3 + 1] >> 3) << 5) | ((srcTex[r * 3 + 2] >> 3) << 10); + } + + WAIT_CR &= ~(0x0080); + REG_WRAM_CNT = 0; + +} + + +void setKeyboardIcon(bool enable) { + keyboardIcon = enable; +} + +bool getKeyboardIcon() { + return keyboardIcon; +} + + +//////////////////// +// Pen stuff +//////////////////// + + +void penInit() { + penDown = false; + penHeld = false; + penReleased = false; + penDownLastFrame = false; + penDownSaved = false; + penReleasedSaved = false; + penDownFrames = 0; + consumeKeys(); +} + +void penUpdate() { + +// if (getKeysHeld() & KEY_L) consolePrintf("%d, %d penX=%d, penY=%d tz=%d\n", IPC->touchXpx, IPC->touchYpx, penX, penY, IPC->touchZ1); + + if ((penDownFrames > 1)) { // Is this right? Dunno, but it works for me. + + if ((penHeld)) { + penHeld = true; + penDown = false; + + if ((IPC->touchZ1 > 0) && (IPC->touchXpx > 0) && (IPC->touchYpx > 0)) { + penX = IPC->touchXpx + touchXOffset; + penY = IPC->touchYpx + touchYOffset; + } + + } else { + penDown = true; + penHeld = true; + penDownSaved = true; + + //if ( (ABS(penX - IPC->touchXpx) < 10) && (ABS(penY - IPC->touchYpx) < 10) ) { + if ((IPC->touchZ1 > 0) && (IPC->touchXpx > 0) && (IPC->touchYpx > 0)) { + penX = IPC->touchXpx; + penY = IPC->touchYpx; + } + //} + } + + } else { + if (penHeld) { + penReleased = true; + penReleasedSaved = true; + } else { + penReleased = false; + } + + penDown = false; + penHeld = false; + } + + + if ((IPC->touchZ1 > 0) || ((penDownFrames == 2)) ) { + penDownLastFrame = true; + penDownFrames++; + } else { + penDownLastFrame = false; + penDownFrames = 0; + } + +} + +int leftHandedSwap(int keys) { + // Start and select are unchanged + if (leftHandedMode) { + int result = keys & (~(KEY_R | KEY_L | KEY_Y | KEY_A | KEY_B | KEY_X | KEY_LEFT | KEY_RIGHT | KEY_UP | KEY_DOWN)); + + if (keys & KEY_L) result |= KEY_R; + if (keys & KEY_R) result |= KEY_L; + + if (keys & KEY_LEFT) result |= KEY_Y; + if (keys & KEY_RIGHT) result |= KEY_A; + if (keys & KEY_DOWN) result |= KEY_B; + if (keys & KEY_UP) result |= KEY_X; + + if (keys & KEY_Y) result |= KEY_LEFT; + if (keys & KEY_A) result |= KEY_RIGHT; + if (keys & KEY_B) result |= KEY_DOWN; + if (keys & KEY_X) result |= KEY_UP; + + return result; + } else { + return keys; + } +} + +void keysUpdate() { + scanKeys(); + keysDownSaved |= leftHandedSwap(keysDown()); + keysReleasedSaved |= leftHandedSwap(keysUp()); +} + +int getKeysDown() { + return keysDownSaved; +} + +int getKeysHeld() { + return leftHandedSwap(keysHeld()); +} + +int getKeysReleased() { + return keysReleasedSaved; +} + +void consumeKeys() { + keysDownSaved = 0; + keysReleasedSaved = 0; +} + +bool getPenDown() { + return penDownSaved; +} + +bool getPenHeld() { + return penHeld; +} + +bool getPenReleased() { + return penReleasedSaved; +} + +void consumePenEvents() { + penDownSaved = false; + penReleasedSaved = false; +} + +int getPenX() { + int x = ((penX * touchScX) >> 8) + touchX; + x = x < 0? 0: (x > gameWidth - 1? gameWidth - 1: x); + return x; +} + +int getPenY() { + int y = ((penY * touchScY) >> 8) + touchY; + y = y < 0? 0: (y > gameHeight - 1? gameHeight - 1: y); + return y; +} + +GLvector getPenPos() { + GLvector v; + + v.x = (penX * inttof32(1)) / SCREEN_WIDTH; + v.y = (penY * inttof32(1)) / SCREEN_HEIGHT; + + return v; +} + +void formatSramOption() { + consolePrintf("The following files are present in save RAM:\n"); + DSSaveFileManager::instance()->listFiles(); + + consolePrintf("\nAre you sure you want to\n"); + consolePrintf("DELETE all files?\n"); + consolePrintf("A = Yes, X = No\n"); + + while (true) { + if (keysHeld() & KEY_A) { + DSSaveFileManager::instance()->formatSram(); + consolePrintf("SRAM cleared!\n"); + return; + } + + if (keysHeld() & KEY_X) { + consolePrintf("Whew, that was close!\n"); + return; + } + } +} + + +void setIndyFightState(bool st) { + indyFightState = st; + indyFightRight = true; +} + +bool getIndyFightState() { + return indyFightState; +} + +///////////////// +// GBAMP +///////////////// + +bool GBAMPAvail = false; + +void initGBAMP() { + FAT_InitFiles(); + if (disc_IsInserted()) { + GBAMPAvail = true; + consolePrintf("Found flash card reader!\n"); + } else { + GBAMPAvail = false; + consolePrintf("Flash card reader not found!\n"); + } +} + +bool isGBAMPAvailable() { + return GBAMPAvail; +} + + + +///////////////// +// Main +///////////////// + +static const Common::String test("poo", 1, 16); + + + +int main(void) +{ + soundCallback = NULL; + + + initHardware(); + + // Let arm9 read cartridge + *((u16 *) (0x04000204)) &= ~0x0080; + + lastCallbackFrame = 0; + tweak = 0; + + indyFightState = false; + indyFightRight = true; + + // CPU speed = 67108864 + // 8 frames = 2946 368.5 bytes per fr + +// playSound(stretch, 47619, false); +// playSound(twang, 11010, true); // 18640 + +// bufferSize = 10; + bufferRate = 22050; + bufferFrame = 0; +// bufferSamples = (bufferRate * bufferSize) / 60; + bufferSamples = 4096; + + bufferFirstHalf = false; + bufferSecondHalf = true; + + lastEventFrame = 0; + mouseMode = MOUSE_LEFT; + + + + + int bytes = (2 * (bufferSamples)) + 100; + + soundBuffer = (s16 *) malloc(bytes * 2); + + + soundHiPart = true; +/* + TIMER1_CR = 0; + TIMER1_DATA = TIMER_FREQ(bufferRate); + TIMER1_CR = TIMER_ENABLE | TIMER_DIV_1; + + TIMER2_CR = 0; + TIMER2_DATA = 0xFFFF - (bufferSamples / 2); + TIMER2_CR = TIMER_ENABLE | TIMER_IRQ_REQ | TIMER_CASCADE; + */ + // 2945 - 2947 + + + +// for (int r = 2946; r < 3000; r++) { +// soundBuffer[r] = 30000; +// } + + + + consolePrintf("------------------------\n"); + consolePrintf("ScummVM DS\n"); + consolePrintf("Ported by Neil Millstone\n"); +#ifdef DS_SCUMM_BUILD + consolePrintf("Version 0.61 build A\n"); +#else + consolePrintf("Version 0.61 build B\n"); +#endif + consolePrintf("------------------------\n"); + consolePrintf("L/R + D-pad/pen: Scroll view\n"); + consolePrintf("D-pad left: Left mouse button\n"); + consolePrintf("D-pad right: Right mouse button\n"); + consolePrintf("D-pad up: Hover mouse\n"); + consolePrintf("D-pad down: Skip dialog line\n"); + consolePrintf("B button: Skip cutscenes\n"); + consolePrintf("Select: DS Options menu\n"); + consolePrintf("Start: Game menu\n"); + consolePrintf("Y (in game): Toggle console\n"); + consolePrintf("X: Toggle keyboard\n"); + consolePrintf("A: Swap screens\n"); + consolePrintf("L + R on bootup: Clear SRAM\n\n"); + consolePrintf("For a complete poo list see the\n"); + consolePrintf("help screen.\npoo\n"); + + + for (int r = 0; r < bytes; r++) { + soundBuffer[r] = 0; + } + + consolePrintf("length=%d str='%s'\n", test.size(), test.c_str()); + + swiWaitForVBlank(); + swiWaitForVBlank(); + playSound(soundBuffer, (bufferSamples * 2), true); + swiWaitForVBlank(); + swiWaitForVBlank(); + swiWaitForVBlank(); + + + + // Create a file system node to force search for a zip file in GBA rom space + DSFileSystemNode* node = new DSFileSystemNode(); + if (!node->getZip() || (!node->getZip()->isReady())) { + // If not found, init CF/SD driver + initGBAMP(); + } + delete node; + + + + updateStatus(); + + +// OSystem_DS::instance(); + g_system = new OSystem_DS(); + assert(g_system); + + if ((keysHeld() & KEY_L) && (keysHeld() & KEY_R)) { + formatSramOption(); + } + +// printf("'%s'", Common::ConfigManager::kTransientDomain.c_str()); + //printf("'%s'", Common::ConfigManager::kApplicationDomain.c_str()); + + + char* argv[2] = {"/scummvmds", "--config=scummvmb.ini"}; +#ifdef DS_NON_SCUMM_BUILD + + while (1) { + scummvm_main(2, (char **) &argv); + } +#else + while (1) { + scummvm_main(1, (char **) &argv); + } +#endif + + + return 0; +} + +} + +int main() { + DS::main(); +} +/* ScummVMDS - Scumm Interpreter DS Port + * Copyright (C) 2002-2004 The ScummVM project and Neil Millstone + * + * 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. + * + * 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 General Public License for more details. + * + * You should have received a copy of the GNU 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. + * + */ + + +#include <nds.h> + +#include <ARM9/console.h> //basic print funcionality + +#include <stdlib.h> +#include "dsmain.h" +#include "string.h" +#include "system.h" +#include "osystem_ds.h" +#include "icons_raw.h" +#include "gba_nds_fat.h" +#include "disc_io.h" +#include "config-manager.h" +#include "engines/scumm/scumm.h" +#include "keyboard_raw.h" +#include "keyboard_pal_raw.h" +#define V16(a, b) ((a << 12) | b) +#include "touchkeyboard.h" +#include "registers_alt.h" +//#include "compact_flash.h" +#include "dsoptions.h" + +namespace DS { + +// From console.c in NDSLib + +//location of cursor +extern u8 row; +extern u8 col; + +// Mouse mode +enum MouseMode { + MOUSE_LEFT, MOUSE_RIGHT, MOUSE_HOVER, MOUSE_NUM_MODES +}; + +// Defines +#define FRAME_TIME 17 +#define SCUMM_GAME_HEIGHT 142 +#define SCUMM_GAME_WIDTH 232 + +int textureID; +u16* texture; + +int frameCount; +int currentTimeMillis; + +// Timer Callback +int callbackInterval; +int callbackTimer; +OSystem::TimerProc callback; + +// Scaled +bool scaledMode; +int scX; +int scY; + +int subScX; +int subScY; +int subScTargetX; +int subScTargetY; +int subScreenWidth = SCUMM_GAME_WIDTH; +int subScreenHeight = SCUMM_GAME_HEIGHT; +int subScreenScale = 256; + + + +// Sound +int bufferSize; +s16* soundBuffer; +int bufferFrame; +int bufferRate; +int bufferSamples; +bool soundHiPart; + +// Events +int lastEventFrame; +bool indyFightState; +bool indyFightRight; + +OSystem::SoundProc soundCallback; +void* soundParam; +int lastCallbackFrame; +bool bufferFirstHalf; +bool bufferSecondHalf; + +// Saved buffers +u8* savedBuffer = NULL; +bool highBuffer; +bool displayModeIs8Bit; + +// Game id +u8 gameID; + +bool consoleEnable = true; +bool gameScreenSwap = false; + +MouseMode mouseMode; + +// Sprites +SpriteEntry sprites[128]; +SpriteEntry spritesMain[128]; +int tweak; + +// Shake +int shakePos = 0; + +// Keyboard +bool keyboardEnable = false; +bool leftHandedMode = false; +bool keyboardIcon = false; + +// Touch +int touchScX, touchScY, touchX, touchY; + +// Dragging +int dragStartX, dragStartY; +bool dragging = false; +int dragScX, dragScY; + +// Interface styles +char gameName[32]; + +// 8-bit surface size +int gameWidth = 320; +int gameHeight = 200; + +enum controlType { + CONT_SCUMM_ORIGINAL, + CONT_SCUMM_SAMNMAX, + CONT_SKY, + CONT_SIMON, +}; + +struct gameListType { + char gameId[16]; + controlType control; +}; + +#define NUM_SUPPORTED_GAMES 15 + +gameListType gameList[NUM_SUPPORTED_GAMES] = { + // Unknown game - use normal SCUMM controls + {"unknown", CONT_SCUMM_ORIGINAL}, + + // SCUMM games + {"maniac", CONT_SCUMM_ORIGINAL}, + {"zak", CONT_SCUMM_ORIGINAL}, + {"loom", CONT_SCUMM_ORIGINAL}, + {"indy3", CONT_SCUMM_ORIGINAL}, + {"atlantis", CONT_SCUMM_ORIGINAL}, + {"monkey", CONT_SCUMM_ORIGINAL}, + {"monkey2", CONT_SCUMM_ORIGINAL}, + {"tentacle", CONT_SCUMM_ORIGINAL}, + {"samnmax", CONT_SCUMM_SAMNMAX}, + + // Non-SCUMM games + {"sky", CONT_SKY}, + {"simon1", CONT_SIMON}, + {"simon2", CONT_SIMON}, + {"gob1", CONT_SCUMM_ORIGINAL}, + {"queen", CONT_SCUMM_ORIGINAL} +}; + +gameListType* currentGame = NULL; + +// Stylus +#define ABS(x) ((x)>0?(x):-(x)) + +bool penDown; +bool penHeld; +bool penReleased; +bool penDownLastFrame; +f32 penX, penY; +int keysDownSaved; +int keysReleasedSaved; + +bool penDownSaved; +bool penReleasedSaved; +int penDownFrames; +int touchXOffset = 0; +int touchYOffset = 0; + +u16 savedPalEntry255 = RGB15(31, 31, 31); + + +extern "C" int scummvm_main(int argc, char *argv[]); +void updateStatus(); + +TransferSound soundControl; + +//plays an 8 bit mono sample at 11025Hz +void playSound(const void* data, u32 length, bool loop, bool adpcm, int rate) +{ + + if (!IPC->soundData) { + soundControl.count = 0; + } + + soundControl.data[soundControl.count].data = data; + soundControl.data[soundControl.count].len = length | (loop? 0x80000000: 0x00000000); + soundControl.data[soundControl.count].rate = rate; // 367 samples per frame + soundControl.data[soundControl.count].pan = 64; + soundControl.data[soundControl.count].vol = 127; + soundControl.data[soundControl.count].format = adpcm? 2: 0; + + soundControl.count++; + + DC_FlushAll(); + IPC->soundData = &soundControl; +} + +void stopSound(int channel) { + playSound(NULL, 0, false, false, -channel); +} + +void updateOAM() { + DC_FlushAll(); + dmaCopy(sprites, OAM_SUB, 128 * sizeof(SpriteEntry)); + dmaCopy(spritesMain, OAM, 128 * sizeof(SpriteEntry)); +} + +void setGameSize(int width, int height) { + gameWidth = width; + gameHeight = height; +} + +int getGameWidth() { + return gameWidth; +} + +int getGameHeight() { + return gameHeight; +} + +void initSprites() { + for(int i = 0; i < 128; i++) { + sprites[i].attribute[0] = ATTR0_DISABLED; + sprites[i].attribute[1] = 0; + sprites[i].attribute[2] = 0; + sprites[i].attribute[3] = 0; + } + + for(int i = 0; i < 128; i++) { + spritesMain[i].attribute[0] = ATTR0_DISABLED; + spritesMain[i].attribute[1] = 0; + spritesMain[i].attribute[2] = 0; + spritesMain[i].attribute[3] = 0; + } + + updateOAM(); +} + + +void saveGameBackBuffer() { +#ifdef DISABLE_SCUMM + if (savedBuffer == NULL) savedBuffer = new u8[gameWidth * gameHeight]; + for (int r = 0; r < 200; r++) { + memcpy(savedBuffer + (r * gameWidth), ((u8 *) (get8BitBackBuffer())) + (r * 512), gameWidth); + } +#endif +} + +void restoreGameBackBuffer() { +#ifdef DISABLE_SCUMM + if (savedBuffer) { + for (int r = 0; r < 200; r++) { + memcpy(((u8 *) (BG_GFX_SUB)) + (r * 512), savedBuffer + (r * gameWidth), gameWidth); + memcpy(((u8 *) (get8BitBackBuffer())) + (r * 512), savedBuffer + (r * gameWidth), gameWidth); + } + delete savedBuffer; + savedBuffer = NULL; + } +#endif + +#ifndef DISABLE_SCUMM + memset(get8BitBackBuffer(), 0, 512 * 256); + memset(BG_GFX_SUB, 0, 512 * 256); + if (Scumm::g_scumm) { + Scumm::g_scumm->markRectAsDirty(Scumm::kMainVirtScreen, 0, gameWidth - 1, 0, gameHeight - 1, 1); + Scumm::g_scumm->markRectAsDirty(Scumm::kTextVirtScreen, 0, gameWidth - 1, 0, gameHeight - 1, 1); + Scumm::g_scumm->markRectAsDirty(Scumm::kVerbVirtScreen, 0, gameWidth - 1, 0, gameHeight - 1, 1); + } +#endif + +} + + +void initGame() { + // This is a good time to check for left handed mode since the mode change is done as the game starts. + // There's probably a better way, but hey. +// consolePrintf("initing game\n"); + + setOptions(); + + //strcpy(gameName, ConfMan.getActiveDomain().c_str()); + strcpy(gameName, ConfMan.get("gameid").c_str()); +// consolePrintf("\n\n\n\nCurrent game: '%s' %d\n", gameName, gameName[0]); + + currentGame = &gameList[0]; // Default game + + for (int r = 0; r < NUM_SUPPORTED_GAMES; r++) { + if (!stricmp(gameName, gameList[r].gameId)) { + currentGame = &gameList[r]; +// consolePrintf("Game list num: %d\n", currentGame); + } + } + + +} + +void setLeftHanded(bool enable) { + leftHandedMode = enable; +} + +void setTouchXOffset(int x) { + touchXOffset = x; +} + +void setTouchYOffset(int y) { + touchYOffset = y; +} + +void setUnscaledMode(bool enable) { + scaledMode = !enable; +} + +void displayMode8Bit() { + + u16 buffer[32 * 32]; + + setKeyboardEnable(false); + + if (!displayModeIs8Bit) { + for (int r = 0; r < 32 * 32; r++) { + buffer[r] = ((u16 *) SCREEN_BASE_BLOCK_SUB(4))[r]; + } + } + + + + videoSetMode(MODE_5_2D | (consoleEnable? DISPLAY_BG0_ACTIVE: 0) | DISPLAY_BG3_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP); + videoSetModeSub(MODE_3_2D /*| DISPLAY_BG0_ACTIVE*/ | DISPLAY_BG3_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP); //sub bg 0 will be used to print text + + vramSetBankA(VRAM_A_MAIN_BG_0x6000000); + vramSetBankB(VRAM_B_MAIN_BG_0x6020000); + + vramSetBankC(VRAM_C_SUB_BG_0x6200000); + vramSetBankD(VRAM_D_MAIN_BG_0x6040000); + + vramSetBankH(VRAM_H_LCD); + + BG3_CR = BG_BMP8_512x256 | BG_BMP_BASE(8); + + + + BG3_XDX = (int) (((float) (gameWidth) / 256.0f) * 256); + BG3_XDY = 0; + BG3_YDX = 0; + BG3_YDY = (int) ((200.0f / 192.0f) * 256); + + SUB_BG3_CR = BG_BMP8_512x256; + + + + SUB_BG3_XDX = (int) (subScreenWidth / 256.0f * 256); + SUB_BG3_XDY = 0; + SUB_BG3_YDX = 0; + SUB_BG3_YDY = (int) (subScreenHeight / 192.0f * 256); + + + // Do text stuff + BG0_CR = BG_MAP_BASE(0) | BG_TILE_BASE(1); + BG0_Y0 = 0; + + // Restore palette entry used by text in the front-end + PALETTE_SUB[255] = savedPalEntry255; + + consoleInitDefault((u16*)SCREEN_BASE_BLOCK(0), (u16*)CHAR_BASE_BLOCK(1), 16); + consolePrintSet(0, 23); + + if (!displayModeIs8Bit) { + for (int r = 0; r < 32 * 32; r++) { + ((u16 *) SCREEN_BASE_BLOCK(0))[r] = buffer[r]; + } +// dmaCopyHalfWords(3, (u16 *) SCREEN_BASE_BLOCK(0), buffer, 32 * 32 * 2); + } + + + if (!displayModeIs8Bit) restoreGameBackBuffer(); + displayModeIs8Bit = true; + + POWER_CR &= ~POWER_SWAP_LCDS; + + keyboardEnable = false; + initGame(); + +} + +void setGameID(int id) { + gameID = id; +} + +void dummyHandler() { + REG_IF = IRQ_VBLANK; +} + +void checkSleepMode() { + if (IPC->performArm9SleepMode) { + + consolePrintf("ARM9 Entering sleep mode\n"); + + int intSave = REG_IE; + irqSet(IRQ_VBLANK, dummyHandler); +// int irqHandlerSave = (int) IRQ_HANDLER; + REG_IE = IRQ_VBLANK; + //IRQ_HANDLER = dummyHandler; + + int powerSave = POWER_CR; + POWER_CR &= ~POWER_ALL; + + while (IPC->performArm9SleepMode) { + swiWaitForVBlank(); + } + + POWER_CR = powerSave; +// IRQ_HANDLER = (void (*)()) irqHandlerSave; + irqSet(IRQ_VBLANK, VBlankHandler); + REG_IE = intSave; + + consolePrintf("ARM9 Waking from sleep mode\n"); + } +} + +void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor) { + if (currentGame->control != CONT_SCUMM_SAMNMAX) + return; + + uint16 border = RGB15(24,24,24) | 0x8000; + + + int off = 48*64; + memset(SPRITE_GFX_SUB+off, 0, 64*64*2); + + int pos = 190 - (w+2); + + + + // make border + for (uint i=0; i<w+2; i++) { + SPRITE_GFX_SUB[off+i] = border; + SPRITE_GFX_SUB[off+(31)*64+i] = border; + } + for (uint i=1; i<31; i++) { + SPRITE_GFX_SUB[off+(i*64)] = border; + SPRITE_GFX_SUB[off+(i*64)+(w+1)] = border; + } + + int offset = (32 - h) >> 1; + + for (uint y=0; y<h; y++) { + for (uint x=0; x<w; x++) { + int color = icon[y*w+x]; + if (color == keycolor) { + SPRITE_GFX_SUB[off+(y+1+offset)*64+(x+1)] = 0x8000; // black background + } else { + SPRITE_GFX_SUB[off+(y+1+offset)*64+(x+1)] = BG_PALETTE[color] | 0x8000; + } + } + } + + sprites[1].attribute[0] = ATTR0_BMP | 150; + sprites[1].attribute[1] = ATTR1_SIZE_64 | pos; + sprites[1].attribute[2] = ATTR2_ALPHA(1) | 48; +} + + + + +void displayMode16Bit() { + + u16 buffer[32 * 32 * 2]; + + + if (displayModeIs8Bit) { + saveGameBackBuffer(); + for (int r = 0; r < 32 * 32; r++) { + buffer[r] = ((u16 *) SCREEN_BASE_BLOCK(0))[r]; + } + } + + + videoSetMode(MODE_5_2D | /*DISPLAY_BG0_ACTIVE |*/ DISPLAY_BG3_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP); + videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE |/* DISPLAY_BG1_ACTIVE |*/ DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP); //sub bg 0 will be used to print text + + vramSetBankA(VRAM_A_MAIN_BG); + vramSetBankB(VRAM_B_MAIN_BG); + vramSetBankC(VRAM_C_MAIN_BG); + vramSetBankD(VRAM_D_MAIN_BG); + vramSetBankH(VRAM_H_SUB_BG); + + BG3_CR = BG_BMP16_512x256; + highBuffer = false; + + BG3_XDX = (int) (1.25f * 256); + BG3_XDY = 0; + BG3_YDX = 0; + BG3_YDY = (int) ((200.0f / 192.0f) * 256); + + memset(BG_GFX, 0, 512 * 256 * 2); + + savedPalEntry255 = PALETTE_SUB[255]; + PALETTE_SUB[255] = RGB15(31,31,31);//by default font will be rendered with color 255 + + // Do text stuff + SUB_BG0_CR = BG_MAP_BASE(4) | BG_TILE_BASE(0); + SUB_BG0_Y0 = 0; + + consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(4), (u16*)CHAR_BASE_BLOCK_SUB(0), 16); + + if (displayModeIs8Bit) { + //dmaCopyHalfWords(3, (u16 *) SCREEN_BASE_BLOCK_SUB(0), buffer, 32 * 32 * 2); + for (int r = 0; r < 32 * 32; r++) { + ((u16 *) SCREEN_BASE_BLOCK_SUB(4))[r] = buffer[r]; + } + } + + consolePrintSet(0, 23); + consolePrintf("\n"); + + // Show keyboard + SUB_BG1_CR = BG_TILE_BASE(1) | BG_MAP_BASE(12); + //drawKeyboard(1, 12); + + POWER_CR &= ~POWER_SWAP_LCDS; + + + + displayModeIs8Bit = false; +} + + +void displayMode16BitFlipBuffer() { + if (!displayModeIs8Bit) { + u16* back = get16BitBackBuffer(); + +// highBuffer = !highBuffer; +// BG3_CR = BG_BMP16_512x256 | BG_BMP_RAM(highBuffer? 1: 0); + + for (int r = 0; r < 512 * 256; r++) { + *(BG_GFX + r) = *(back + r); + } + } +} + +void setShakePos(int shakePos) { + shakePos = shakePos; +} + + +u16* get16BitBackBuffer() { + return BG_GFX + 0x20000; +} + +u16* get8BitBackBuffer() { + return BG_GFX + 0x10000; // 16bit qty! +} + +void setSoundProc(OSystem::SoundProc proc, void* param) { +// consolePrintf("Set sound callback"); + soundCallback = proc; + soundParam = param; +} + +// The sound system in ScummVM seems to always return stereo interleaved samples. +// Here, I'm treating an 11Khz stereo stream as a 22Khz mono stream, which works sorta ok, but is +// a horrible bodge. Any advice on how to change the engine to output mono would be greatly +// appreciated. +void doSoundCallback() { + if ((soundCallback)) { + lastCallbackFrame = frameCount; + + for (int r = IPC->playingSection; r < IPC->playingSection + 4; r++) { + int chunk = r & 3; + + if (IPC->fillNeeded[chunk]) { + IPC->fillNeeded[chunk] = false; + DC_FlushAll(); + soundCallback(soundParam, (byte *) (soundBuffer + ((bufferSamples >> 2) * chunk)), bufferSamples >> 1); + IPC->fillNeeded[chunk] = false; + DC_FlushAll(); + } + + } + + } +} + +void doTimerCallback() { + if (callback) { + if (callbackTimer <= 0) { + callbackTimer += callbackInterval; + callback(callbackInterval); + } + } +} + +void soundUpdate() { + if ((bufferFrame == 0)) { +// playSound(soundBuffer, (bufferSamples * 2), true); + } +// consolePrintf("%x\n", IPC->test); + + + if (bufferFrame == 0) { +// bufferFirstHalf = true; + } + if (bufferFrame == bufferSize >> 1) { + //bufferSecondHalf = true; + } + + bufferFrame++; + if (bufferFrame == bufferSize) { + bufferFrame = 0; + } +} + +void memoryReport() { + int r = 0; + int* p; + do { + p = (int *) malloc(r * 8192); + free(p); + r++; + } while ((p) && (r < 512)); + + int t = -1; + void* block[1024]; + do { + t++; + block[t] = (int *) malloc(4096); + } while ((t < 1024) && (block[t])); + + for (int q = 0; q < t; q++) { + free(block[q]); + } + + consolePrintf("Free: %dK, Largest: %dK\n", t * 4, r * 8); +} + + +void addIndyFightingKeys() { + OSystem_DS* system = OSystem_DS::instance(); + OSystem::Event event; + + event.type = OSystem::EVENT_KEYDOWN; + event.kbd.flags = 0; + + if ((getKeysDown() & KEY_L)) { + indyFightRight = false; + } + + if ((getKeysDown() & KEY_R)) { + indyFightRight = true; + } + + if ((getKeysDown() & KEY_UP)) { + event.kbd.keycode = '8'; + event.kbd.ascii = '8'; + system->addEvent(event); + } + if ((getKeysDown() & KEY_LEFT)) { + event.kbd.keycode = '4'; + event.kbd.ascii = '4'; + system->addEvent(event); + } + if ((getKeysDown() & KEY_RIGHT)) { + event.kbd.keycode = '6'; + event.kbd.ascii = '6'; + system->addEvent(event); + } + if ((getKeysDown() & KEY_DOWN)) { + event.kbd.keycode = '2'; + event.kbd.ascii = '2'; + system->addEvent(event); + } + + if (indyFightRight) { + + if ((getKeysDown() & KEY_X)) { + event.kbd.keycode = '9'; + event.kbd.ascii = '9'; + system->addEvent(event); + } + if ((getKeysDown() & KEY_A)) { + event.kbd.keycode = '6'; + event.kbd.ascii = '6'; + system->addEvent(event); + } + if ((getKeysDown() & KEY_B)) { + event.kbd.keycode = '3'; + event.kbd.ascii = '3'; + system->addEvent(event); + } + + } else { + + if ((getKeysDown() & KEY_X)) { + event.kbd.keycode = '7'; + event.kbd.ascii = '7'; + system->addEvent(event); + } + if ((getKeysDown() & KEY_A)) { + event.kbd.keycode = '4'; + event.kbd.ascii = '4'; + system->addEvent(event); + } + if ((getKeysDown() & KEY_B)) { + event.kbd.keycode = '1'; + event.kbd.ascii = '1'; + system->addEvent(event); + } + + } + + + if ((getKeysDown() & KEY_Y)) { + event.kbd.keycode = '5'; + event.kbd.ascii = '5'; + system->addEvent(event); + } +} + + +void setKeyboardEnable(bool en) { + if (en == keyboardEnable) return; + keyboardEnable = en; + u16* backupBank = (u16 *) 0x6040000; + + if (keyboardEnable) { + + + DS::drawKeyboard(1, 12, backupBank); + + + SUB_BG1_CR = BG_TILE_BASE(1) | BG_MAP_BASE(12); + + if (displayModeIs8Bit) { + SUB_DISPLAY_CR |= DISPLAY_BG1_ACTIVE; // Turn on keyboard layer + SUB_DISPLAY_CR &= ~DISPLAY_BG3_ACTIVE; // Turn off game layer + } else { + SUB_DISPLAY_CR |= DISPLAY_BG1_ACTIVE; // Turn on keyboard layer + SUB_DISPLAY_CR &= ~DISPLAY_BG0_ACTIVE; // Turn off console layer + } + lcdSwap(); + } else { + + + // Restore the palette that the keyboard has used + for (int r = 0; r < 256; r++) { + BG_PALETTE_SUB[r] = BG_PALETTE[r]; + } + + + //restoreVRAM(1, 12, backupBank); + + if (displayModeIs8Bit) { + // Copy the sub screen VRAM from the top screen - they should always be + // the same. + for (int r = 0; r < (512 * 256) >> 1; r++) { + BG_GFX_SUB[r] = get8BitBackBuffer()[r]; + } + + SUB_DISPLAY_CR &= ~DISPLAY_BG1_ACTIVE; // Turn off keyboard layer + SUB_DISPLAY_CR |= DISPLAY_BG3_ACTIVE; // Turn on game layer + } else { + SUB_DISPLAY_CR &= ~DISPLAY_BG1_ACTIVE; // Turn off keyboard layer + SUB_DISPLAY_CR |= DISPLAY_BG0_ACTIVE; // Turn on console layer + } + + lcdSwap(); + } +} + +bool getKeyboardEnable() { + return keyboardEnable; +} + +bool getIsDisplayMode8Bit() { + return displayModeIs8Bit; +} + +void addEventsToQueue() { + OSystem_DS* system = OSystem_DS::instance(); + OSystem::Event event; + + + + + if (system->isEventQueueEmpty()) { + +/* + if (getKeysDown() & KEY_L) { + tweak--; + consolePrintf("Tweak: %d\n", tweak); + IPC->tweakChanged = true; + } + + + if (getKeysDown() & KEY_R) { + tweak++; + consolePrintf("Tweak: %d\n", tweak); + IPC->tweakChanged = true; + } + */ + if ((keysHeld() & KEY_L) && (keysHeld() & KEY_R)) { + memoryReport(); + } + + if (displayModeIs8Bit) { + + if (!indyFightState) { + + + if ((getKeysDown() & KEY_B) && (!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) { + // consolePrintf("Pressing Esc"); + + event.type = OSystem::EVENT_KEYDOWN; + event.kbd.keycode = 27; + event.kbd.ascii = 27; + event.kbd.flags = 0; + system->addEvent(event); + } + + } + + + + if ((!getIndyFightState()) && (getKeysDown() & KEY_Y)) { + consoleEnable = !consoleEnable; + if (displayModeIs8Bit) { + displayMode8Bit(); + } else { + displayMode16Bit(); + } + } + + + if (!((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (!getIndyFightState())) { + + if ((getKeysDown() & KEY_A) && (!indyFightState)) { + gameScreenSwap = !gameScreenSwap; + } + + if (!getPenHeld() || (mouseMode != MOUSE_HOVER)) { + if (getKeysDown() & KEY_LEFT) { + mouseMode = MOUSE_LEFT; + } + if (getKeysDown() & KEY_RIGHT) { + if (currentGame->control != CONT_SCUMM_SAMNMAX) { + mouseMode = MOUSE_RIGHT; + } else { + // If we're playing sam and max, click and release the right mouse + // button to change verb + OSystem::Event event; + + event.type = OSystem::EVENT_RBUTTONDOWN; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + + event.type = OSystem::EVENT_RBUTTONUP; + system->addEvent(event); + } + } + if (getKeysDown() & KEY_UP) { + mouseMode = MOUSE_HOVER; + } + } + + + + } + + if ((getKeysDown() & KEY_SELECT)) { + //scaledMode = !scaledMode; + //scY = 4; + showOptionsDialog(); + } + + + } + + if (!getIndyFightState() && !((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (getKeysDown() & KEY_X)) { + setKeyboardEnable(!keyboardEnable); + } + + updateStatus(); + + OSystem::Event event; + + if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) { + event.type = OSystem::EVENT_MOUSEMOVE; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + //consolePrintf("x=%d y=%d \n", getPenX(), getPenY()); + } + + if (!keyboardEnable) { + if ((mouseMode != MOUSE_HOVER) || (!displayModeIs8Bit)) { + if (getPenDown() && (!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) { + event.type = ((mouseMode == MOUSE_LEFT) || (!displayModeIs8Bit))? OSystem::EVENT_LBUTTONDOWN: OSystem::EVENT_RBUTTONDOWN; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + } + + if (getPenReleased()) { + event.type = mouseMode == MOUSE_LEFT? OSystem::EVENT_LBUTTONUP: OSystem::EVENT_RBUTTONUP; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + } + } else { + // In hover mode, D-pad left and right click the mouse when the pen is on the screen + + if (getPenHeld()) { + if (getKeysDown() & KEY_LEFT) { + event.type = OSystem::EVENT_LBUTTONDOWN; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + } + /* if (getKeysReleased() & KEY_LEFT) { + event.type = OSystem::EVENT_LBUTTONUP; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + }*/ + + if (getKeysDown() & KEY_RIGHT) { + event.type = OSystem::EVENT_RBUTTONDOWN; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + } + /*if (getKeysReleased() & KEY_RIGHT) { + event.type = OSystem::EVENT_RBUTTONUP; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + }*/ + } + } + + if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R)) && (displayModeIs8Bit)) { + // Controls specific to the control method + + + if (currentGame->control == CONT_SKY) { + // Extra controls for Benieth a Steel Sky + if ((getKeysDown() & KEY_DOWN)) { + penY = 0; + penX = 0; // Show inventory by moving mouse onto top line + } + } + + if (currentGame->control == CONT_SIMON) { + // Extra controls for Simon the Sorcerer + if ((getKeysDown() & KEY_DOWN)) { + OSystem::Event event; + + event.type = OSystem::EVENT_KEYDOWN; + event.kbd.keycode = '#'; // F10 or # - show hotspots + event.kbd.ascii = '#'; + event.kbd.flags = 0; + system->addEvent(event); +// consolePrintf("F10\n"); + } + } + + if (currentGame->control == CONT_SCUMM_ORIGINAL) { + // Extra controls for Scumm v1-5 games + if ((getKeysDown() & KEY_DOWN)) { + OSystem::Event event; + + event.type = OSystem::EVENT_KEYDOWN; + event.kbd.keycode = '.'; // Full stop - skips current dialogue line + event.kbd.ascii = '.'; + event.kbd.flags = 0; + system->addEvent(event); + } + + if (indyFightState) { + addIndyFightingKeys(); + } + + } + + } + } + + if (!displayModeIs8Bit) { + // Front end controls + + if (leftHandedSwap(getKeysDown()) & KEY_UP) { + event.type = OSystem::EVENT_KEYDOWN; + event.kbd.keycode = SDLK_UP; + event.kbd.ascii = 0; + event.kbd.flags = 0; + system->addEvent(event); + + event.type = OSystem::EVENT_KEYUP; + system->addEvent(event); + } + + if (leftHandedSwap(getKeysDown()) & KEY_DOWN) { + event.type = OSystem::EVENT_KEYDOWN; + event.kbd.keycode = SDLK_DOWN; + event.kbd.ascii = 0; + event.kbd.flags = 0; + system->addEvent(event); + + event.type = OSystem::EVENT_KEYUP; + system->addEvent(event); + } + + if (leftHandedSwap(getKeysDown()) & KEY_A) { + event.type = OSystem::EVENT_KEYDOWN; + event.kbd.keycode = SDLK_RETURN; + event.kbd.ascii = 0; + event.kbd.flags = 0; + system->addEvent(event); + + event.type = OSystem::EVENT_KEYUP; + system->addEvent(event); + } + + } + + + if ((getKeysDown() & KEY_START)) { + event.type = OSystem::EVENT_KEYDOWN; + event.kbd.keycode = 319; // F5 + event.kbd.ascii = 319; + event.kbd.flags = 0; + system->addEvent(event); +/* + event.type = OSystem::EVENT_KEYUP; + event.kbd.keycode = 319; // F5 + event.kbd.ascii = 319; + system->addEvent(event);*/ + +// consolePrintf("Pressing F5"); + } + + + if (keyboardEnable) { + DS::addKeyboardEvents(); + } + + consumeKeys(); + + consumePenEvents(); + + } +} + +void updateStatus() { + int offs; + + if (displayModeIs8Bit) { + switch (mouseMode) { + case MOUSE_LEFT: { + offs = 16; + break; + } + case MOUSE_RIGHT: { + offs = 32; + break; + } + case MOUSE_HOVER: { + offs = 0; + break; + } + default: { + // Nothing! + offs = 0; + break; + } + } + + + sprites[0].attribute[0] = ATTR0_BMP | 150; + sprites[0].attribute[1] = ATTR1_SIZE_32 | 208; + sprites[0].attribute[2] = ATTR2_ALPHA(1)| offs; + + if (indyFightState) { + sprites[2].attribute[0] = ATTR0_BMP | 150; + sprites[2].attribute[1] = ATTR1_SIZE_32 | (190 - 32) | (indyFightRight? 0: ATTR1_FLIP_X); + sprites[2].attribute[2] = ATTR2_ALPHA(1)| 48; + } else { + sprites[2].attribute[0] = ATTR0_DISABLED; + sprites[2].attribute[1] = 0; + sprites[2].attribute[2] = 0; + } + } else { + sprites[0].attribute[0] = ATTR0_DISABLED; + sprites[1].attribute[0] = ATTR0_DISABLED; + sprites[2].attribute[0] = ATTR0_DISABLED; + sprites[3].attribute[0] = ATTR0_DISABLED; + } + + if ((keyboardIcon) && (!keyboardEnable) && (!displayModeIs8Bit)) { + spritesMain[0].attribute[0] = ATTR0_BMP | 160; + spritesMain[0].attribute[1] = ATTR1_SIZE_32 | 0; + spritesMain[0].attribute[2] = ATTR2_ALPHA(1) | 64; + } else { + spritesMain[0].attribute[0] = ATTR0_DISABLED; + spritesMain[0].attribute[1] = 0; + spritesMain[0].attribute[2] = 0; + spritesMain[0].attribute[3] = 0; + } + +} + +void soundBufferEmptyHandler() { + REG_IF = IRQ_TIMER2; + + if (soundHiPart) { +// bufferSecondHalf = true; + } else { +// bufferFirstHalf = true; + } + + soundHiPart = !soundHiPart; +} + +void setMainScreenScroll(int x, int y) { + if (gameScreenSwap) { + SUB_BG3_CX = x + (((frameCount & 1) == 0)? 64: 0); + SUB_BG3_CY = y; + } else { + BG3_CX = x + (((frameCount & 1) == 0)? 64: 0); + BG3_CY = y; + + touchX = x >> 8; + touchY = y >> 8; + } +} + +void setMainScreenScale(int x, int y) { + if (gameScreenSwap) { + SUB_BG3_XDX = x; + SUB_BG3_XDY = 0; + SUB_BG3_YDX = 0; + SUB_BG3_YDY = y; + } else { + BG3_XDX = x; + BG3_XDY = 0; + BG3_YDX = 0; + BG3_YDY = y; + + touchScX = x; + touchScY = y; + } +} + +void setZoomedScreenScroll(int x, int y) { + if (gameScreenSwap) { + BG3_CX = x + (((frameCount & 1) == 0)? 64: 0); + BG3_CY = y; + + touchX = x >> 8; + touchY = y >> 8; + } else { + SUB_BG3_CX = x + (((frameCount & 1) == 0)? 64: 0); + SUB_BG3_CY = y; + } +} + +void setZoomedScreenScale(int x, int y) { + if (gameScreenSwap) { + BG3_XDX = x; + BG3_XDY = 0; + BG3_YDX = 0; + BG3_YDY = y; + + touchScX = x; + touchScY = y; + } else { + SUB_BG3_XDX = x; + SUB_BG3_XDY = 0; + SUB_BG3_YDX = 0; + SUB_BG3_YDY = y; + } +} + +void VBlankHandler(void) { +// BG_PALETTE[0] = RGB15(31, 31, 31); +// if (*((int *) (0x023FFF00)) != 0xBEEFCAFE) { + // consolePrintf("Guard band overwritten!"); +// } + +// consolePri ntf("X:%d Y:%d\n", getPenX(), getPenY()); + + + IPC->tweak = tweak; + soundUpdate(); + + + + + if ((!gameScreenSwap) && (!(getKeysHeld() & KEY_L) && !(getKeysHeld() & KEY_R))) { + if (currentGame) { + if (currentGame->control != CONT_SCUMM_SAMNMAX) { + if (getPenHeld() && (getPenY() < SCUMM_GAME_HEIGHT)) { + setTopScreenTarget(getPenX(), getPenY()); + } + } else { + if (getPenHeld()) { + setTopScreenTarget(getPenX(), getPenY()); + } + } + } + } + + + penUpdate(); + keysUpdate(); + + + frameCount++; + + + + if (callback) { + callbackTimer -= FRAME_TIME; + } + + if ((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) { + + if ((!dragging) && (getPenHeld()) && (penDownFrames > 5)) { + dragging = true; + dragStartX = penX; + dragStartY = penY; + + if (gameScreenSwap) { + dragScX = subScTargetX; + dragScY = subScTargetY; + } else { + dragScX = scX; + dragScY = scY; + } + + + } + + if ((dragging) && (!getPenHeld())) { + dragging = false; + } + + if (dragging) { + + if (gameScreenSwap) { + subScTargetX = dragScX + ((dragStartX - penX) << 8); + subScTargetY = dragScY + ((dragStartY - penY) << 8); + } else { + scX = dragScX + ((dragStartX - penX)); + scY = dragScY + ((dragStartY - penY)); + } + +// consolePrintf("X:%d Y:%d\n", dragStartX - penX, dragStartY - penY); + } + } + + +/* if ((frameCount & 1) == 0) { + SUB_BG3_CX = subScX; + } else { + SUB_BG3_CX = subScX + 64; + } + + SUB_BG3_CY = subScY + (shakePos << 8);*/ + + /*SUB_BG3_XDX = (int) (subScreenWidth / 256.0f * 256); + SUB_BG3_XDY = 0; + SUB_BG3_YDX = 0; + SUB_BG3_YDY = (int) (subScreenHeight / 192.0f * 256);*/ + + + if ((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) { + if ((getKeysHeld() & KEY_A) && (subScreenScale < 256)) { + subScreenScale += 3; + } + + if ((getKeysHeld() & KEY_B) && (subScreenScale > 128)) { + subScreenScale -=3; + } + + int xCenter = subScTargetX + ((subScreenWidth >> 1) << 8); + int yCenter = subScTargetY + ((subScreenHeight >> 1) << 8); + + subScreenWidth = SCUMM_GAME_WIDTH * subScreenScale >> 8; + subScreenHeight = SCUMM_GAME_HEIGHT * subScreenScale >> 8; + + subScTargetX = xCenter - ((subScreenWidth >> 1) << 8); + subScTargetY = yCenter - ((subScreenHeight >> 1) << 8); + + + + + if (subScTargetX < 0) subScTargetX = 0; + if (subScTargetX > (gameWidth - subScreenWidth) << 8) subScTargetX = (gameWidth - subScreenWidth) << 8; + + if (subScTargetY < 0) subScTargetY = 0; + if (subScTargetY > (gameHeight - subScreenHeight) << 8) subScTargetY = (gameHeight - subScreenHeight) << 8; + } + + subScX += (subScTargetX - subScX) >> 2; + subScY += (subScTargetY - subScY) >> 2; + + if (displayModeIs8Bit) { + + if ((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) { + + int offsX = 0, offsY = 0; + + + if (getKeysHeld() & KEY_LEFT) { + offsX -= 1; + } + + if (getKeysHeld() & KEY_RIGHT) { + offsX += 1; + } + + if (getKeysHeld() & KEY_UP) { + offsY -= 1; + } + + if (getKeysHeld() & KEY_DOWN) { + offsY += 1; + } + + if (((gameScreenSwap) && (getKeysHeld() & KEY_L)) || ((!gameScreenSwap) && (getKeysHeld() & KEY_R))) { + subScTargetX += offsX << 8; + subScTargetY += offsY << 8; + } else { + scX += offsX; + scY += offsY; + } + } + + if (!scaledMode) { + + if (scX + 256 > gameWidth - 1) { + scX = gameWidth - 1 - 256; + } + + if (scX < 0) { + scX = 0; + } + + if (scY + 192 > gameHeight - 1) { + scY = gameHeight - 1 - 192; + } + + if (scY < 0) { + scY = 0; + } + + setZoomedScreenScroll(subScX, subScY); + setZoomedScreenScale(subScreenWidth, (subScreenHeight * 256) / 192); + + + setMainScreenScroll(scX << 8, (scY << 8) + (shakePos << 8)); + setMainScreenScale(256, 256); // 1:1 scale + + } else { + + if (scY > gameHeight - 192 - 1) { + scY = gameHeight - 192 - 1; + } + + if (scY < 0) { + scY = 0; + } + + setZoomedScreenScroll(subScX, subScY); + setZoomedScreenScale(subScreenWidth, (subScreenHeight * 256) / 192); + + setMainScreenScroll(64, (scY << 8) + (shakePos << 8)); + setMainScreenScale(320, 256); // 1:1 scale + + } + } else { + setZoomedScreenScroll(0, 0); + setZoomedScreenScale(320, 256); + + setMainScreenScroll(0, 0); + setMainScreenScale(320, 256); // 1:1 scale + } + + // Enable on screen keyboard when pen taps icon + if ((keyboardIcon) && (penX < 32) && (penY > 160) && (penHeld)) { + setKeyboardEnable(true); + } + + if (keyboardEnable) { + if (DS::getKeyboardClosed()) { + setKeyboardEnable(false); + } + } + + updateOAM(); + + //PALETTE[0] = RGB15(0, 0, 0); + REG_IF = IRQ_VBLANK; +} + +int getMillis() { + return currentTimeMillis; +// return frameCount * FRAME_TIME; +} + +void setTimerCallback(OSystem::TimerProc proc, int interval) { +// consolePrintf("Set timer proc %x, int %d\n", proc, interval); + callback = proc; + callbackInterval = interval; + callbackTimer = interval; +} + +void timerTickHandler() { + REG_IF = IRQ_TIMER0; + if ((callback) && (callbackTimer > 0)) { + callbackTimer--; + } + currentTimeMillis++; +} + +void setTalkPos(int x, int y) { +// if (gameID != Scumm::GID_SAMNMAX) { +// setTopScreenTarget(x, 0); +// } else { + setTopScreenTarget(x, y); +// } +} + +void setTopScreenTarget(int x, int y) { + subScTargetX = (x - (subScreenWidth >> 1)); + subScTargetY = (y - (subScreenHeight >> 1)); + + if (subScTargetX < 0) subScTargetX = 0; + if (subScTargetX > gameWidth - subScreenWidth) subScTargetX = gameWidth - subScreenWidth; + + if (subScTargetY < 0) subScTargetY = 0; + if (subScTargetY > gameHeight - subScreenHeight) subScTargetY = gameHeight - subScreenHeight; + + subScTargetX <<=8; + subScTargetY <<=8; +} + +void initHardware() { + // Guard band +//((int *) (0x023FFF00)) = 0xBEEFCAFE; + + + penInit(); + + powerON(POWER_ALL); +/* vramSetBankA(VRAM_A_MAIN_BG); + vramSetBankB(VRAM_B_MAIN_BG); + vramSetBankC(VRAM_C_SUB_BG); */ + vramSetBankI(VRAM_I_SUB_SPRITE); + vramSetBankG(VRAM_G_MAIN_SPRITE); + + currentTimeMillis = 0; + + +/* + // Set up a millisecond counter + TIMER0_CR = 0; + TIMER0_DATA = 0xFFFF; + TIMER0_CR = TIMER_ENABLE | TIMER_CASCADE; +*/ + + + + PALETTE[255] = RGB15(0,31,0); + + // Allocate save buffer for game screen +// savedBuffer = new u8[320 * 200]; + displayMode16Bit(); + + memset(BG_GFX, 0, 512 * 256 * 2); + scaledMode = true; + scX = 0; + scY = 0; + subScX = 0; + subScY = 0; + subScTargetX = 0; + subScTargetY = 0; + + //lcdSwap(); + POWER_CR &= ~POWER_SWAP_LCDS; + + frameCount = 0; + callback = NULL; + +// vramSetBankH(VRAM_H_SUB_BG); + + +// // Do text stuff + //BG0_CR = BG_MAP_BASE(0) | BG_TILE_BASE(1); +// BG0_Y0 = 48; + + PALETTE[255] = RGB15(31,31,31);//by default font will be rendered with color 255 + + //consoleInit() is a lot more flexible but this gets you up and running quick +// consoleInitDefault((u16*)SCREEN_BASE_BLOCK(0), (u16*)CHAR_BASE_BLOCK(1), 16); + //consolePrintSet(0, 6); + + //irqs are nice + irqInit(); +// irqInitHandler(); + irqSet(IRQ_VBLANK, VBlankHandler); + irqSet(IRQ_TIMER0, timerTickHandler); + irqSet(IRQ_TIMER2, soundBufferEmptyHandler); + + irqEnable(IRQ_VBLANK); + irqEnable(IRQ_TIMER0); + irqEnable(IRQ_TIMER2); + + + // Set up a millisecond timer + TIMER0_CR = 0; + TIMER0_DATA = (u32) TIMER_FREQ(1000); + TIMER0_CR = TIMER_ENABLE | TIMER_DIV_1 | TIMER_IRQ_REQ; + REG_IME = 1; + + PALETTE[255] = RGB15(0,0,31); + + initSprites(); + +// videoSetModeSub(MODE_3_2D | DISPLAY_BG0_ACTIVE | DISPLAY_BG3_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP); //sub bg 0 will be used to print text + + // Convert texture from 24bit 888 to 16bit 1555, remembering to set top bit! + u8* srcTex = (u8 *) icons_raw; + for (int r = 32 * 160 ; r >= 0; r--) { + SPRITE_GFX_SUB[r] = 0x8000 | (srcTex[r * 3] >> 3) | ((srcTex[r * 3 + 1] >> 3) << 5) | ((srcTex[r * 3 + 2] >> 3) << 10); + SPRITE_GFX[r] = 0x8000 | (srcTex[r * 3] >> 3) | ((srcTex[r * 3 + 1] >> 3) << 5) | ((srcTex[r * 3 + 2] >> 3) << 10); + } + + WAIT_CR &= ~(0x0080); + REG_WRAM_CNT = 0; + +} + + +void setKeyboardIcon(bool enable) { + keyboardIcon = enable; +} + +bool getKeyboardIcon() { + return keyboardIcon; +} + + +//////////////////// +// Pen stuff +//////////////////// + + +void penInit() { + penDown = false; + penHeld = false; + penReleased = false; + penDownLastFrame = false; + penDownSaved = false; + penReleasedSaved = false; + penDownFrames = 0; + consumeKeys(); +} + +void penUpdate() { + +// if (getKeysHeld() & KEY_L) consolePrintf("%d, %d penX=%d, penY=%d tz=%d\n", IPC->touchXpx, IPC->touchYpx, penX, penY, IPC->touchZ1); + + if ((penDownFrames > 1)) { // Is this right? Dunno, but it works for me. + + if ((penHeld)) { + penHeld = true; + penDown = false; + + if ((IPC->touchZ1 > 0) && (IPC->touchXpx > 0) && (IPC->touchYpx > 0)) { + penX = IPC->touchXpx + touchXOffset; + penY = IPC->touchYpx + touchYOffset; + } + + } else { + penDown = true; + penHeld = true; + penDownSaved = true; + + //if ( (ABS(penX - IPC->touchXpx) < 10) && (ABS(penY - IPC->touchYpx) < 10) ) { + if ((IPC->touchZ1 > 0) && (IPC->touchXpx > 0) && (IPC->touchYpx > 0)) { + penX = IPC->touchXpx; + penY = IPC->touchYpx; + } + //} + } + + } else { + if (penHeld) { + penReleased = true; + penReleasedSaved = true; + } else { + penReleased = false; + } + + penDown = false; + penHeld = false; + } + + + if ((IPC->touchZ1 > 0) || ((penDownFrames == 2)) ) { + penDownLastFrame = true; + penDownFrames++; + } else { + penDownLastFrame = false; + penDownFrames = 0; + } + +} + +int leftHandedSwap(int keys) { + // Start and select are unchanged + if (leftHandedMode) { + int result = keys & (~(KEY_R | KEY_L | KEY_Y | KEY_A | KEY_B | KEY_X | KEY_LEFT | KEY_RIGHT | KEY_UP | KEY_DOWN)); + + if (keys & KEY_L) result |= KEY_R; + if (keys & KEY_R) result |= KEY_L; + + if (keys & KEY_LEFT) result |= KEY_Y; + if (keys & KEY_RIGHT) result |= KEY_A; + if (keys & KEY_DOWN) result |= KEY_B; + if (keys & KEY_UP) result |= KEY_X; + + if (keys & KEY_Y) result |= KEY_LEFT; + if (keys & KEY_A) result |= KEY_RIGHT; + if (keys & KEY_B) result |= KEY_DOWN; + if (keys & KEY_X) result |= KEY_UP; + + return result; + } else { + return keys; + } +} + +void keysUpdate() { + scanKeys(); + keysDownSaved |= leftHandedSwap(keysDown()); + keysReleasedSaved |= leftHandedSwap(keysUp()); +} + +int getKeysDown() { + return keysDownSaved; +} + +int getKeysHeld() { + return leftHandedSwap(keysHeld()); +} + +int getKeysReleased() { + return keysReleasedSaved; +} + +void consumeKeys() { + keysDownSaved = 0; + keysReleasedSaved = 0; +} + +bool getPenDown() { + return penDownSaved; +} + +bool getPenHeld() { + return penHeld; +} + +bool getPenReleased() { + return penReleasedSaved; +} + +void consumePenEvents() { + penDownSaved = false; + penReleasedSaved = false; +} + +int getPenX() { + int x = ((penX * touchScX) >> 8) + touchX; + x = x < 0? 0: (x > gameWidth - 1? gameWidth - 1: x); + return x; +} + +int getPenY() { + int y = ((penY * touchScY) >> 8) + touchY; + y = y < 0? 0: (y > gameHeight - 1? gameHeight - 1: y); + return y; +} + +GLvector getPenPos() { + GLvector v; + + v.x = (penX * inttof32(1)) / SCREEN_WIDTH; + v.y = (penY * inttof32(1)) / SCREEN_HEIGHT; + + return v; +} + +void formatSramOption() { + consolePrintf("The following files are present in save RAM:\n"); + DSSaveFileManager::instance()->listFiles(); + + consolePrintf("\nAre you sure you want to\n"); + consolePrintf("DELETE all files?\n"); + consolePrintf("A = Yes, X = No\n"); + + while (true) { + if (keysHeld() & KEY_A) { + DSSaveFileManager::instance()->formatSram(); + consolePrintf("SRAM cleared!\n"); + return; + } + + if (keysHeld() & KEY_X) { + consolePrintf("Whew, that was close!\n"); + return; + } + } +} + + +void setIndyFightState(bool st) { + indyFightState = st; + indyFightRight = true; +} + +bool getIndyFightState() { + return indyFightState; +} + +///////////////// +// GBAMP +///////////////// + +bool GBAMPAvail = false; + +void initGBAMP() { + FAT_InitFiles(); + if (disc_IsInserted()) { + GBAMPAvail = true; + consolePrintf("Found flash card reader!\n"); + } else { + GBAMPAvail = false; + consolePrintf("Flash card reader not found!\n"); + } +} + +bool isGBAMPAvailable() { + return GBAMPAvail; +} + + + +///////////////// +// Main +///////////////// + +static const Common::String test("poo", 1, 16); + + + +int main(void) +{ + soundCallback = NULL; + + + initHardware(); + + // Let arm9 read cartridge + *((u16 *) (0x04000204)) &= ~0x0080; + + lastCallbackFrame = 0; + tweak = 0; + + indyFightState = false; + indyFightRight = true; + + // CPU speed = 67108864 + // 8 frames = 2946 368.5 bytes per fr + +// playSound(stretch, 47619, false); +// playSound(twang, 11010, true); // 18640 + +// bufferSize = 10; + bufferRate = 22050; + bufferFrame = 0; +// bufferSamples = (bufferRate * bufferSize) / 60; + bufferSamples = 4096; + + bufferFirstHalf = false; + bufferSecondHalf = true; + + lastEventFrame = 0; + mouseMode = MOUSE_LEFT; + + + + + int bytes = (2 * (bufferSamples)) + 100; + + soundBuffer = (s16 *) malloc(bytes * 2); + + + soundHiPart = true; +/* + TIMER1_CR = 0; + TIMER1_DATA = TIMER_FREQ(bufferRate); + TIMER1_CR = TIMER_ENABLE | TIMER_DIV_1; + + TIMER2_CR = 0; + TIMER2_DATA = 0xFFFF - (bufferSamples / 2); + TIMER2_CR = TIMER_ENABLE | TIMER_IRQ_REQ | TIMER_CASCADE; + */ + // 2945 - 2947 + + + +// for (int r = 2946; r < 3000; r++) { +// soundBuffer[r] = 30000; +// } + + + + consolePrintf("------------------------\n"); + consolePrintf("ScummVM DS\n"); + consolePrintf("Ported by Neil Millstone\n"); +#ifdef DS_SCUMM_BUILD + consolePrintf("Version 0.61 build A\n"); +#else + consolePrintf("Version 0.61 build B\n"); +#endif + consolePrintf("------------------------\n"); + consolePrintf("L/R + D-pad/pen: Scroll view\n"); + consolePrintf("D-pad left: Left mouse button\n"); + consolePrintf("D-pad right: Right mouse button\n"); + consolePrintf("D-pad up: Hover mouse\n"); + consolePrintf("D-pad down: Skip dialog line\n"); + consolePrintf("B button: Skip cutscenes\n"); + consolePrintf("Select: DS Options menu\n"); + consolePrintf("Start: Game menu\n"); + consolePrintf("Y (in game): Toggle console\n"); + consolePrintf("X: Toggle keyboard\n"); + consolePrintf("A: Swap screens\n"); + consolePrintf("L + R on bootup: Clear SRAM\n\n"); + consolePrintf("For a complete poo list see the\n"); + consolePrintf("help screen.\npoo\n"); + + + for (int r = 0; r < bytes; r++) { + soundBuffer[r] = 0; + } + + consolePrintf("length=%d str='%s'\n", test.size(), test.c_str()); + + swiWaitForVBlank(); + swiWaitForVBlank(); + playSound(soundBuffer, (bufferSamples * 2), true); + swiWaitForVBlank(); + swiWaitForVBlank(); + swiWaitForVBlank(); + + + + // Create a file system node to force search for a zip file in GBA rom space + DSFileSystemNode* node = new DSFileSystemNode(); + if (!node->getZip() || (!node->getZip()->isReady())) { + // If not found, init CF/SD driver + initGBAMP(); + } + delete node; + + + + updateStatus(); + + +// OSystem_DS::instance(); + g_system = new OSystem_DS(); + assert(g_system); + + if ((keysHeld() & KEY_L) && (keysHeld() & KEY_R)) { + formatSramOption(); + } + +// printf("'%s'", Common::ConfigManager::kTransientDomain.c_str()); + //printf("'%s'", Common::ConfigManager::kApplicationDomain.c_str()); + + + char* argv[2] = {"/scummvmds", "--config=scummvmb.ini"}; +#ifdef DS_NON_SCUMM_BUILD + + while (1) { + scummvm_main(2, (char **) &argv); + } +#else + while (1) { + scummvm_main(1, (char **) &argv); + } +#endif + + + return 0; +} + +} + +int main() { + DS::main(); +} |