Reorganized code.
This commit is contained in:
parent
eea86533cc
commit
7040fff6e7
8 changed files with 594 additions and 423 deletions
|
@ -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
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -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
69
pc/include/bitmap.h
Normal 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
|
|
@ -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
371
pc/src/a23d2.c
Normal 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
116
pc/src/bitmap.c
Normal 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];
|
||||
}
|
|
@ -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;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
|
426
pc/src/main.c
426
pc/src/main.c
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue