/* * Copyright (c) 2024 Scott Duensing, scott@kangaroopunch.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "a23d2.h" #include // For memcopy volatile cameraT *_camera = (cameraT *)CAMERA_SHARED_START; // Simulation copy of camera. volatile cameraT *_cameraInDatabase; volatile byte *_pointer; uint16_t _drawlist; uint16_t _drawlistInDatabase; uint16_t _bytes; uint8_t _x1; uint8_t _y1; uint8_t _x2; uint8_t _y2; bool _useColor; byte _mmu; byte _ram; //float _trig; #define SEGMENT_A23D2 // There's a lot of global use in here. We can't use the virtual stack. #if 0 void a23d2Cos(void) { // We need to manually page 0x54000 into 0x6000. // This isn't actually large enough for A2-3D2 but what we should only // lose Apple ][ stuff we're not using anyway. POKE(MMU_MEM_BANK_3, A23D2_FAR_BLOCK); // Map 0-359 into 0-255. _tdata = _tdata % 359; _y1 = (360/256) * _tdata; // Call COSEX. POKE(A23D2_TDATA, _y1); __attribute__((leaf)) asm volatile("jsr %[addy]":: [addy] "i"(A23D2_COSEX)); // Convert to float. _trig = (float)PEEKW(A23D2_TDATA) / 32768; // Restore memory map. POKE(MMU_MEM_BANK_3, 3); } #endif void a23d2Draw(void) { _pointer = (byte *)_drawlist; // Move our 3D/2D data buffer at 0x56000 into slot 4. POKE(MMU_MEM_BANK_4, DATABASE_FAR_BLOCK); while (true) { switch (*_pointer++) { // Line. case (byte)LIN2D: _x1 = (uint8_t)((int8_t)(*_pointer++) + 128); _y1 = 255 - (uint8_t)((int8_t)(*_pointer++) + 128); _x2 = (uint8_t)((int8_t)(*_pointer++) + 128); _y2 = 255 - (uint8_t)((int8_t)(*_pointer++) + 128); bitmapLine(_x1, _y1, _x2, _y2); continue; // Point. case (byte)PNT2D: _x1 = (uint8_t)((int8_t)(*_pointer++) + 128); _y1 = 255 - (uint8_t)((int8_t)(*_pointer++) + 128); bitmapPutPixel(_x1, _y1); continue; // Set Color. case (byte)STCOL: _x1 = (int8_t)(*_pointer++); if (_useColor) bitmapSetColor(_x1); continue; // Set Resolution. case (byte)SRES: // Eat this byte. We don't need it. _pointer++; continue; // End. case (byte)END: break; } break; } // Restore memory map. POKE(MMU_MEM_BANK_4, 4); } void a23d2Init(void) { // We need to manually page 0x54000 into 0x6000. // This isn't actually large enough for A2-3D2 but what we should only // lose Apple ][ stuff we're not using anyway. POKE(MMU_MEM_BANK_3, A23D2_FAR_BLOCK); // We're going to clobber from 0x80fb to 0x8101 with our setup database. // Usually we'd swap in bank 4, but we'd have to save that, too. Back it up. scdMemCpy((byte *)(SCRATCH_END - 0x06), (byte *)A23D2_TEST_DATABASE, 0x06); // Initialize A2-3D2 so we can use the "fast entry point" (NXTPT) when rendering. _bytes = 0; _pointer = (byte *)A23D2_TEST_DATABASE; // Standard location for test database in A2-3D2. _pointer[_bytes++] = SCRSZ; // Screen size. 256x240. Center is 0,0. _pointer[_bytes++] = 255; _pointer[_bytes++] = 239; _pointer[_bytes++] = 0; _pointer[_bytes++] = 0; _pointer[_bytes++] = END; // Setup complete! // Save ZP that A2-3D2 is going to clobber. scdMemCpy((byte *)COMPILER_ZP_SAVE, (byte *)COMPILER_ZP_START, COMPILER_ZP_LENGTH); // Call ENTRYN. This sets up A2-3D2. __attribute__((leaf)) asm volatile("jsr %[addy]":: [addy] "i"(A23D2_ENTRYN)); // Save A2-3D2s ZP for later. scdMemCpy((byte *)A23D2_ZP_SAVE, (byte *)A23D2_ZP_START, A23D2_ZP_LENGTH); // Restore ZP that A2-3D2 clobbered. scdMemCpy((byte *)COMPILER_ZP_START, (byte *)COMPILER_ZP_SAVE, COMPILER_ZP_LENGTH); // Put back the RAM we clobbered. scdMemCpy((byte *)A23D2_TEST_DATABASE, (byte *)(SCRATCH_END - 0x06), 0x06); // Move our 3D/2D data buffer at 0x56000 into slot 4. POKE(MMU_MEM_BANK_4, DATABASE_FAR_BLOCK); // Set up drawlists. _drawlistInDatabase = DATABASE + 1; // First value after ARRAY in near memory. POKE(DRAWLIST_P0, END); POKE(DRAWLIST_P1, END); // Set up camera. _cameraInDatabase = (cameraT *)(DATABASE + 4); // First value after EYE in near memory. _camera->x = _cameraInDatabase->x; _camera->y = _cameraInDatabase->y; _camera->z = _cameraInDatabase->z; _camera->p = _cameraInDatabase->p; _camera->b = _cameraInDatabase->b; _camera->h = _cameraInDatabase->h; // Restore memory map. POKE(MMU_MEM_BANK_4, 4); POKE(MMU_MEM_BANK_3, 3); } void a23d2Render(void) { // We need to manually page 0x54000 into 0x6000. // This isn't actually large enough for A2-3D2 but what we should only // lose Apple ][ stuff we're not using anyway. POKE(MMU_MEM_BANK_3, A23D2_FAR_BLOCK); // Move our 3D/2D data buffer at 0x56000 into slot 4. POKE(MMU_MEM_BANK_4, DATABASE_FAR_BLOCK); // Update drawlist. POKEW(_drawlistInDatabase, _drawlist); // Update camera position. _cameraInDatabase->x = _camera->x; _cameraInDatabase->y = _camera->y; _cameraInDatabase->z = _camera->z; _cameraInDatabase->p = _camera->p; _cameraInDatabase->b = _camera->b; _cameraInDatabase->h = _camera->h; // Save ZP that A2-3D2 is going to clobber. scdMemCpy((byte *)COMPILER_ZP_SAVE, (byte *)COMPILER_ZP_START, COMPILER_ZP_LENGTH); // Restore A2-3D2s ZP. scdMemCpy((byte *)A23D2_ZP_START, (byte *)A23D2_ZP_SAVE, A23D2_ZP_LENGTH); // Set IBP. POKEW(A23D2_IBP, DATABASE); // Call NXTPT. __attribute__((leaf)) asm volatile("jsr %[addy]":: [addy] "i"(A23D2_NXTPT) : "a","x","y","c","v"); // Call NXTPT. // Save A2-3D2s ZP for later. scdMemCpy((byte *)A23D2_ZP_SAVE, (byte *)A23D2_ZP_START, A23D2_ZP_LENGTH); // Restore ZP that A2-3D2 clobbered. scdMemCpy((byte *)COMPILER_ZP_START, (byte *)COMPILER_ZP_SAVE, COMPILER_ZP_LENGTH); // Restore memory map. POKE(MMU_MEM_BANK_4, 4); POKE(MMU_MEM_BANK_3, 3); } #if 0 void a23d2Sin(void) { // We need to manually page 0x54000 into 0x6000. // This isn't actually large enough for A2-3D2 but what we should only // lose Apple ][ stuff we're not using anyway. POKE(MMU_MEM_BANK_3, A23D2_FAR_BLOCK); // Map 0-359 into 0-255. _tdata = _tdata % 359; _y1 = (360/256) * _tdata; // Call SINEX. POKE(A23D2_TDATA, _y1); __attribute__((leaf)) asm volatile("jsr %[addy]":: [addy] "i"(A23D2_SINEX)); // Convert to float. _trig = (float)PEEKW(A23D2_TDATA) / 32768; // Restore memory map. POKE(MMU_MEM_BANK_3, 3); } #endif