Reorganized code.

This commit is contained in:
Scott Duensing 2024-04-21 18:10:31 -05:00
parent eea86533cc
commit 7040fff6e7
8 changed files with 594 additions and 423 deletions

View file

@ -30,6 +30,9 @@ list(TRANSFORM SOURCE PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/src/")
add_executable(${CMAKE_PROJECT_NAME}
${HEADERS}
${SOURCE}
src/a23d2.c
include/bitmap.h
src/bitmap.c
)

View file

@ -26,7 +26,7 @@
#else
#include <stdint.h>
#include <stdbool.h>
typedef uint8_t byte;
#include "util.h"
#endif

69
pc/include/bitmap.h Normal file
View file

@ -0,0 +1,69 @@
/*
* 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.
*/
#ifndef BITMAP_H
#define BITMAP_H
#include <stdio.h>
#include "util.h"
#define HEIGHT 240
#define WIDTH 320
#define SCALE 1.25 // Scale factor for 256->320
// ***FIX*** Somehow we're getting invalid drawing coordinates from A2-3D2.
#define bitmapPutPixelIOSet(x,y) \
({ \
if ((x < WIDTH) && (y < HEIGHT)) { \
byte *p = _pixels + ((x) * 4 + ((y) * WIDTH * 4)); \
*p++ = _color.r; \
*p++ = _color.g; \
*p++ = _color.b; \
*p++ = 255; \
} else { \
printf("CLIPPED!\n"); \
fflush(0); \
} \
})
typedef struct ColorS {
byte r;
byte g;
byte b;
} ColorT;
extern byte *_pixels;
extern ColorT _color;
void bitmapLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
void colorSet(byte ega);
#endif // BITMAP_H

View file

@ -26,6 +26,14 @@
#include <stdarg.h>
#include <stdint.h>
#define LOW_BYTE(x) ((uint8_t)(x))
#define HIGH_BYTE(x) ((uint8_t)(((uint16_t)(x)) >> 8))
typedef uint8_t byte;
char *utilCreateString(char *format, ...);

371
pc/src/a23d2.c Normal file
View file

@ -0,0 +1,371 @@
/*
* 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 <stdlib.h>
#include "vrEmu6502.h"
#include "a23d2bin.h"
#include "bitmap.h"
#include "flight.h"
#include "a23d2.h"
// Emulator Stuff.
byte _RAM[0x10000]; // 6502 memory.
VrEmu6502 *_v6502 = NULL;
uint16_t _drawlistInDatabase;
float _trig;
uint8_t _x1;
void jsr(uint16_t addr);
void landscape(void);
byte memoryRead(uint16_t addr, bool isDebug);
void memoryWrite(uint16_t addr, byte value);
void a23d2Cos(void) {
// Map 0-359 into 0-255.
_tdata = _tdata % 359;
_x1 = (360/256) * _tdata;
// Call COSEX.
_RAM[A23D2_TDATA] = _x1;
jsr(A23D2_COSEX);
// Convert to float.
_trig = (float)(_RAM[A23D2_TDATA] + _RAM[A23D2_TDATA + 1] * 256) / 32768;
}
void a23d2Draw(void) {
uint16_t pointer = DRAWLIST_P0;
int16_t x1;
int16_t y1;
int16_t x2;
int16_t y2;
while (true) {
switch (_RAM[pointer++]) {
// Line.
case LIN2D:
x1 = (int8_t)_RAM[pointer++] + 128;
y1 = 255 - ((int8_t)_RAM[pointer++] + 128);
x2 = (int8_t)_RAM[pointer++] + 128;
y2 = 255 - ((int8_t)_RAM[pointer++] + 128);
bitmapLine(x1 * SCALE, y1 / SCALE, x2 * SCALE, y2 / SCALE);
continue;
// Point.
case PNT2D:
x1 = (int8_t)_RAM[pointer++] + 128;
y1 = 255 - ((int8_t)_RAM[pointer++] + 128);
x1 *= SCALE;
y1 /= SCALE;
bitmapPutPixelIOSet(x1, y1);
continue;
// Set Color.
case STCOL:
x1 = _RAM[pointer++];
colorSet(x1);
continue;
// Set Resolution.
case SRES:
// Eat this byte. We don't need it.
pointer++;
continue;
// End.
case END:
break;
}
break;
}
}
void a23d2Init(void) {
uint16_t bytes;
// Clear VM RAM.
memset(_RAM, 0, 0x10000);
// Create our VM.
_v6502 = vrEmu6502New(CPU_W65C02, memoryRead, memoryWrite);
// Copy A2-3D2 into 6502 RAM.
memcpy(&_RAM[0x6000], a23d2bin, a23d2bin_len);
// Initialize A2-3D2 so we can use the "fast entry point" (NXTPT) when rendering.
bytes = A23D2_TEST_DATABASE;
_RAM[bytes++] = SCRSZ; // Screen size. 256x240. Center is 0,0. We're going to scale this up.
_RAM[bytes++] = 255; // Scales up to 320.
_RAM[bytes++] = 233; // Scales up to 193 (leaves 46 pixels for a control panel).
_RAM[bytes++] = 0;
_RAM[bytes++] = 0;
_RAM[bytes++] = END; // Setup complete!
jsr(A23D2_ENTRYN);
// Generate scene database.
landscape();
// Set up drawlist.
_drawlistInDatabase = DATABASE + 1;
_RAM[DRAWLIST_P0] = END;
// Set up camera.
_camera = (cameraT *)&_RAM[DATABASE + 4];
_camera->x = 10600;
_camera->y = PLANE_HEIGHT;
_camera->z = 10500;
_camera->p = 0;
_camera->h = 0;
}
void a23d2Render(void) {
// Update drawlist.
_RAM[_drawlistInDatabase + 0] = LOW_BYTE(DRAWLIST_P0);
_RAM[_drawlistInDatabase + 1] = HIGH_BYTE(DRAWLIST_P0);
// Set IBP.
_RAM[A23D2_IBP + 0] = LOW_BYTE(DATABASE);
_RAM[A23D2_IBP + 1] = HIGH_BYTE(DATABASE);
// Render.
jsr(A23D2_NXTPT);
}
void a23d2Shutdown(void) {
vrEmu6502Destroy(_v6502);
_v6502 = NULL;
}
void a23d2Sin(void) {
// Map 0-359 into 0-255.
_tdata = _tdata % 359;
_x1 = (360/256) * _tdata;
// Call COSEX.
_RAM[A23D2_TDATA] = _x1;
jsr(A23D2_SINEX);
// Convert to float.
_trig = (float)(_RAM[A23D2_TDATA] + _RAM[A23D2_TDATA + 1] * 256) / 32768;
}
void jsr(uint16_t addr) {
int32_t depth = 0;
//int32_t instructions = 0;
uint16_t PC = addr;
vrEmu6502SetPC(_v6502, PC);
while (true) {
// Did we execute an instruction?
if (PC != vrEmu6502GetPC(_v6502)) {
PC = vrEmu6502GetPC(_v6502);
//instructions++;
// Track JSRs & RTSs.
if (vrEmu6502GetCurrentOpcode(_v6502) == 0x20) depth++;
if (vrEmu6502GetCurrentOpcode(_v6502) == 0x60) {
depth--;
if (depth < 0) break;
}
}
// Step.
vrEmu6502Tick(_v6502);
}
//printf("%x = %d instructions\n", addr, instructions);
}
void landscape(void) {
int32_t i;
int32_t x;
int32_t z;
int32_t w;
int32_t l;
int32_t min = 0;
int32_t max = 30000; // A mile is 5280.
int32_t lines = 10;
int32_t skip = (abs(min) + abs(max)) / lines;
byte *db = _RAM;
uint16_t bytes = DATABASE;
// All scene databases need to begin with the ARRAY and EYE records.
// The CLPSW clipping setting is up to you. :-)
db[bytes++] = ARRAY; // Will be filled in by the program.
db[bytes++] = 0;
db[bytes++] = 0;
db[bytes++] = EYE; // Will be filled in by the program.
db[bytes++] = 0x00; // X
db[bytes++] = 0x00;
db[bytes++] = 0x00; // Y
db[bytes++] = 0x00;
db[bytes++] = 0x00; // Z
db[bytes++] = 0x00;
db[bytes++] = 0x00; // P
db[bytes++] = 0x00; // B
db[bytes++] = 0x00; // H
db[bytes++] = CLPSW;
db[bytes++] = 0x00;
// Landscape
db[bytes++] = STCOL;
db[bytes++] = 2; // Green
for (i=min; i<=max; i+=skip) {
db[bytes++] = SPNT;
db[bytes++] = LOW_BYTE(i); // X
db[bytes++] = HIGH_BYTE(i);
db[bytes++] = 0; // Y
db[bytes++] = 0;
db[bytes++] = LOW_BYTE(min); // Z
db[bytes++] = HIGH_BYTE(min);
db[bytes++] = CPNT;
db[bytes++] = LOW_BYTE(i); // X
db[bytes++] = HIGH_BYTE(i);
db[bytes++] = 0; // Y
db[bytes++] = 0;
db[bytes++] = LOW_BYTE(max); // Z
db[bytes++] = HIGH_BYTE(max);
db[bytes++] = SPNT;
db[bytes++] = LOW_BYTE(min); // X
db[bytes++] = HIGH_BYTE(min);
db[bytes++] = 0; // Y
db[bytes++] = 0;
db[bytes++] = LOW_BYTE(i); // Z
db[bytes++] = HIGH_BYTE(i);
db[bytes++] = CPNT;
db[bytes++] = LOW_BYTE(max); // X
db[bytes++] = HIGH_BYTE(max);
db[bytes++] = 0; // Y
db[bytes++] = 0;
db[bytes++] = LOW_BYTE(i); // Z
db[bytes++] = HIGH_BYTE(i);
}
// Runway - 3000' x 200'
w = 200;
l = 3000;
x = skip * 3.5;
z = skip * 3.5;
printf("%dx%d\n", x, z);
db[bytes++] = STCOL;
db[bytes++] = 7; // Light Grey
db[bytes++] = SPNT;
db[bytes++] = LOW_BYTE(x); // X
db[bytes++] = HIGH_BYTE(x);
db[bytes++] = 0; // Y
db[bytes++] = 0;
db[bytes++] = LOW_BYTE(z); // Z
db[bytes++] = HIGH_BYTE(z);
db[bytes++] = CPNT;
db[bytes++] = LOW_BYTE(x+w); // X
db[bytes++] = HIGH_BYTE(x+w);
db[bytes++] = 0; // Y
db[bytes++] = 0;
db[bytes++] = LOW_BYTE(z); // Z
db[bytes++] = HIGH_BYTE(z);
db[bytes++] = CPNT;
db[bytes++] = LOW_BYTE(x+w); // X
db[bytes++] = HIGH_BYTE(x+w);
db[bytes++] = 0; // Y
db[bytes++] = 0;
db[bytes++] = LOW_BYTE(z+l); // Z
db[bytes++] = HIGH_BYTE(z+l);
db[bytes++] = CPNT;
db[bytes++] = LOW_BYTE(x); // X
db[bytes++] = HIGH_BYTE(x);
db[bytes++] = 0; // Y
db[bytes++] = 0;
db[bytes++] = LOW_BYTE(z+l); // Z
db[bytes++] = HIGH_BYTE(z+l);
db[bytes++] = CPNT;
db[bytes++] = LOW_BYTE(x); // X
db[bytes++] = HIGH_BYTE(x);
db[bytes++] = 0; // Y
db[bytes++] = 0;
db[bytes++] = LOW_BYTE(z); // Z
db[bytes++] = HIGH_BYTE(z);
db[bytes++] = STCOL;
db[bytes++] = 15; // White
skip = l / (lines * 2);
x += (w / 2);
for (i=z + skip; i<z+l-skip; i+=(skip*2)) {
db[bytes++] = SPNT;
db[bytes++] = LOW_BYTE(x); // X
db[bytes++] = HIGH_BYTE(x);
db[bytes++] = 0; // Y
db[bytes++] = 0;
db[bytes++] = LOW_BYTE(i); // Z
db[bytes++] = HIGH_BYTE(i);
db[bytes++] = CPNT;
db[bytes++] = LOW_BYTE(x); // X
db[bytes++] = HIGH_BYTE(x);
db[bytes++] = 0; // Y
db[bytes++] = 0;
db[bytes++] = LOW_BYTE(i+skip); // Z
db[bytes++] = HIGH_BYTE(i+skip);
}
db[bytes++] = END;
}
byte memoryRead(uint16_t addr, bool isDebug) {
(void)isDebug;
return _RAM[addr];
}
void memoryWrite(uint16_t addr, byte value) {
_RAM[addr] = value;
}

116
pc/src/bitmap.c Normal file
View file

@ -0,0 +1,116 @@
/*
* 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 <stdint.h>
#include <stdlib.h>
#include "bitmap.h"
byte _ega[16][3] = {
{ 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0xaa },
{ 0x00, 0xaa, 0x00 },
{ 0x00, 0xaa, 0xaa },
{ 0xaa, 0x00, 0x00 },
{ 0xaa, 0x00, 0xaa },
{ 0xaa, 0x55, 0x00 },
{ 0xaa, 0xaa, 0xaa },
{ 0x55, 0x55, 0x55 },
{ 0x55, 0x55, 0xff },
{ 0x55, 0xff, 0x55 },
{ 0x55, 0xff, 0xff },
{ 0xff, 0x55, 0x55 },
{ 0xff, 0x55, 0xff },
{ 0xff, 0xff, 0x55 },
{ 0xff, 0xff, 0xff }
};
byte *_pixels = NULL;
ColorT _color;
void bitmapLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {
uint16_t x;
uint16_t y;
int16_t dx;
int16_t dy;
int16_t incX;
int16_t incY;
int16_t balance;
if (x2 >= x1) {
dx = x2 - x1;
incX = 1;
} else {
dx = x1 - x2;
incX = -1;
}
if (y2 >= y1) {
dy = y2 - y1;
incY = 1;
} else {
dy = y1 - y2;
incY = -1;
}
x = x1;
y = y1;
if (dx >= dy) {
dy <<= 1;
balance = dy - dx;
dx <<= 1;
while (x != x2) {
bitmapPutPixelIOSet(x, y);
if (balance >= 0) {
y += incY;
balance -= dx;
}
balance += dy;
x += incX;
}
bitmapPutPixelIOSet(x, y);
} else {
dx <<= 1;
balance = dx - dy;
dy <<= 1;
while (y != y2) {
bitmapPutPixelIOSet(x, y);
if (balance >= 0) {
x += incX;
balance -= dy;
}
balance += dx;
y += incY;
}
bitmapPutPixelIOSet(x, y);
}
}
void colorSet(byte ega) {
_color.r = _ega[ega][0];
_color.g = _ega[ega][1];
_color.b = _ega[ega][2];
}

View file

@ -22,6 +22,7 @@
#include "flight.h"
#include "a23d2.h"
airplaneT _plane;
@ -35,12 +36,10 @@ airplaneT _plane;
#define Rads(d) (((d) < 0 ? (d) + 360 : (d)) * (PI / 180))
#define Degs(r) ((r) * (180 / PI))
// https://www.reddit.com/r/programming/comments/3e7ghi/discrete_arctan_in_6502/
#define ATAN_SPLINE_C0 (double)(-0.14380550980765507115) /* 3pi/4 - 5/2 */
#define ATAN_SPLINE_C1 (double)(-0.07079632679489661923) /* 3/2 - pi/2 */
// https://www.reddit.com/r/programming/comments/3e7ghi/discrete_arctan_in_6502
#define ATAN_SPLINE_C0 (double)(-0.14380550980765507115) // 3pi/4 - 5/2
#define ATAN_SPLINE_C1 (double)(-0.07079632679489661923) // 3/2 - pi/2
double ourAtan(double x){
return atan(x);
/*
if (x >= 0) {
if ( x<= 1) {
return x + (ATAN_SPLINE_C0 + ATAN_SPLINE_C1 * x) * x * x;
@ -56,17 +55,28 @@ double ourAtan(double x){
return (x + (ATAN_SPLINE_C0 + ATAN_SPLINE_C1 * x) * x * x) - PI / 2;
}
}
*/
}
float cosD(float d) {
return cos(Rads(d));
/*
// Map 0-359 into 0-255.
_tdata = (int)d % 359;
a23d2Cos();
return _trig;
*/
}
float sinD(float d) {
return sin(Rads(d));
/*
// Map 0-359 into 0-255.
_tdata = (int)d % 359;
a23d2Sin();
return _trig;
*/
}

View file

@ -21,11 +21,10 @@
*/
#include "vrEmu6502.h"
#include "a23d2bin.h"
#include "a23d2.h"
#include "flight.h"
#include "util.h"
#include "bitmap.h"
#define APP_IMPLEMENTATION
@ -42,9 +41,6 @@
#include "sysfont.h"
#define HEIGHT 240
#define WIDTH 320
#define SCALE 1.25 // Scale factor for 256->320
#define DEG2CAM 0.711111111
#define CAM2DEG 1.40625
@ -58,381 +54,20 @@
#define JOY_BUTTON_3 64
typedef struct ColorS {
byte r;
byte g;
byte b;
} ColorT;
// Foenix Stuff.
byte _gamepad;
// Graphics Stuff.
byte _ega[16][3] = {
{ 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0xaa },
{ 0x00, 0xaa, 0x00 },
{ 0x00, 0xaa, 0xaa },
{ 0xaa, 0x00, 0x00 },
{ 0xaa, 0x00, 0xaa },
{ 0xaa, 0x55, 0x00 },
{ 0xaa, 0xaa, 0xaa },
{ 0x55, 0x55, 0x55 },
{ 0x55, 0x55, 0xff },
{ 0x55, 0xff, 0x55 },
{ 0x55, 0xff, 0xff },
{ 0xff, 0x55, 0x55 },
{ 0xff, 0x55, 0xff },
{ 0xff, 0xff, 0x55 },
{ 0xff, 0xff, 0xff }
};
byte *_pixels = NULL;
ColorT _color;
// Emulator Stuff.
byte _RAM[0x10000]; // 6502 memory.
VrEmu6502 *_v6502 = NULL;
// A2-3D2 Stuff.
volatile cameraT *_camera;
uint16_t _drawlistInDatabase;
// External.
void a23d2Shutdown(void);
#define LOW_BYTE(x) ((uint8_t)(x))
#define HIGH_BYTE(x) ((uint8_t)(((uint16_t)(x)) >> 8))
// ***FIX*** Somehow we're getting invalid drawing coordinates from A2-3D2.
#define bitmapPutPixelIOSet(x,y) \
({ \
if ((x < WIDTH) && (y < HEIGHT)) { \
byte *p = _pixels + ((x) * 4 + ((y) * WIDTH * 4)); \
*p++ = _color.r; \
*p++ = _color.g; \
*p++ = _color.b; \
*p++ = 255; \
} else { \
printf("CLIPPED!\n"); \
fflush(0); \
} \
})
void bitmapLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
void colorSet(byte ega);
void draw(void);
void jsr(uint16_t addr);
void landscape(void);
byte memoryRead(uint16_t addr, bool isDebug);
void memoryWrite(uint16_t addr, byte value);
void printAt(uint8_t x, uint8_t y, char *format, ...);
int appMain(app_t *app, void *userData);
void bitmapLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {
uint16_t x;
uint16_t y;
int16_t dx;
int16_t dy;
int16_t incX;
int16_t incY;
int16_t balance;
if (x2 >= x1) {
dx = x2 - x1;
incX = 1;
} else {
dx = x1 - x2;
incX = -1;
}
if (y2 >= y1) {
dy = y2 - y1;
incY = 1;
} else {
dy = y1 - y2;
incY = -1;
}
x = x1;
y = y1;
if (dx >= dy) {
dy <<= 1;
balance = dy - dx;
dx <<= 1;
while (x != x2) {
bitmapPutPixelIOSet(x, y);
if (balance >= 0) {
y += incY;
balance -= dx;
}
balance += dy;
x += incX;
}
bitmapPutPixelIOSet(x, y);
} else {
dx <<= 1;
balance = dx - dy;
dy <<= 1;
while (y != y2) {
bitmapPutPixelIOSet(x, y);
if (balance >= 0) {
x += incX;
balance -= dy;
}
balance += dx;
y += incY;
}
bitmapPutPixelIOSet(x, y);
}
}
void colorSet(byte ega) {
_color.r = _ega[ega][0];
_color.g = _ega[ega][1];
_color.b = _ega[ega][2];
}
void draw(void) {
uint16_t pointer = DRAWLIST_P0;
int16_t x1;
int16_t y1;
int16_t x2;
int16_t y2;
while (true) {
switch (_RAM[pointer++]) {
// Line.
case LIN2D:
x1 = (int8_t)_RAM[pointer++] + 128;
y1 = 255 - ((int8_t)_RAM[pointer++] + 128);
x2 = (int8_t)_RAM[pointer++] + 128;
y2 = 255 - ((int8_t)_RAM[pointer++] + 128);
bitmapLine(x1 * SCALE, y1 / SCALE, x2 * SCALE, y2 / SCALE);
continue;
// Point.
case PNT2D:
x1 = (int8_t)_RAM[pointer++] + 128;
y1 = 255 - ((int8_t)_RAM[pointer++] + 128);
x1 *= SCALE;
y1 /= SCALE;
bitmapPutPixelIOSet(x1, y1);
continue;
// Set Color.
case STCOL:
x1 = _RAM[pointer++];
colorSet(x1);
continue;
// Set Resolution.
case SRES:
// Eat this byte. We don't need it.
pointer++;
continue;
// End.
case END:
break;
}
break;
}
}
void jsr(uint16_t addr) {
int32_t depth = 0;
// int32_t instructions = 0;
uint16_t PC = addr;
vrEmu6502SetPC(_v6502, PC);
while (true) {
// Did we execute an instruction?
if (PC != vrEmu6502GetPC(_v6502)) {
PC = vrEmu6502GetPC(_v6502);
// instructions++;
// Track JSRs & RTSs.
if (vrEmu6502GetCurrentOpcode(_v6502) == 0x20) depth++;
if (vrEmu6502GetCurrentOpcode(_v6502) == 0x60) {
depth--;
if (depth < 0) break;
}
}
// Step.
vrEmu6502Tick(_v6502);
}
//printf("%x = %d instructions\n", addr, instructions);
}
void landscape(void) {
int32_t i;
int32_t x;
int32_t z;
int32_t w;
int32_t l;
int32_t min = 0;
int32_t max = 30000; // A mile is 5280.
int32_t lines = 10;
int32_t skip = (abs(min) + abs(max)) / lines;
byte *db = _RAM;
uint16_t bytes = DATABASE;
// All scene databases need to begin with the ARRAY and EYE records.
// The CLPSW clipping setting is up to you. :-)
db[bytes++] = ARRAY; // Will be filled in by the program.
db[bytes++] = 0;
db[bytes++] = 0;
db[bytes++] = EYE; // Will be filled in by the program.
db[bytes++] = 0x00; // X
db[bytes++] = 0x00;
db[bytes++] = 0x00; // Y
db[bytes++] = 0x00;
db[bytes++] = 0x00; // Z
db[bytes++] = 0x00;
db[bytes++] = 0x00; // P
db[bytes++] = 0x00; // B
db[bytes++] = 0x00; // H
db[bytes++] = CLPSW;
db[bytes++] = 0x00;
// Landscape
db[bytes++] = STCOL;
db[bytes++] = 2; // Green
for (i=min; i<=max; i+=skip) {
db[bytes++] = SPNT;
db[bytes++] = LOW_BYTE(i); // X
db[bytes++] = HIGH_BYTE(i);
db[bytes++] = 0; // Y
db[bytes++] = 0;
db[bytes++] = LOW_BYTE(min); // Z
db[bytes++] = HIGH_BYTE(min);
db[bytes++] = CPNT;
db[bytes++] = LOW_BYTE(i); // X
db[bytes++] = HIGH_BYTE(i);
db[bytes++] = 0; // Y
db[bytes++] = 0;
db[bytes++] = LOW_BYTE(max); // Z
db[bytes++] = HIGH_BYTE(max);
db[bytes++] = SPNT;
db[bytes++] = LOW_BYTE(min); // X
db[bytes++] = HIGH_BYTE(min);
db[bytes++] = 0; // Y
db[bytes++] = 0;
db[bytes++] = LOW_BYTE(i); // Z
db[bytes++] = HIGH_BYTE(i);
db[bytes++] = CPNT;
db[bytes++] = LOW_BYTE(max); // X
db[bytes++] = HIGH_BYTE(max);
db[bytes++] = 0; // Y
db[bytes++] = 0;
db[bytes++] = LOW_BYTE(i); // Z
db[bytes++] = HIGH_BYTE(i);
}
// Runway - 3000' x 200'
w = 200;
l = 3000;
x = skip * 3.5;
z = skip * 3.5;
printf("%dx%d\n", x, z);
db[bytes++] = STCOL;
db[bytes++] = 7; // Light Grey
db[bytes++] = SPNT;
db[bytes++] = LOW_BYTE(x); // X
db[bytes++] = HIGH_BYTE(x);
db[bytes++] = 0; // Y
db[bytes++] = 0;
db[bytes++] = LOW_BYTE(z); // Z
db[bytes++] = HIGH_BYTE(z);
db[bytes++] = CPNT;
db[bytes++] = LOW_BYTE(x+w); // X
db[bytes++] = HIGH_BYTE(x+w);
db[bytes++] = 0; // Y
db[bytes++] = 0;
db[bytes++] = LOW_BYTE(z); // Z
db[bytes++] = HIGH_BYTE(z);
db[bytes++] = CPNT;
db[bytes++] = LOW_BYTE(x+w); // X
db[bytes++] = HIGH_BYTE(x+w);
db[bytes++] = 0; // Y
db[bytes++] = 0;
db[bytes++] = LOW_BYTE(z+l); // Z
db[bytes++] = HIGH_BYTE(z+l);
db[bytes++] = CPNT;
db[bytes++] = LOW_BYTE(x); // X
db[bytes++] = HIGH_BYTE(x);
db[bytes++] = 0; // Y
db[bytes++] = 0;
db[bytes++] = LOW_BYTE(z+l); // Z
db[bytes++] = HIGH_BYTE(z+l);
db[bytes++] = CPNT;
db[bytes++] = LOW_BYTE(x); // X
db[bytes++] = HIGH_BYTE(x);
db[bytes++] = 0; // Y
db[bytes++] = 0;
db[bytes++] = LOW_BYTE(z); // Z
db[bytes++] = HIGH_BYTE(z);
db[bytes++] = STCOL;
db[bytes++] = 15; // White
skip = l / (lines * 2);
x += (w / 2);
for (i=z + skip; i<z+l-skip; i+=(skip*2)) {
db[bytes++] = SPNT;
db[bytes++] = LOW_BYTE(x); // X
db[bytes++] = HIGH_BYTE(x);
db[bytes++] = 0; // Y
db[bytes++] = 0;
db[bytes++] = LOW_BYTE(i); // Z
db[bytes++] = HIGH_BYTE(i);
db[bytes++] = CPNT;
db[bytes++] = LOW_BYTE(x); // X
db[bytes++] = HIGH_BYTE(x);
db[bytes++] = 0; // Y
db[bytes++] = 0;
db[bytes++] = LOW_BYTE(i+skip); // Z
db[bytes++] = HIGH_BYTE(i+skip);
}
db[bytes++] = END;
}
byte memoryRead(uint16_t addr, bool isDebug) {
(void)isDebug;
return _RAM[addr];
}
void memoryWrite(uint16_t addr, byte value) {
_RAM[addr] = value;
}
void printAt(uint8_t x, uint8_t y, char *format, ...) {
va_list args;
char *string;
@ -464,43 +99,12 @@ int appMain(app_t *app, void *userData) {
app_interpolation(app, APP_INTERPOLATION_NONE);
app_window_size(app, WIDTH * 2, HEIGHT * 2);
// Clear VM RAM.
memset(_RAM, 0, 0x10000);
// Create our VM.
_v6502 = vrEmu6502New(CPU_W65C02, memoryRead, memoryWrite);
// Copy A2-3D2 into 6502 RAM.
memcpy(&_RAM[0x6000], a23d2bin, a23d2bin_len);
// Initialize A2-3D2 so we can use the "fast entry point" (NXTPT) when rendering.
bytes = A23D2_TEST_DATABASE;
_RAM[bytes++] = SCRSZ; // Screen size. 256x240. Center is 0,0. We're going to scale this up.
_RAM[bytes++] = 255; // Scales up to 320.
_RAM[bytes++] = 233; // Scales up to 193 (leaves 46 pixels for a control panel).
_RAM[bytes++] = 0;
_RAM[bytes++] = 0;
_RAM[bytes++] = END; // Setup complete!
jsr(A23D2_ENTRYN);
// Generate scene database.
landscape();
// Set up drawlist.
_drawlistInDatabase = DATABASE + 1;
_RAM[DRAWLIST_P0] = END;
// Set up camera.
_camera = (cameraT *)&_RAM[DATABASE + 4];
_camera->x = 10600;
_camera->y = PLANE_HEIGHT;
_camera->z = 10500;
_camera->p = 0;
_camera->h = 0;
// Set up render surface.
_pixels = (byte *)malloc(HEIGHT * WIDTH * 4);
// Start up 3D engine.
a23d2Init();
// Build a plane!
resetAircraft();
_plane.x = _camera->x;
@ -523,17 +127,8 @@ int appMain(app_t *app, void *userData) {
// Clear screen.
memset(_pixels, 0, HEIGHT * WIDTH * 4);
// Update drawlist.
_RAM[_drawlistInDatabase + 1] = HIGH_BYTE(DRAWLIST_P0);
_RAM[_drawlistInDatabase + 0] = LOW_BYTE(DRAWLIST_P0);
// Set IBP.
_RAM[A23D2_IBP + 1] = HIGH_BYTE(DATABASE);
_RAM[A23D2_IBP + 0] = LOW_BYTE(DATABASE);
// Render.
jsr(A23D2_NXTPT);
draw();
a23d2Render();
a23d2Draw();
fps++;
// Control Panel.
@ -679,8 +274,7 @@ int appMain(app_t *app, void *userData) {
}
// Destroy VM.
vrEmu6502Destroy(_v6502);
_v6502 = NULL;
a23d2Shutdown();
// Free render surface.
free(_pixels);