I'm attempting to port WabbitEmu to the Prizm, but it won't be able to emulate the TI-73, 83+, 83+SE, 84+, or 84+SE due to limited RAM. I've also set up a Github repository so you can see that I've made some progress, albeit very little.

https://github.com/souvik1997/pWabbit
Best of luck! For many, many months I have been working on PrizdurTI, a PindurTI port for the Prizm, but I'm afraid I haven't gotten time to make progress on it in a long time. Basically, the main problem is RAM. For the TI-83, you need 64KB of RAM (more or less). The Flash is read-only, so you can keep it in a file in storage memory. Same thing with the TI-82. For the TI-73 and all of the TI-83+ and TI-84+ calculators, you need the 512KB/1024KB/2048KB of Flash to be mutable, plus the 48KB to 128KB of RAM.
Here are the key mappings for the emulated calculator:

Code:
static keyprog_t keygrps[256] = {
        {KEY_PRGM_SHIFT, 6, 5}, // 2nd
   {KEY_PRGM_OPTN, 6, 6}, // Mode
   {KEY_PRGM_DEL, 6, 7}, // Delete
   {KEY_PRGM_ALPHA, 5, 7}, // Alpha
   {KEY_PRGM_XTHETAT, 4, 7}, // Default Var
   {KEY_PRGM_F6, 3, 7}, // Stat
   {KEY_PRGM_FRAC, 5, 6}, // Math
   {KEY_PRGM_FRAC2DEC, 4, 6}, // Apps
   {KEY_PRGM_EXIT, 3, 6}, // Prgm
   {KEY_PRGM_VARS, 2, 6}, // Vars
   {KEY_PRGM_ACON, 1, 6}, // Clear
   {KEY_PRGM_EXP, 5, 5}, // Inverse
   {KEY_PRGM_SIN, 4, 5}, // Sin
   {KEY_PRGM_COS, 3, 5}, // Cos
   {KEY_PRGM_TAN, 2, 5}, // Tan
   {KEY_PRGM_CARET, 1, 5}, // Power
   {KEY_PRGM_XSQUARED, 5, 4}, // Square
   {KEY_PRGM_COMMA, 4, 4}, // Comma
   {KEY_PRGM_LPAREN, 3, 4}, // (
   {KEY_PRGM_RPAREN, 2, 4}, // )
   {KEY_PRGM_DIVIDE, 1, 4}, // Divide
   {KEY_PRGM_LOG, 5, 3}, // Log
   {KEY_PRGM_7, 4, 3}, // 7
   {KEY_PRGM_8, 3, 3}, // 8
   {KEY_PRGM_9, 2, 3}, // 9
   {KEY_PRGM_MULTIPLY, 1, 3}, // Multiply
   {KEY_PRGM_LN, 5, 2}, // Ln
   {KEY_PRGM_4, 4, 2}, // 4
   {KEY_PRGM_5, 3, 2}, // 5
   {KEY_PRGM_6, 2, 2}, // 6
   {KEY_PRGM_SUBTRACT, 1, 2}, // Subtract
   {KEY_PRGM_ARROW, 5, 1}, // Sto
   {KEY_PRGM_1, 4, 1}, // 1
   {KEY_PRGM_2, 3, 1}, // 2
   {KEY_PRGM_3, 2, 1}, // 3
   {KEY_PRGM_ADD, 1, 1}, // Add
   {KEY_PRGM_MENU, 5, 0}, // Power On/Off, This is a special key that will be used to bring up the emulator menu/handle exiting the add-in
   {KEY_PRGM_0, 4, 0}, // 0
   {KEY_PRGM_PERIOD, 3, 0}, // Decimal Point
   {KEY_PRGM_NEGATE, 2, 0}, // Negate
   {KEY_PRGM_RETURN, 1, 0}, // Enter
   {KEY_PRGM_F1, 6, 4}, // Y=
   {KEY_PRGM_F2, 6, 3}, // Window
   {KEY_PRGM_F3, 6, 2}, // Zoom
   {KEY_PRGM_F4, 6, 1}, // Trace
   {KEY_PRGM_F5, 6, 0}, // Graph
   {KEY_PRGM_UP, 0, 3}, // Up Arrow
   {KEY_PRGM_DOWN, 0, 0}, // Down Arrow
   {KEY_PRGM_LEFT, 0, 1}, // Left Arrow
   {KEY_PRGM_RIGHT, 0, 2} // Right Arrow
};

The emulated MATH, APPS(MATRIX), STAT, PRGM, and the inverse key are mapped to keys that have nothing to do with those functions, because the Prizm doesn't have any equivalents.
Very Happy This will be awesome when it's finished! nice github page too
Excellent! Would the speed be the same as the original calcs?
Good luck! I hope you get this done! Smile
I don't know if the speed will be the same, since I haven't actually run it on my calculator yet. The core compiles successfully with minimal modification, but I still have to add all of the key defines that I am going to use to the header files.
souvik1997 wrote:
I don't know if the speed will be the same, since I haven't actually run it on my calculator yet. The core compiles successfully with minimal modification, but I still have to add all of the key defines that I am going to use to the header files.
Sounds like some good steps in the right direction. Smile I vote for a minimal interface on the screen so you can have 3x3 pixel blocks, for a 288x192 emulated screen, and 48 pixels on each side plus 24 pixels spare on the top or bottom.
woah, nice work Smile It's nice that it compiled so easily! Reminds I should get back to work on my Lin8x micro-distribution with a framebuffer-based display for WabbitEmu (plus spasm, wabbitsign, and a z80 assembly syntax highlighting file for VIM) Smile
I was waiting for an update on this. Smile I hope that this project will continue to go at a steady pace.
It successfully compiled, but I'm facing a memory issue. The total amount of memory I will ever need is 393216 bytes, but I don't know if I will be able to consistently allocate that much memory at one time in one continuous block.

Here's the first build of pWabbit, which I am 99% sure will crash and fail.
http://dl.dropbox.com/u/3601919/pWabbit.g3a
You won't be able to malloc() that much memory. Presumably most of that is in a couple chunks (looks like most of it is the emulated Flash), so you should statically allocate it, either in the stack frame for one of your top-level functions or just in a static scope.

The former solution is fast to start up but you still need to zero it out yourself, while the latter protects you from trying to grab too much memory (since the linker will catch it) and zeroes it out for you (crt0 zeroes out the .data segment at startup), but that will slow down program startup a bit. If there's no feedback during memory_init anyway, putting the buffer in a static scope is easier.
souvik1997 wrote:
It successfully compiled, but I'm facing a memory issue. The total amount of memory I will ever need is 393216 bytes, but I don't know if I will be able to consistently allocate that much memory at one time in one continuous block.

Here's the first build of pWabbit, which I am 99% sure will crash and fail.
http://dl.dropbox.com/u/3601919/pWabbit.g3a


Ooh. Imma gonna test it.

Edit: All it says is "R:MEM"
I've been trying to load a TI-82 ROM, and it seems like it's running until 0038h but then it just stops. Also, loading ROMs over 128 KB results in an error.

Code:
BOOL rom_load_minimal(LPCALC lpCalc, char* FileName, int model, char* version)
{
          
if (lpCalc == NULL) {
      return FALSE;
   }
      
   switch (model) {
           case TI_81:
              calc_init_81(lpCalc, version);
              if (!loadFileToRAM(FileName, (void*)lpCalc->cpu.mem_c->flash, lpCalc->cpu.mem_c->flash_size)) return FALSE;
              break;
           case TI_82:
           case TI_83:
              calc_init_83(lpCalc, version);
              if (!loadFileToRAM(FileName, (void*)lpCalc->cpu.mem_c->flash, lpCalc->cpu.mem_c->flash_size)) return FALSE;
              break;
           case TI_85:
           case TI_86:
              calc_init_86(lpCalc);
              if (!loadFileToRAM(FileName, (void*)lpCalc->cpu.mem_c->flash, lpCalc->cpu.mem_c->flash_size)) return FALSE;
              break;          
           default:
              return FALSE;
   }

   lpCalc->active = TRUE;
   memcpy(lpCalc->rom_version, version, sizeof(lpCalc->rom_version));
   //memset(lpCalc->rom_version,0xA5,sizeof(lpCalc->rom_version)); //fill with junk data. Not sure if the rom version is actually used anywhere, though

   strcpy(lpCalc->rom_path, FileName);
   return TRUE;

}


Code:
BOOL loadFileToRAM(unsigned char* f, void* buffer, unsigned int length)
{
        unsigned short pFile[256];
        int hFile;

        Bfile_StrToName_ncpy(pFile, f, strlen(f));
        hFile = Bfile_OpenFile_OS(pFile, READWRITE); // Get handle

        if(hFile < 0) // Check if it opened
        {
          int size = 256;
          if(Bfile_CreateEntry_OS(pFile, CREATEMODE_FILE, &size) >= 0) // Did it create?
          {
            hFile = Bfile_OpenFile_OS(pFile, READWRITE);
            Bfile_ReadFile_OS(hFile, buffer, length, 1);
            if(hFile < 0) // Still failing?
            {
              Bfile_CloseFile_OS(hFile);
              return FALSE;
            }
          }
          else
          {
            Bfile_CloseFile_OS(hFile);
            return FALSE;
          }
        }
        Bfile_CloseFile_OS(hFile);
   return TRUE;
}
0038h is the start of the interrupt. Are you handling interrupts properly? Does Wabbit depend on some timer code that we don't have on the Prizm?
It should handle interrupts, according to this code.

Code:
int CPU_step(CPU_t* cpu) {
   cpu->interrupt = 0;
   cpu->ei_block = FALSE;

#ifdef WITH_REVERSE
   CPU_add_prev_instr(cpu);
#endif
   if (cpu->halt == FALSE) {
      if (cpu->hasHitEnter) {
         /*TCHAR buffer[MAX_PATH];
         _stprintf(buffer, _T("%d: %d %04X\r\n"), cpu->timer_c->tstates - cpu->hasHitEnter, cpu->pc, cpu->pc);
         OutputDebugString(buffer);*/
      }
      CPU_opcode_fetch(cpu);
      if (cpu->bus == 0xDD || cpu->bus == 0xFD) {
         cpu->prefix = cpu->bus;
         CPU_opcode_fetch(cpu);
         CPU_opcode_run(cpu);
         cpu->prefix = 0;
      } else {
         CPU_opcode_run(cpu);
      }
   } else {
      /* If the CPU is in halt */
      tc_add(cpu->timer_c, 4 * HALT_SCALE);
      cpu->r = (cpu->r & 0x80) + ((cpu->r + 1 * HALT_SCALE) & 0x7F);
   }

   handle_pio(cpu);

   if (cpu->interrupt && !cpu->ei_block) {
      handle_interrupt(cpu);
   }
   return 0;
}


Code:
static void handle_interrupt(CPU_t *cpu) {
   if (cpu->iff1) {
      cpu->iff1 = FALSE;
      cpu->iff2 = FALSE;
      if (cpu->imode == 0) {
         /* should execute whatever is on the bus...*/
         cpu->halt = FALSE;
         CPU_opcode_run(cpu);
      } else if (cpu->imode == 1) {
         //
         tc_add(cpu->timer_c, 8);
         cpu->halt = FALSE;
         cpu->bus = 0xFF;
#ifdef WITH_REVERSE
         CPU_add_prev_instr(cpu);
#endif
         CPU_opcode_run(cpu);
      } else if (cpu->imode == 2) {
         tc_add(cpu->timer_c, 19);
         cpu->halt = FALSE;
         unsigned short vector = (cpu->i << 8) + cpu->bus;
         int reg = CPU_mem_read(cpu,vector++) + (CPU_mem_read(cpu,vector) << 8);
         CPU_mem_write(cpu, --cpu->sp, (cpu->pc >> 8) & 0xFF);
         CPU_mem_write(cpu, --cpu->sp, cpu->pc & 0xFF);
         cpu->pc = reg;
      }
   }
}

Also, I tried turning the calculator on with calc_turn_on, but it still doesn't work

Code:
void calc_turn_on(LPCALC lpCalc)
{
   BOOL running = lpCalc->running;
   lpCalc->running = TRUE;
   calc_run_seconds(lpCalc, 2.0);
   keypad_press(&lpCalc->cpu, KEYGROUP_ON, KEYBIT_ON);
   calc_run_seconds(lpCalc, 1.0);
   keypad_release(&lpCalc->cpu, KEYGROUP_ON, KEYBIT_ON);
#ifdef QUICKLOOK
   calc_run_seconds(lpCalc, 0.5);
#endif
   lpCalc->running = running;
}
int calc_run_seconds(LPCALC lpCalc, double seconds) {
   time_t time = (time_t ) (seconds * CLOCKS_PER_SEC);
   return calc_run_timed(lpCalc, time);
}
int calc_run_timed(LPCALC lpCalc, time_t time) {
   int frames = (int) time / TPF;

   int speed_backup = lpCalc->speed;

   lpCalc->speed = MAX_SPEED;
   while (frames--)
      calc_run_frame(lpCalc);
   lpCalc->speed = speed_backup;
   return 0;
}
int calc_run_frame(LPCALC lpCalc) {
   uint64_t end_time = lpCalc->timer_c.freq / FPS;
   uint64_t cpu_sync = tc_tstates(&lpCalc->timer_c) + end_time - lpCalc->time_error;

   while(lpCalc->running) {
      CPU_step(&lpCalc->cpu);

      if (tc_tstates(&lpCalc->timer_c) >= cpu_sync) {
         lpCalc->time_error = (time_t)(tc_tstates((&lpCalc->timer_c)) - cpu_sync);
         return 0;
      }
   }

   return 0;
}
I think I've figured out why it was getting stuck at 0038h, the ROM wasn't being loaded properly causing the Flash memory to be initialized to just $FFs which is the z80 opcode for 'rst 38h'. I already posted my ROM loading functions above, does there seem to be anything wrong with it?
It looks OK to me, but there's a lot more that could be going wrong. What pages are mapped into the four banks what it resets?
I've narrowed down the problem to the file loading. When I hardcode a path to a file to load, the file actually gets loaded.

Code:

unsigned char* testfile = "\\\\fls0\\ti83.rom";
loadFileToRAM(testfile,globalmem,262000);
VRAM = GetVRAMAddress();

However, if I use the file browser dialog, the file does not get loaded.

Code:

Bdisp_EnableColor(1);
       struct FBL_Filelist_Data *list = FBL_Filelist_cons("\\\\fls0\\", "*.rom", "Open file...");
        FBL_Filelist_go(list);
        // Optional
        DrawFrame(COLOR_BLACK);
        if(list->result == 1) {
                FBL_Filelist_getFilename(list,buffer,127);

        }
... // other stuff, FileName is the name of the pointer to the file name when buffer is passed into rom_load_minimal
switch (model) {
            case TI_81:
                calc_init_81(lpCalc, version);
                breakpoint("xxInit 81");
                if (!loadFileToRAM(FileName, (void*)globalmem, lpCalc->cpu.mem_c->flash_size)) return FALSE;
                break;
            case TI_82:
            case TI_83:
                calc_init_83(lpCalc, version);
                breakpoint("xxInit 83");
                if (!loadFileToRAM(FileName, (void*)globalmem, lpCalc->cpu.mem_c->flash_size)) return FALSE;
                break;
            case TI_85:
            case TI_86:
                calc_init_86(lpCalc);
                breakpoint("xxInit 86");
                if (!loadFileToRAM(FileName, (void*)globalmem, lpCalc->cpu.mem_c->flash_size)) return FALSE;
                break;         
            default:
                return FALSE;
    }

breakpoint() is just a function I made to easily display strings for debugging. Here's the file loading code:

Code:
BOOL loadFileToRAM(unsigned char* f, void* buffer, unsigned int length)
{
       
    itoa(length,nbuf+2);
    breakpoint(nbuf);
    unsigned short pFile[256];
    int hFile;

    Bfile_StrToName_ncpy(pFile, f, strlen(f));
    hFile = Bfile_OpenFile_OS(pFile, READ); // Get handle

    if(hFile > 0) // Check if it opened
    {
        int i = 0;
        breakpoint("xxreading");
        while (i < length && Bfile_ReadFile_OS(hFile, (void*)(buffer+i), 1, -1) > 0 ) //strange issues with loading it all at once...
            i++;
        itoa(i,nbuf+2);
        breakpoint(nbuf);
    }
    else
    {
      Bfile_CloseFile_OS(hFile);
      breakpoint("xxfail"); //this shows when I'm using the dialog
      return FALSE;
    }
    Bfile_CloseFile_OS(hFile);
    return TRUE;
}


I've checked what FBL_FileList_getFileName returns in the buffer, and it is identical to what I'm hardcoding.


Edit: Something even stranger: If I put my hardcoded path into rom_load_minimal, it doesn't work. It still works at the beginning of my program.

Edit 2: It seems like loadFileToRAM only works if it is in the main function of the program...
Those are extremely odd results indeed. Don't forget that Prizm paths, if you're interacting directly with the syscalls, must be arrays of shorts (not chars).
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 3
» All times are GMT - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement