f256/examples/a23d2/src/a23d2.c
2024-04-18 18:18:11 -05:00

251 lines
7.3 KiB
C

/*
* 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 <string.h> // 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