Merge branch 'master' into bsnes_integration
This commit is contained in:
commit
ea7dec4e88
@ -532,7 +532,7 @@ TrademarkSymbol:
|
|||||||
db $3c,$42,$b9,$a5,$b9,$a5,$42,$3c
|
db $3c,$42,$b9,$a5,$b9,$a5,$42,$3c
|
||||||
|
|
||||||
SameBoyLogo:
|
SameBoyLogo:
|
||||||
incbin "SameBoyLogo.rle"
|
incbin "SameBoyLogo.pb8"
|
||||||
|
|
||||||
AnimationColors:
|
AnimationColors:
|
||||||
dw $7FFF ; White
|
dw $7FFF ; White
|
||||||
@ -634,41 +634,55 @@ ReadCGBLogoHalfTile:
|
|||||||
ld a, e
|
ld a, e
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
; LoadTileset using PB8 codec, 2019 Damian Yerrick
|
||||||
|
;
|
||||||
|
; The logo is compressed using PB8, a form of RLE with unary-coded
|
||||||
|
; run lengths. Each block representing 8 bytes consists of a control
|
||||||
|
; byte, where each bit (MSB to LSB) is 0 for literal or 1 for repeat
|
||||||
|
; previous, followed by the literals in that block.
|
||||||
|
|
||||||
|
SameBoyLogo_dst = $8080
|
||||||
|
SameBoyLogo_length = (128 * 24) / 64
|
||||||
|
|
||||||
LoadTileset:
|
LoadTileset:
|
||||||
; Copy SameBoy Logo
|
ld hl, SameBoyLogo
|
||||||
ld de, SameBoyLogo
|
ld de, SameBoyLogo_dst
|
||||||
ld hl, $8080
|
ld c, SameBoyLogo_length
|
||||||
.sameboyLogoLoop
|
.pb8BlockLoop:
|
||||||
ld a, [de]
|
; Register map for PB8 decompression
|
||||||
inc de
|
; HL: source address in boot ROM
|
||||||
|
; DE: destination address in VRAM
|
||||||
ld b, a
|
; A: Current literal value
|
||||||
and $0f
|
; B: Repeat bits, terminated by 1000...
|
||||||
jr z, .skipLiteral
|
; C: Number of 8-byte blocks left in this block
|
||||||
ld c, a
|
; Source address in HL lets the repeat bits go straight to B,
|
||||||
|
; bypassing A and avoiding spilling registers to the stack.
|
||||||
.literalLoop
|
ld b, [hl]
|
||||||
ld a, [de]
|
|
||||||
ldi [hl], a
|
|
||||||
inc hl
|
inc hl
|
||||||
inc de
|
|
||||||
dec c
|
|
||||||
jr nz, .literalLoop
|
|
||||||
.skipLiteral
|
|
||||||
swap b
|
|
||||||
ld a, b
|
|
||||||
and $0f
|
|
||||||
jr z, .sameboyLogoEnd
|
|
||||||
ld c, a
|
|
||||||
ld a, [de]
|
|
||||||
inc de
|
|
||||||
|
|
||||||
.repeatLoop
|
; Shift a 1 into lower bit of shift value. Once this bit
|
||||||
ldi [hl], a
|
; reaches the carry, B becomes 0 and the byte is over
|
||||||
inc hl
|
scf
|
||||||
|
rl b
|
||||||
|
|
||||||
|
.pb8BitLoop:
|
||||||
|
; If not a repeat, load a literal byte
|
||||||
|
jr c,.pb8Repeat
|
||||||
|
ld a, [hli]
|
||||||
|
.pb8Repeat:
|
||||||
|
; Decompressed data uses colors 0 and 1, so write once, inc twice
|
||||||
|
ld [de], a
|
||||||
|
inc de
|
||||||
|
inc de
|
||||||
|
sla b
|
||||||
|
jr nz, .pb8BitLoop
|
||||||
|
|
||||||
dec c
|
dec c
|
||||||
jr nz, .repeatLoop
|
jr nz, .pb8BlockLoop
|
||||||
jr .sameboyLogoLoop
|
|
||||||
|
; End PB8 decoding. The rest uses HL as the destination
|
||||||
|
ld h, d
|
||||||
|
ld l, e
|
||||||
|
|
||||||
.sameboyLogoEnd
|
.sameboyLogoEnd
|
||||||
; Copy (unresized) ROM logo
|
; Copy (unresized) ROM logo
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
#include <assert.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <io.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void pair(size_t count, uint8_t byte)
|
|
||||||
{
|
|
||||||
static size_t unique_count = 0;
|
|
||||||
static uint8_t unique_data[15];
|
|
||||||
if (count == 1) {
|
|
||||||
unique_data[unique_count++] = byte;
|
|
||||||
assert(unique_count <= 15);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
assert(count <= 15);
|
|
||||||
uint8_t control = (count << 4) | unique_count;
|
|
||||||
putchar(control);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < unique_count; i++) {
|
|
||||||
putchar(unique_data[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count != 0) {
|
|
||||||
putchar(byte);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
assert(control == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
unique_count = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
size_t count = 1;
|
|
||||||
uint8_t byte = getchar();
|
|
||||||
int new;
|
|
||||||
size_t position = 0;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
_setmode(0,_O_BINARY);
|
|
||||||
_setmode(1,_O_BINARY);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while ((new = getchar()) != EOF) {
|
|
||||||
if (byte == new) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pair(count, byte);
|
|
||||||
byte = new;
|
|
||||||
count = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pair(count, byte);
|
|
||||||
pair(0, 0);
|
|
||||||
}
|
|
330
BootROMs/pb8.c
Normal file
330
BootROMs/pb8.c
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
PB8 compressor and decompressor
|
||||||
|
|
||||||
|
Copyright 2019 Damian Yerrick
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
// For setting stdin/stdout to binary mode
|
||||||
|
#if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
|
||||||
|
#include <unistd.h>
|
||||||
|
#define fd_isatty isatty
|
||||||
|
#elif defined (_WIN32)
|
||||||
|
#include <io.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#define fd_isatty _isatty
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
; The logo is compressed using PB8, a form of RLE with unary-coded
|
||||||
|
; run lengths. Each block representing 8 bytes consists of a control
|
||||||
|
; byte, where each bit (MSB to LSB) is 0 for literal or 1 for repeat
|
||||||
|
; previous, followed by the literals in that block.
|
||||||
|
|
||||||
|
SameBoyLogo_dst = $8080
|
||||||
|
SameBoyLogo_length = (128 * 24) / 64
|
||||||
|
|
||||||
|
LoadTileset:
|
||||||
|
ld hl, SameBoyLogo
|
||||||
|
ld de, SameBoyLogo_dst
|
||||||
|
ld c, SameBoyLogo_length
|
||||||
|
.pb8BlockLoop:
|
||||||
|
; Register map for PB8 decompression
|
||||||
|
; HL: source address in boot ROM
|
||||||
|
; DE: destination address in VRAM
|
||||||
|
; A: Current literal value
|
||||||
|
; B: Repeat bits, terminated by 1000...
|
||||||
|
; C: Number of 8-byte blocks left in this block
|
||||||
|
; Source address in HL lets the repeat bits go straight to B,
|
||||||
|
; bypassing A and avoiding spilling registers to the stack.
|
||||||
|
ld b, [hl]
|
||||||
|
inc hl
|
||||||
|
|
||||||
|
; Shift a 1 into lower bit of shift value. Once this bit
|
||||||
|
; reaches the carry, B becomes 0 and the byte is over
|
||||||
|
scf
|
||||||
|
rl b
|
||||||
|
|
||||||
|
.pb8BitLoop:
|
||||||
|
; If not a repeat, load a literal byte
|
||||||
|
jr c,.pb8Repeat
|
||||||
|
ld a, [hli]
|
||||||
|
.pb8Repeat:
|
||||||
|
; Decompressed data uses colors 0 and 1, so write once, inc twice
|
||||||
|
ld [de], a
|
||||||
|
inc de
|
||||||
|
inc de
|
||||||
|
sla b
|
||||||
|
jr nz, .pb8BitLoop
|
||||||
|
|
||||||
|
dec c
|
||||||
|
jr nz, .pb8BlockLoop
|
||||||
|
ret
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Compressor and decompressor *************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compresses an input stream to PB8 data on an output stream.
|
||||||
|
* @param infp input stream
|
||||||
|
* @param outfp output stream
|
||||||
|
* @param blocklength size of an independent input block in bytes
|
||||||
|
* @return 0 for reaching infp end of file, or EOF for error
|
||||||
|
*/
|
||||||
|
int pb8(FILE *infp, FILE *outfp, size_t blocklength) {
|
||||||
|
blocklength >>= 3; // convert bytes to blocks
|
||||||
|
assert(blocklength > 0);
|
||||||
|
while (1) {
|
||||||
|
int last_byte = EOF; // value that never occurs in a file
|
||||||
|
for (size_t blkleft = blocklength; blkleft > 0; --blkleft) {
|
||||||
|
unsigned int control_byte = 0x0001;
|
||||||
|
unsigned char literals[8];
|
||||||
|
size_t nliterals = 0;
|
||||||
|
while (control_byte < 0x100) {
|
||||||
|
int c = fgetc(infp);
|
||||||
|
if (c == EOF) break;
|
||||||
|
|
||||||
|
control_byte <<= 1;
|
||||||
|
if (c == last_byte) {
|
||||||
|
control_byte |= 0x01;
|
||||||
|
} else {
|
||||||
|
literals[nliterals++] = last_byte = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (control_byte > 1) {
|
||||||
|
// Fill partial block with repeats
|
||||||
|
while (control_byte < 0x100) {
|
||||||
|
control_byte = (control_byte << 1) | 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write control byte and check for write failure
|
||||||
|
int ok = fputc(control_byte & 0xFF, outfp);
|
||||||
|
if (ok == EOF) return EOF;
|
||||||
|
size_t ok2 = fwrite(literals, 1, nliterals, outfp);
|
||||||
|
if (ok2 < nliterals) return EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If finished, return success or failure
|
||||||
|
if (ferror(infp) || ferror(outfp)) return EOF;
|
||||||
|
if (feof(infp)) return 0;
|
||||||
|
} // End 8-byte block
|
||||||
|
} // End packet, resetting last_byte
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decompresses PB8 data on an input stream to an output stream.
|
||||||
|
* @param infp input stream
|
||||||
|
* @param outfp output stream
|
||||||
|
* @return 0 for reaching infp end of file, or EOF for error
|
||||||
|
*/
|
||||||
|
int unpb8(FILE *infp, FILE *outfp) {
|
||||||
|
int last_byte = 0;
|
||||||
|
while (1) {
|
||||||
|
int control_byte = fgetc(infp);
|
||||||
|
if (control_byte == EOF) {
|
||||||
|
return feof(infp) ? 0 : EOF;
|
||||||
|
}
|
||||||
|
control_byte &= 0xFF;
|
||||||
|
for (size_t bytesleft = 8; bytesleft > 0; --bytesleft) {
|
||||||
|
if (!(control_byte & 0x80)) {
|
||||||
|
last_byte = fgetc(infp);
|
||||||
|
if (last_byte == EOF) return EOF; // read error
|
||||||
|
}
|
||||||
|
control_byte <<= 1;
|
||||||
|
int ok = fputc(last_byte, outfp);
|
||||||
|
if (ok == EOF) return EOF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CLI frontend ****************************************************/
|
||||||
|
|
||||||
|
static inline void set_fd_binary(unsigned int fd) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
_setmode(fd, _O_BINARY);
|
||||||
|
#else
|
||||||
|
(void) fd;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *usage_msg =
|
||||||
|
"usage: pb8 [-d] [-l blocklength] [infile [outfile]]\n"
|
||||||
|
"Compresses a file using RLE with unary run and literal lengths.\n"
|
||||||
|
"\n"
|
||||||
|
"options:\n"
|
||||||
|
" -d decompress\n"
|
||||||
|
" -l blocklength allow RLE packets to span up to blocklength\n"
|
||||||
|
" input bytes (multiple of 8; default 8)\n"
|
||||||
|
" -h, -?, --help show this usage page\n"
|
||||||
|
" --version show copyright info\n"
|
||||||
|
"\n"
|
||||||
|
"If infile is - or missing, it is standard input.\n"
|
||||||
|
"If outfile is - or missing, it is standard output.\n"
|
||||||
|
"You cannot compress to or decompress from a terminal.\n"
|
||||||
|
;
|
||||||
|
static const char *version_msg =
|
||||||
|
"PB8 compressor (C version) v0.01\n"
|
||||||
|
"Copyright 2019 Damian Yerrick <https://pineight.com/contact/>\n"
|
||||||
|
"This software is provided 'as-is', without any express or implied\n"
|
||||||
|
"warranty.\n"
|
||||||
|
;
|
||||||
|
static const char *toomanyfilenames_msg =
|
||||||
|
"pb8: too many filenames; try pb8 --help\n";
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
const char *infilename = NULL;
|
||||||
|
const char *outfilename = NULL;
|
||||||
|
bool decompress = false;
|
||||||
|
size_t blocklength = 8;
|
||||||
|
|
||||||
|
for (int i = 1; i < argc; ++i) {
|
||||||
|
if (argv[i][0] == '-' && argv[i][1] != 0) {
|
||||||
|
if (!strcmp(argv[i], "--help")) {
|
||||||
|
fputs(usage_msg, stdout);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!strcmp(argv[i], "--version")) {
|
||||||
|
fputs(version_msg, stdout);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -t1 or -t 1
|
||||||
|
int argtype = argv[i][1];
|
||||||
|
switch (argtype) {
|
||||||
|
case 'h':
|
||||||
|
case '?':
|
||||||
|
fputs(usage_msg, stdout);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
decompress = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'l': {
|
||||||
|
const char *argvalue = argv[i][2] ? argv[i] + 2 : argv[++i];
|
||||||
|
const char *endptr = NULL;
|
||||||
|
|
||||||
|
unsigned long tvalue = strtoul(argvalue, (char **)&endptr, 10);
|
||||||
|
if (endptr == argvalue || tvalue == 0 || tvalue > SIZE_MAX) {
|
||||||
|
fprintf(stderr, "pb8: block length %s not a positive integer\n",
|
||||||
|
argvalue);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
if (tvalue % 8 != 0) {
|
||||||
|
fprintf(stderr, "pb8: block length %s not a multiple of 8\n",
|
||||||
|
argvalue);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
blocklength = tvalue;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "pb8: unknown option -%c\n", argtype);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
} else if (!infilename) {
|
||||||
|
infilename = argv[i];
|
||||||
|
} else if (!outfilename) {
|
||||||
|
outfilename = argv[i];
|
||||||
|
} else {
|
||||||
|
fputs(toomanyfilenames_msg, stderr);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (infilename && !strcmp(infilename, "-")) {
|
||||||
|
infilename = NULL;
|
||||||
|
}
|
||||||
|
if (!infilename && decompress && fd_isatty(0)) {
|
||||||
|
fputs("pb8: cannot decompress from terminal; try redirecting stdin\n",
|
||||||
|
stderr);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
if (outfilename && !strcmp(outfilename, "-")) {
|
||||||
|
outfilename = NULL;
|
||||||
|
}
|
||||||
|
if (!outfilename && !decompress && fd_isatty(1)) {
|
||||||
|
fputs("pb8: cannot compress to terminal; try redirecting stdout or pb8 --help\n",
|
||||||
|
stderr);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *infp = NULL;
|
||||||
|
if (infilename) {
|
||||||
|
infp = fopen(infilename, "rb");
|
||||||
|
if (!infp) {
|
||||||
|
fprintf(stderr, "pb8: error opening %s ", infilename);
|
||||||
|
perror("for reading");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
infp = stdin;
|
||||||
|
set_fd_binary(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *outfp = NULL;
|
||||||
|
if (outfilename) {
|
||||||
|
outfp = fopen(outfilename, "wb");
|
||||||
|
if (!outfp) {
|
||||||
|
fprintf(stderr, "pb8: error opening %s ", outfilename);
|
||||||
|
perror("for writing");
|
||||||
|
fclose(infp);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
outfp = stdout;
|
||||||
|
set_fd_binary(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int compfailed = 0;
|
||||||
|
int has_ferror = 0;
|
||||||
|
if (decompress) {
|
||||||
|
compfailed = unpb8(infp, outfp);
|
||||||
|
} else {
|
||||||
|
compfailed = pb8(infp, outfp, blocklength);
|
||||||
|
}
|
||||||
|
fflush(outfp);
|
||||||
|
if (ferror(infp)) {
|
||||||
|
fprintf(stderr, "pb8: error reading %s\n",
|
||||||
|
infilename ? infilename : "<stdin>");
|
||||||
|
has_ferror = EOF;
|
||||||
|
}
|
||||||
|
fclose(infp);
|
||||||
|
if (ferror(outfp)) {
|
||||||
|
fprintf(stderr, "pb8: error writing %s\n",
|
||||||
|
outfilename ? outfilename : "<stdout>");
|
||||||
|
has_ferror = EOF;
|
||||||
|
}
|
||||||
|
fclose(outfp);
|
||||||
|
|
||||||
|
if (compfailed && !has_ferror) {
|
||||||
|
fputs("pb8: unknown compression failure\n", stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (compfailed || has_ferror) ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||||
|
}
|
@ -389,6 +389,7 @@ static void audioCallback(GB_gameboy_t *gb, GB_sample_t *sample)
|
|||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
[cameraSession stopRunning];
|
[cameraSession stopRunning];
|
||||||
|
self.view.gb = NULL;
|
||||||
GB_free(&gb);
|
GB_free(&gb);
|
||||||
if (cameraImage) {
|
if (cameraImage) {
|
||||||
CVBufferRelease(cameraImage);
|
CVBufferRelease(cameraImage);
|
||||||
|
@ -131,6 +131,7 @@ static const vector_float2 rect[] =
|
|||||||
- (void)drawInMTKView:(nonnull MTKView *)view
|
- (void)drawInMTKView:(nonnull MTKView *)view
|
||||||
{
|
{
|
||||||
if (!(view.window.occlusionState & NSWindowOcclusionStateVisible)) return;
|
if (!(view.window.occlusionState & NSWindowOcclusionStateVisible)) return;
|
||||||
|
if (!self.gb) return;
|
||||||
if (texture.width != GB_get_screen_width(self.gb) ||
|
if (texture.width != GB_get_screen_width(self.gb) ||
|
||||||
texture.height != GB_get_screen_height(self.gb)) {
|
texture.height != GB_get_screen_height(self.gb)) {
|
||||||
[self allocateTextures];
|
[self allocateTextures];
|
||||||
|
@ -33,6 +33,7 @@ static const GB_conflict_t cgb_conflict_map[0x80] = {
|
|||||||
/* Todo: most values not verified, and probably differ between revisions */
|
/* Todo: most values not verified, and probably differ between revisions */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Todo: verify on an MGB */
|
||||||
static const GB_conflict_t dmg_conflict_map[0x80] = {
|
static const GB_conflict_t dmg_conflict_map[0x80] = {
|
||||||
[GB_IO_IF] = GB_CONFLICT_WRITE_CPU,
|
[GB_IO_IF] = GB_CONFLICT_WRITE_CPU,
|
||||||
[GB_IO_LYC] = GB_CONFLICT_READ_OLD,
|
[GB_IO_LYC] = GB_CONFLICT_READ_OLD,
|
||||||
@ -40,7 +41,6 @@ static const GB_conflict_t dmg_conflict_map[0x80] = {
|
|||||||
[GB_IO_SCY] = GB_CONFLICT_READ_NEW,
|
[GB_IO_SCY] = GB_CONFLICT_READ_NEW,
|
||||||
[GB_IO_STAT] = GB_CONFLICT_STAT_DMG,
|
[GB_IO_STAT] = GB_CONFLICT_STAT_DMG,
|
||||||
|
|
||||||
/* Todo: these are GB_CONFLICT_READ_NEW on MGB/SGB2 */
|
|
||||||
[GB_IO_BGP] = GB_CONFLICT_PALETTE_DMG,
|
[GB_IO_BGP] = GB_CONFLICT_PALETTE_DMG,
|
||||||
[GB_IO_OBP0] = GB_CONFLICT_PALETTE_DMG,
|
[GB_IO_OBP0] = GB_CONFLICT_PALETTE_DMG,
|
||||||
[GB_IO_OBP1] = GB_CONFLICT_PALETTE_DMG,
|
[GB_IO_OBP1] = GB_CONFLICT_PALETTE_DMG,
|
||||||
@ -51,6 +51,24 @@ static const GB_conflict_t dmg_conflict_map[0x80] = {
|
|||||||
[GB_IO_SCX] = GB_CONFLICT_READ_NEW,
|
[GB_IO_SCX] = GB_CONFLICT_READ_NEW,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Todo: Verify on an SGB1 */
|
||||||
|
static const GB_conflict_t sgb_conflict_map[0x80] = {
|
||||||
|
[GB_IO_IF] = GB_CONFLICT_WRITE_CPU,
|
||||||
|
[GB_IO_LYC] = GB_CONFLICT_READ_OLD,
|
||||||
|
[GB_IO_LCDC] = GB_CONFLICT_READ_NEW,
|
||||||
|
[GB_IO_SCY] = GB_CONFLICT_READ_NEW,
|
||||||
|
[GB_IO_STAT] = GB_CONFLICT_STAT_DMG,
|
||||||
|
|
||||||
|
[GB_IO_BGP] = GB_CONFLICT_READ_NEW,
|
||||||
|
[GB_IO_OBP0] = GB_CONFLICT_READ_NEW,
|
||||||
|
[GB_IO_OBP1] = GB_CONFLICT_READ_NEW,
|
||||||
|
|
||||||
|
/* Todo: these were not verified at all */
|
||||||
|
[GB_IO_WY] = GB_CONFLICT_READ_NEW,
|
||||||
|
[GB_IO_WX] = GB_CONFLICT_READ_NEW,
|
||||||
|
[GB_IO_SCX] = GB_CONFLICT_READ_NEW,
|
||||||
|
};
|
||||||
|
|
||||||
static uint8_t cycle_read(GB_gameboy_t *gb, uint16_t addr)
|
static uint8_t cycle_read(GB_gameboy_t *gb, uint16_t addr)
|
||||||
{
|
{
|
||||||
if (gb->pending_cycles) {
|
if (gb->pending_cycles) {
|
||||||
@ -92,7 +110,17 @@ static void cycle_write(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
|
|||||||
assert(gb->pending_cycles);
|
assert(gb->pending_cycles);
|
||||||
GB_conflict_t conflict = GB_CONFLICT_READ_OLD;
|
GB_conflict_t conflict = GB_CONFLICT_READ_OLD;
|
||||||
if ((addr & 0xFF80) == 0xFF00) {
|
if ((addr & 0xFF80) == 0xFF00) {
|
||||||
conflict = (GB_is_cgb(gb)? cgb_conflict_map : dmg_conflict_map)[addr & 0x7F];
|
const GB_conflict_t *map = NULL;
|
||||||
|
if (GB_is_cgb(gb)) {
|
||||||
|
map = cgb_conflict_map;
|
||||||
|
}
|
||||||
|
else if (GB_is_sgb(gb)) {
|
||||||
|
map = sgb_conflict_map;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
map = dmg_conflict_map;
|
||||||
|
}
|
||||||
|
conflict = map[addr & 0x7F];
|
||||||
}
|
}
|
||||||
switch (conflict) {
|
switch (conflict) {
|
||||||
case GB_CONFLICT_READ_OLD:
|
case GB_CONFLICT_READ_OLD:
|
||||||
|
26
Makefile
26
Makefile
@ -13,13 +13,15 @@ ifneq ($(findstring MSYS,$(PLATFORM)),)
|
|||||||
PLATFORM := windows32
|
PLATFORM := windows32
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LOGO_COMPRESS := build/logo-compress
|
|
||||||
|
|
||||||
ifeq ($(PLATFORM),windows32)
|
ifeq ($(PLATFORM),windows32)
|
||||||
_ := $(shell chcp 65001)
|
_ := $(shell chcp 65001)
|
||||||
LOGO_COMPRESS := build/logo-compress.exe
|
EXESUFFIX:=.exe
|
||||||
|
else
|
||||||
|
EXESUFFIX:=
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
PB8_COMPRESS := build/pb8$(EXESUFFIX)
|
||||||
|
|
||||||
ifeq ($(PLATFORM),Darwin)
|
ifeq ($(PLATFORM),Darwin)
|
||||||
DEFAULT := cocoa
|
DEFAULT := cocoa
|
||||||
else
|
else
|
||||||
@ -79,7 +81,7 @@ OPEN_DIALOG = OpenDialog/cocoa.m
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
CFLAGS += -Werror -Wall -Wno-strict-aliasing -Wno-unknown-warning -Wno-unknown-warning-option -Wno-multichar -Wno-int-in-bool-context -std=gnu11 -D_GNU_SOURCE -DVERSION="$(VERSION)" -I. -D_USE_MATH_DEFINES
|
CFLAGS += -Werror -Wall -Wno-unused-result -Wno-strict-aliasing -Wno-unknown-warning -Wno-unknown-warning-option -Wno-multichar -Wno-int-in-bool-context -std=gnu11 -D_GNU_SOURCE -DVERSION="$(VERSION)" -I. -D_USE_MATH_DEFINES
|
||||||
SDL_LDFLAGS := -lSDL2 -lGL
|
SDL_LDFLAGS := -lSDL2 -lGL
|
||||||
ifeq ($(PLATFORM),windows32)
|
ifeq ($(PLATFORM),windows32)
|
||||||
CFLAGS += -IWindows -Drandom=rand
|
CFLAGS += -IWindows -Drandom=rand
|
||||||
@ -302,11 +304,11 @@ $(BIN)/tester/sameboy_tester.exe: $(CORE_OBJECTS) $(SDL_OBJECTS)
|
|||||||
$(BIN)/SDL/%.bin $(BIN)/tester/%.bin: $(BOOTROMS_DIR)/%.bin
|
$(BIN)/SDL/%.bin $(BIN)/tester/%.bin: $(BOOTROMS_DIR)/%.bin
|
||||||
-@$(MKDIR) -p $(dir $@)
|
-@$(MKDIR) -p $(dir $@)
|
||||||
cp -f $^ $@
|
cp -f $^ $@
|
||||||
|
|
||||||
$(BIN)/SameBoy.app/Contents/Resources/%.bin: $(BOOTROMS_DIR)/%.bin
|
$(BIN)/SameBoy.app/Contents/Resources/%.bin: $(BOOTROMS_DIR)/%.bin
|
||||||
-@$(MKDIR) -p $(dir $@)
|
-@$(MKDIR) -p $(dir $@)
|
||||||
cp -f $^ $@
|
cp -f $^ $@
|
||||||
|
|
||||||
$(BIN)/SDL/LICENSE: LICENSE
|
$(BIN)/SDL/LICENSE: LICENSE
|
||||||
-@$(MKDIR) -p $(dir $@)
|
-@$(MKDIR) -p $(dir $@)
|
||||||
cp -f $^ $@
|
cp -f $^ $@
|
||||||
@ -314,7 +316,7 @@ $(BIN)/SDL/LICENSE: LICENSE
|
|||||||
$(BIN)/SDL/registers.sym: Misc/registers.sym
|
$(BIN)/SDL/registers.sym: Misc/registers.sym
|
||||||
-@$(MKDIR) -p $(dir $@)
|
-@$(MKDIR) -p $(dir $@)
|
||||||
cp -f $^ $@
|
cp -f $^ $@
|
||||||
|
|
||||||
$(BIN)/SDL/background.bmp: SDL/background.bmp
|
$(BIN)/SDL/background.bmp: SDL/background.bmp
|
||||||
-@$(MKDIR) -p $(dir $@)
|
-@$(MKDIR) -p $(dir $@)
|
||||||
cp -f $^ $@
|
cp -f $^ $@
|
||||||
@ -329,17 +331,17 @@ $(OBJ)/%.1bpp: %.png
|
|||||||
-@$(MKDIR) -p $(dir $@)
|
-@$(MKDIR) -p $(dir $@)
|
||||||
rgbgfx -d 1 -h -o $@ $<
|
rgbgfx -d 1 -h -o $@ $<
|
||||||
|
|
||||||
$(OBJ)/BootROMs/SameBoyLogo.rle: $(OBJ)/BootROMs/SameBoyLogo.1bpp $(LOGO_COMPRESS)
|
$(OBJ)/BootROMs/SameBoyLogo.pb8: $(OBJ)/BootROMs/SameBoyLogo.1bpp $(PB8_COMPRESS)
|
||||||
$(realpath $(LOGO_COMPRESS)) < $< > $@
|
$(realpath $(PB8_COMPRESS)) -l 384 $< $@
|
||||||
|
|
||||||
$(LOGO_COMPRESS): BootROMs/logo-compress.c
|
$(PB8_COMPRESS): BootROMs/pb8.c
|
||||||
$(CC) $< -o $@
|
$(CC) $< -o $@
|
||||||
|
|
||||||
$(BIN)/BootROMs/agb_boot.bin: BootROMs/cgb_boot.asm
|
$(BIN)/BootROMs/agb_boot.bin: BootROMs/cgb_boot.asm
|
||||||
$(BIN)/BootROMs/cgb_boot_fast.bin: BootROMs/cgb_boot.asm
|
$(BIN)/BootROMs/cgb_boot_fast.bin: BootROMs/cgb_boot.asm
|
||||||
$(BIN)/BootROMs/sgb2_boot: BootROMs/sgb_boot.asm
|
$(BIN)/BootROMs/sgb2_boot: BootROMs/sgb_boot.asm
|
||||||
|
|
||||||
$(BIN)/BootROMs/%.bin: BootROMs/%.asm $(OBJ)/BootROMs/SameBoyLogo.rle
|
$(BIN)/BootROMs/%.bin: BootROMs/%.asm $(OBJ)/BootROMs/SameBoyLogo.pb8
|
||||||
-@$(MKDIR) -p $(dir $@)
|
-@$(MKDIR) -p $(dir $@)
|
||||||
rgbasm -i $(OBJ)/BootROMs/ -i BootROMs/ -o $@.tmp $<
|
rgbasm -i $(OBJ)/BootROMs/ -i BootROMs/ -o $@.tmp $<
|
||||||
rgblink -o $@.tmp2 $@.tmp
|
rgblink -o $@.tmp2 $@.tmp
|
||||||
@ -349,7 +351,7 @@ $(BIN)/BootROMs/%.bin: BootROMs/%.asm $(OBJ)/BootROMs/SameBoyLogo.rle
|
|||||||
# Libretro Core (uses its own build system)
|
# Libretro Core (uses its own build system)
|
||||||
libretro:
|
libretro:
|
||||||
$(MAKE) -C libretro
|
$(MAKE) -C libretro
|
||||||
|
|
||||||
# Clean
|
# Clean
|
||||||
clean:
|
clean:
|
||||||
rm -rf build
|
rm -rf build
|
||||||
|
@ -23,6 +23,11 @@
|
|||||||
#define AUDIO_FREQUENCY 48000
|
#define AUDIO_FREQUENCY 48000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Compatibility with older SDL versions */
|
||||||
|
#ifndef SDL_AUDIO_ALLOW_SAMPLES_CHANGE
|
||||||
|
#define SDL_AUDIO_ALLOW_SAMPLES_CHANGE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
GB_gameboy_t gb;
|
GB_gameboy_t gb;
|
||||||
static bool paused = false;
|
static bool paused = false;
|
||||||
static uint32_t pixel_buffer_1[256 * 224], pixel_buffer_2[256 * 224];
|
static uint32_t pixel_buffer_1[256 * 224], pixel_buffer_2[256 * 224];
|
||||||
@ -464,7 +469,7 @@ restart:
|
|||||||
start_capturing_logs();
|
start_capturing_logs();
|
||||||
const char * const boot_roms[] = {"dmg_boot.bin", "cgb_boot.bin", "agb_boot.bin", "sgb_boot.bin"};
|
const char * const boot_roms[] = {"dmg_boot.bin", "cgb_boot.bin", "agb_boot.bin", "sgb_boot.bin"};
|
||||||
const char *boot_rom = boot_roms[configuration.model];
|
const char *boot_rom = boot_roms[configuration.model];
|
||||||
if (configuration.model == GB_MODEL_SGB && configuration.sgb_revision == SGB_2) {
|
if (configuration.model == MODEL_SGB && configuration.sgb_revision == SGB_2) {
|
||||||
boot_rom = "sgb2_boot.bin";
|
boot_rom = "sgb2_boot.bin";
|
||||||
}
|
}
|
||||||
error = GB_load_boot_rom(&gb, resource_path(boot_rom));
|
error = GB_load_boot_rom(&gb, resource_path(boot_rom));
|
||||||
|
@ -1,2 +1 @@
|
|||||||
APP_STL := gnustl_static
|
|
||||||
APP_ABI := all
|
APP_ABI := all
|
||||||
|
@ -84,7 +84,7 @@ static struct retro_log_callback logging;
|
|||||||
static retro_log_printf_t log_cb;
|
static retro_log_printf_t log_cb;
|
||||||
|
|
||||||
static retro_video_refresh_t video_cb;
|
static retro_video_refresh_t video_cb;
|
||||||
static retro_audio_sample_batch_t audio_batch_cb;
|
static retro_audio_sample_t audio_sample_cb;
|
||||||
static retro_input_poll_t input_poll_cb;
|
static retro_input_poll_t input_poll_cb;
|
||||||
static retro_input_state_t input_state_cb;
|
static retro_input_state_t input_state_cb;
|
||||||
|
|
||||||
@ -152,7 +152,7 @@ static void audio_callback(GB_gameboy_t *gb, GB_sample_t *sample)
|
|||||||
{
|
{
|
||||||
if ((audio_out == GB_1 && gb == &gameboy[0]) ||
|
if ((audio_out == GB_1 && gb == &gameboy[0]) ||
|
||||||
(audio_out == GB_2 && gb == &gameboy[1])) {
|
(audio_out == GB_2 && gb == &gameboy[1])) {
|
||||||
audio_batch_cb((void*)sample, 1);
|
audio_sample_cb(sample->left, sample->right);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -772,11 +772,11 @@ void retro_set_environment(retro_environment_t cb)
|
|||||||
|
|
||||||
void retro_set_audio_sample(retro_audio_sample_t cb)
|
void retro_set_audio_sample(retro_audio_sample_t cb)
|
||||||
{
|
{
|
||||||
|
audio_sample_cb = cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb)
|
void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb)
|
||||||
{
|
{
|
||||||
audio_batch_cb = cb;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void retro_set_input_poll(retro_input_poll_t cb)
|
void retro_set_input_poll(retro_input_poll_t cb)
|
||||||
@ -850,8 +850,7 @@ void retro_run(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int x = GB_run_frame(&gameboy[0]);
|
GB_run_frame(&gameboy[0]);
|
||||||
log_cb(RETRO_LOG_DEBUG, "%d\n", x);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (emulated_devices == 2)
|
if (emulated_devices == 2)
|
||||||
|
Loading…
Reference in New Issue
Block a user