First commit.
Way too much.. Sould have done this sooner...
This commit is contained in:
commit
2fb9be227d
|
@ -0,0 +1,3 @@
|
|||
build-*/
|
||||
*.ch8
|
||||
*.g*a
|
|
@ -0,0 +1,194 @@
|
|||
#! /usr/bin/make -f
|
||||
# Default Makefile for fxSDK add-ins. This file was probably copied there by
|
||||
# the [fxsdk] program.
|
||||
#---
|
||||
|
||||
#
|
||||
# Configuration
|
||||
#
|
||||
|
||||
include project.cfg
|
||||
|
||||
# Compiler flags
|
||||
CFLAGSFX := $(CFLAGS) $(CFLAGS_FX) $(INCLUDE)
|
||||
CFLAGSCG := $(CFLAGS) $(CFLAGS_CG) $(INCLUDE)
|
||||
|
||||
# Linker flags
|
||||
LDFLAGSFX := $(LDFLAGS) $(LDFLAGS_FX)
|
||||
LDFLAGSCG := $(LDFLAGS) $(LDFLAGS_CG)
|
||||
|
||||
# Dependency list generation flags
|
||||
depflags = -MMD -MT $@ -MF $(@:.o=.d) -MP
|
||||
# ELF to binary flags
|
||||
BINFLAGS := -R .bss -R .gint_bss
|
||||
|
||||
# G1A and G3A generation flags
|
||||
NAME_G1A ?= $(NAME)
|
||||
NAME_G3A ?= $(NAME)
|
||||
G1AF := -i "$(ICON_FX)" -n "$(NAME_G1A)" --internal="$(INTERNAL)"
|
||||
G3AF := -n basic:"$(NAME_G3A)" -i uns:"$(ICON_CG_UNS)" -i sel:"$(ICON_CG_SEL)"
|
||||
|
||||
ifeq "$(TOOLCHAIN_FX)" ""
|
||||
TOOLCHAIN_FX := sh3eb-elf
|
||||
endif
|
||||
|
||||
ifeq "$(TOOLCHAIN_CG)" ""
|
||||
TOOLCHAIN_CG := sh4eb-elf
|
||||
endif
|
||||
|
||||
# fxconv flags
|
||||
FXCONVFX := --fx --toolchain=$(TOOLCHAIN_FX)
|
||||
FXCONVCG := --cg --toolchain=$(TOOLCHAIN_CG)
|
||||
|
||||
#
|
||||
# File listings
|
||||
#
|
||||
|
||||
NULL :=
|
||||
TARGET := $(subst $(NULL) $(NULL),-,$(NAME))
|
||||
|
||||
ifeq "$(TARGET_FX)" ""
|
||||
TARGET_FX := $(TARGET).g1a
|
||||
endif
|
||||
|
||||
ifeq "$(TARGET_CG)" ""
|
||||
TARGET_CG := $(TARGET).g3a
|
||||
endif
|
||||
|
||||
ELF_FX := build-fx/$(shell basename -s .g1a $(TARGET_FX)).elf
|
||||
BIN_FX := $(ELF_FX:.elf=.bin)
|
||||
|
||||
ELF_CG := build-cg/$(shell basename -s .g3a $(TARGET_CG)).elf
|
||||
BIN_CG := $(ELF_CG:.elf=.bin)
|
||||
|
||||
# Source files
|
||||
src := $(wildcard src/*.[csS] \
|
||||
src/*/*.[csS] \
|
||||
src/*/*/*.[csS] \
|
||||
src/*/*/*/*.[csS])
|
||||
assets-fx := $(wildcard assets-fx/*/*)
|
||||
assets-cg := $(wildcard assets-cg/*/*)
|
||||
|
||||
# Object files
|
||||
obj-fx := $(src:%=build-fx/%.o) \
|
||||
$(assets-fx:assets-fx/%=build-fx/assets/%.o)
|
||||
obj-cg := $(src:%=build-cg/%.o) \
|
||||
$(assets-cg:assets-cg/%=build-cg/assets/%.o)
|
||||
|
||||
# Additional dependencies
|
||||
deps-fx := $(ICON_FX)
|
||||
deps-cg := $(ICON_CG_UNS) $(ICON_CG_SEL)
|
||||
|
||||
# All targets
|
||||
all :=
|
||||
ifneq "$(wildcard build-fx)" ""
|
||||
all += all-fx
|
||||
endif
|
||||
ifneq "$(wildcard build-cg)" ""
|
||||
all += all-cg
|
||||
endif
|
||||
|
||||
#
|
||||
# Build rules
|
||||
#
|
||||
|
||||
all: $(all)
|
||||
|
||||
all-fx: $(TARGET_FX)
|
||||
all-cg: $(TARGET_CG)
|
||||
|
||||
$(TARGET_FX): $(obj-fx) $(deps-fx)
|
||||
@ mkdir -p $(dir $@)
|
||||
$(TOOLCHAIN_FX)-gcc -o $(ELF_FX) $(obj-fx) $(CFLAGSFX) $(LDFLAGSFX)
|
||||
$(TOOLCHAIN_FX)-objcopy -O binary $(BINFLAGS) $(ELF_FX) $(BIN_FX)
|
||||
fxg1a $(BIN_FX) -o $@ $(G1AF)
|
||||
|
||||
$(TARGET_CG): $(obj-cg) $(deps-cg)
|
||||
@ mkdir -p $(dir $@)
|
||||
$(TOOLCHAIN_CG)-gcc -o $(ELF_CG) $(obj-cg) $(CFLAGSCG) $(LDFLAGSCG)
|
||||
$(TOOLCHAIN_CG)-objcopy -O binary $(BINFLAGS) $(ELF_CG) $(BIN_CG)
|
||||
mkg3a $(G3AF) $(BIN_CG) $@
|
||||
|
||||
# C sources
|
||||
build-fx/%.c.o: %.c
|
||||
@ mkdir -p $(dir $@)
|
||||
$(TOOLCHAIN_FX)-gcc -c $< -o $@ $(CFLAGSFX) $(depflags)
|
||||
build-cg/%.c.o: %.c
|
||||
@ mkdir -p $(dir $@)
|
||||
$(TOOLCHAIN_CG)-gcc -c $< -o $@ $(CFLAGSCG) $(depflags)
|
||||
|
||||
# Assembler sources
|
||||
build-fx/%.s.o: %.s
|
||||
@ mkdir -p $(dir $@)
|
||||
$(TOOLCHAIN_FX)-gcc -c $< -o $@
|
||||
build-cg/%.s.o: %.s
|
||||
@ mkdir -p $(dir $@)
|
||||
$(TOOLCHAIN_CG)-gcc -c $< -o $@
|
||||
|
||||
# Preprocessed assembler sources
|
||||
build-fx/%.S.o: %.S
|
||||
@ mkdir -p $(dir $@)
|
||||
$(TOOLCHAIN_FX)-gcc -c $< -o $@ $(INCLUDE)
|
||||
build-cg/%.S.o: %.S
|
||||
@ mkdir -p $(dir $@)
|
||||
$(TOOLCHAIN_CG)-gcc -c $< -o $@ $(INCLUDE)
|
||||
|
||||
# Images
|
||||
build-fx/assets/img/%.o: assets-fx/img/%
|
||||
@ mkdir -p $(dir $@)
|
||||
fxconv -i $< -o $@ $(FXCONVFX) name:img_$(basename $*) $(IMG.$*)
|
||||
build-cg/assets/img/%.o: assets-cg/img/%
|
||||
@ mkdir -p $(dir $@)
|
||||
fxconv -i $< -o $@ $(FXCONVCG) name:img_$(basename $*) $(IMG.$*)
|
||||
|
||||
# Fonts
|
||||
build-fx/assets/fonts/%.o: assets-fx/fonts/%
|
||||
@ mkdir -p $(dir $@)
|
||||
fxconv -f $< -o $@ $(FXCONVFX) name:font_$(basename $*) $(FONT.$*)
|
||||
build-cg/assets/fonts/%.o: assets-cg/fonts/%
|
||||
@ mkdir -p $(dir $@)
|
||||
fxconv -f $< -o $@ $(FXCONVCG) name:font_$(basename $*) $(FONT.$*)
|
||||
|
||||
# Binaries
|
||||
build-fx/assets/bin/%.o: assets-fx/bin/%
|
||||
@ mkdir -p $(dir $@)
|
||||
fxconv -b $< -o $@ $(FXCONVFX) name:bin_$(basename $*) $(BIN.$*)
|
||||
build-cg/assets/bin/%.o: assets-cg/bin/%
|
||||
@ mkdir -p $(dir $@)
|
||||
fxconv -b $< -o $@ $(FXCONVCG) name:bin_$(basename $*) $(BIN.$*)
|
||||
|
||||
#
|
||||
# Cleaning and utilities
|
||||
#
|
||||
|
||||
# Dependency information
|
||||
-include $(shell find build* -name *.d 2> /dev/null)
|
||||
build-fx/%.d: ;
|
||||
build-cg/%.d: ;
|
||||
.PRECIOUS: build-fx build-cg build-fx/%.d build-cg/%.d %/
|
||||
|
||||
clean-fx:
|
||||
@ rm -rf build-fx/
|
||||
clean-cg:
|
||||
@ rm -rf build-cg/
|
||||
|
||||
distclean-fx: clean-fx
|
||||
@ rm -f $(TARGET_FX)
|
||||
distclean-cg: clean-cg
|
||||
@ rm -f $(TARGET_CG)
|
||||
|
||||
clean: clean-fx clean-cg
|
||||
|
||||
distclean: distclean-fx distclean-cg
|
||||
|
||||
install-fx: $(TARGET_FX)
|
||||
p7 send -f $<
|
||||
install-cg: $(TARGET_CG)
|
||||
@ while [[ ! -h /dev/Prizm1 ]]; do sleep 0.25; done
|
||||
@ while ! mount /dev/Prizm1; do sleep 0.25; done
|
||||
@ rm -f /mnt/prizm/$<
|
||||
@ cp $< /mnt/prizm
|
||||
@ umount /dev/Prizm1
|
||||
@- eject /dev/Prizm1
|
||||
|
||||
.PHONY: all all-fx all-cg clean distclean install-fx install-cg
|
Binary file not shown.
After Width: | Height: | Size: 8.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 7.3 KiB |
|
@ -0,0 +1,22 @@
|
|||
#ifndef _CHIP_8_H_
|
||||
#define _CHIP_8_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define STACK_SIZE 0xF+1
|
||||
|
||||
struct Chip8
|
||||
{
|
||||
uint8_t memory[0xFFF+1];
|
||||
uint8_t regist[0xF+1];
|
||||
uint16_t stack[STACK_SIZE];
|
||||
uint16_t PC; //program counter
|
||||
uint16_t I; //Special register
|
||||
uint8_t SP; //Stack pointer
|
||||
uint8_t DT; //Delay timer
|
||||
uint8_t ST; //Sound timer
|
||||
uint64_t vram[32];//waiting for c21 and uint128_t for big screen :3c
|
||||
};
|
||||
|
||||
|
||||
#endif //_CHIP_8_H_
|
|
@ -0,0 +1,76 @@
|
|||
#ifndef _OPCODE_H_
|
||||
#define _OPCODE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <gint/display.h>
|
||||
#include <gint/keyboard.h>
|
||||
#include "Chip8.h"
|
||||
|
||||
#define N (opcode&0x000F)
|
||||
#define NNN (opcode&0x0FFF)
|
||||
#define X (opcode&0x0F00)>>8
|
||||
#define Y (opcode&0x00F0)>>4
|
||||
#define KK (opcode&0x00FF)
|
||||
|
||||
|
||||
void execute();
|
||||
|
||||
void op0table(); //
|
||||
void op00E0(); //clear screen
|
||||
void op00EE(); //return
|
||||
|
||||
void op1NNN(); //jump
|
||||
|
||||
void op2NNN(); //call
|
||||
|
||||
void op3XKK(); //skip if reg[X] equal KK
|
||||
|
||||
void op4XKK(); //skip if reg[X] not equal KK
|
||||
|
||||
void op5XY0(); //skip if reg[X] equal reg[Y]
|
||||
|
||||
void op6XKK(); //Load KK in reg[X]
|
||||
|
||||
void op7XKK(); //reg[X] += KK, no carry
|
||||
|
||||
void op8table();
|
||||
void op8XY0(); //load reg[Y] in reg [X]
|
||||
void op8XY1(); //OR reg[X] and reg[Y] in reg [X]
|
||||
void op8XY2(); //AND reg[X] and reg[Y] in reg [X]
|
||||
void op8XY3(); //XOR reg[X] and reg[Y] in reg [X]
|
||||
void op8XY4(); //add reg[X] and reg[Y] in reg[X] whit carry
|
||||
void op8XY5(); //reg[X] = reg[X] -reg[Y] with NOT borrow
|
||||
void op8XY6(); //rotate reg[X] -> and save the least significant bit in the carry flag
|
||||
void op8XY7(); //reg[X] = reg[X] -reg[Y] with NOT borrow
|
||||
void op8XYE(); //rotate reg[X] <- and save the least significant bit in the carry flag
|
||||
|
||||
void op9XY0(); //skip if reg[X] not equal reg[Y]
|
||||
|
||||
void opANNN(); //load NNN into I
|
||||
|
||||
void opBNNN(); //jump to address regist[0]+NNN
|
||||
|
||||
void opCXKK(); //set regist[X] = random(0,255) AND KK
|
||||
|
||||
void opDXYN(); //xor the sprite of size 8*N at adress I on the screen at position (regist[X],regist[Y])
|
||||
//if a pixel is erased, set set carry flag.
|
||||
|
||||
void opEtable();
|
||||
void opEX9E(); //skip if regist[X] equal value of key pressed
|
||||
void opEXA1(); //skip if regist[X] not equal value of key pressed
|
||||
|
||||
void opFtable();
|
||||
void opF5table();
|
||||
void opFX07(); //set regist[X] = DelayTimer
|
||||
void opFX0A(); //set regist[X] = keycode of pressed key (wait for press if not any)
|
||||
void opFX15(); //set DelayTimer = regist[X]
|
||||
void opFX18(); //set SoundTimer = regist[X]
|
||||
void opFX1E(); //set I = I + regist[X]
|
||||
void opFX29(); //set I to the location to draw the char stored in regist[X]
|
||||
void opFX33(); //store BCD representation of regist[X] in the adress I(hundreds), I+1(tens), I+2(digits)
|
||||
void opFX55(); //store regist[0]~regist[X] into memory adress I~I+X
|
||||
void opFX65(); //load regist[0]~regist[X] from memory adress I~I+X
|
||||
void uninplemented();
|
||||
|
||||
|
||||
#endif // _OPCODE_H_
|
|
@ -0,0 +1,84 @@
|
|||
#---
|
||||
# fxSDK project configuration file for Chip8Emu
|
||||
#---
|
||||
|
||||
# Project name, should be at most 8 bytes long.
|
||||
# (You can also specify NAME_G1A or NAME_G3A to override individually.)
|
||||
NAME := Chip8Emu
|
||||
|
||||
# Internal name, should be '@' followed by at most 7 uppercase letters.
|
||||
# WARNING: If this convention is not followed, the add-in might not appear in
|
||||
# the main menu of the calculator!
|
||||
INTERNAL := @HUITEMU
|
||||
|
||||
# Output file name. The default is to take <NAME>, replace spaces with dashes,
|
||||
# and add .g1a (or .g3a). You can specify a different folder if you want.
|
||||
TARGET_FX :=
|
||||
TARGET_CG :=
|
||||
|
||||
# fx-9860G icon location
|
||||
ICON_FX = assets-fx/icon-fx.png
|
||||
# fx-CG 50 icon locations
|
||||
ICON_CG_UNS = assets-cg/icon-cg-uns.png
|
||||
ICON_CG_SEL = assets-cg/icon-cg-sel.png
|
||||
|
||||
#---
|
||||
# Toolchain selection
|
||||
#---
|
||||
|
||||
# Toolchain for fx9860g. Please see also CFLAGS_FX below.
|
||||
TOOLCHAIN_FX := sh-elf
|
||||
|
||||
# Toolchain for fxcg50. Please see also CFLAGS_CG below.
|
||||
TOOLCHAIN_CG := sh-elf
|
||||
|
||||
#---
|
||||
# Compiler flags
|
||||
#---
|
||||
|
||||
# Base compiler flags for the fxSDK, you usually want to keep these.
|
||||
CFLAGS := -mb -ffreestanding -nostdlib -fstrict-volatile-bitfields
|
||||
|
||||
# Platform-specific compiler flags.
|
||||
# <> If you are using sh3eb-elf, use -m3. (You can do this on both FX and CG.)
|
||||
# <> If you are using sh4eb-elf, use -m4-nofpu. (Not ideal on FX but works.)
|
||||
# <> If you are using sh4eb-nofpu-elf, then your compiler will likely use the
|
||||
# FPU and cause problems on the calculator. Consider another configuration.
|
||||
# <> If you are using an sh-elf with several targets, specify whichever you
|
||||
# support. I recommend -m3 on FX and -m4-nofpu on CG.
|
||||
# Please see also TOOLCHAIN_FX and TOOLCHAIN_CG above.
|
||||
CFLAGS_FX := -D FX9860G -m3
|
||||
CFLAGS_CG := -D FXCG50 -m4-nofpu
|
||||
|
||||
# Additional compiler flags, change to your own taste!
|
||||
CFLAGS += -Wall -Wextra -Os
|
||||
|
||||
# Include paths. Add one -I option for each folder from which you want to
|
||||
# be able to include files with #include<>.
|
||||
INCLUDE := -I include
|
||||
|
||||
# Libraries. Add one -l option for each library you are using, and also
|
||||
# suitable -L options if you have library files in custom folders. To use
|
||||
# fxlib, add libfx.a to the project directory and use "-L . -lfx".
|
||||
LIBS :=
|
||||
|
||||
# Base linker flags for the fxSDK, you usually want to keep these.
|
||||
LDFLAGS_FX := -T fx9860g.ld -lgint-fx $(LIBS) -lgint-fx -lgcc
|
||||
LDFLAGS_CG := -T fxcg50.ld -lgint-cg $(LIBS) -lgint-cg -lgcc
|
||||
|
||||
# Additional linker flags, if you need any.
|
||||
LDFLAGS :=
|
||||
|
||||
# Additional platform-specific linker flags.
|
||||
LDFLAGS_FX += -Wl,-Map=build-fx/map
|
||||
LDFLAGS_CG += -Wl,-Map=build-cg/map
|
||||
|
||||
#---
|
||||
# File conversion parameters
|
||||
#---
|
||||
|
||||
# Here you can add fxconv options for each converted file, individually.
|
||||
# The syntax is "<type>.<file>". For example, to specify the parameters for a
|
||||
# font name "hexa.png", you might write:
|
||||
#
|
||||
# FONT.hexa.png = charset:print grid:size:3x5 grid.padding:1
|
|
@ -0,0 +1,52 @@
|
|||
#include <gint/display.h>
|
||||
#include <gint/keyboard.h>
|
||||
#include <gint/bfile.h>
|
||||
#include "Chip8.h"
|
||||
#include "opcode.h"
|
||||
struct Chip8 chip8 = {
|
||||
.PC = 0x200,
|
||||
.memory= { //bitmap for the fonts
|
||||
0xF0, 0x90, 0x90, 0x90, 0xF0, //0
|
||||
0x20, 0x60, 0x20, 0x20, 0x70, //1
|
||||
0xF0, 0x10, 0xF0, 0x80, 0xF0, //2
|
||||
0xF0, 0x10, 0xF0, 0x10, 0xF0, //3
|
||||
0x90, 0x90, 0xF0, 0x10, 0x10, //4
|
||||
0xF0, 0x80, 0xF0, 0x10, 0xF0, //5
|
||||
0xF0, 0x80, 0xF0, 0x90, 0xF0, //6
|
||||
0xF0, 0x10, 0x20, 0x40, 0x40, //7
|
||||
0xF0, 0x90, 0xF0, 0x90, 0xF0, //8
|
||||
0xF0, 0x90, 0xF0, 0x10, 0xF0, //9
|
||||
0xF0, 0x90, 0xF0, 0x90, 0x90, //A
|
||||
0xE0, 0x90, 0xE0, 0x90, 0xE0, //B
|
||||
0xF0, 0x80, 0x80, 0x80, 0xF0, //C
|
||||
0xE0, 0x90, 0x90, 0x90, 0xE0, //D
|
||||
0xF0, 0x80, 0xF0, 0x80, 0xF0, //E
|
||||
0xF0, 0x80, 0xF0, 0x80, 0x80 //F
|
||||
}};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int file_handler;
|
||||
uint16_t const * pathname = u"\\\\fls0\\PUZZLE.ch8";
|
||||
dclear(C_BLACK);
|
||||
dupdate();
|
||||
file_handler = BFile_Open(pathname, BFile_ReadOnly);
|
||||
/* if(file_handler > 0)
|
||||
{
|
||||
dtext(1,1,"reading", C_BLACK, C_WHITE);
|
||||
dupdate();
|
||||
getkey();
|
||||
}
|
||||
if(BFile_Read(file_handler, &chip8.memory[0x200], 3000,-1) > 0)
|
||||
{
|
||||
dtext(1,1,"reading", C_BLACK, C_WHITE);
|
||||
dupdate();
|
||||
getkey();
|
||||
}*/
|
||||
BFile_Read(file_handler, &chip8.memory[0x200], 264,-1);
|
||||
while(1)
|
||||
{
|
||||
execute();
|
||||
}
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,374 @@
|
|||
#include "Chip8.h"
|
||||
#include "opcode.h"
|
||||
|
||||
extern struct Chip8 chip8;
|
||||
|
||||
uint16_t opcode;
|
||||
|
||||
/*
|
||||
Chip8 Keyboard and Casio keyboard
|
||||
_________ | ___________
|
||||
|1|2|3|C| | |7|8|9|DEL|
|
||||
--------- | -----------
|
||||
|4|5|6|D| | |4|5|6| x |
|
||||
--------- | -----------
|
||||
|7|8|9|E| | |1|2|3| + |
|
||||
--------- | -----------
|
||||
|A|0|B|F| | |0|.|E|(-)| (that's the little E for *10^)
|
||||
*/
|
||||
const int Chip8Kb2Casio[0xF+1] =
|
||||
{
|
||||
KEY_DOT, KEY_7, KEY_8, KEY_9, KEY_4, KEY_5, KEY_6, KEY_1, KEY_2, KEY_3, KEY_0, KEY_EXP, KEY_DEL, KEY_MUL, KEY_ADD, KEY_NEG
|
||||
};
|
||||
/*
|
||||
keycode are progressing from right to left and bottom to top with gap in it, so it will need a magic function to map the key we are interrested in [0x11-0x44] to [0x0-0xF]
|
||||
|
||||
Casiokeycode, Casiokeycode after magic function Keyboard and Chip8 keyboard
|
||||
_____________ | _________ | _________
|
||||
|41|42|43|44| | |C|D|E|F| | |1|2|3|C|
|
||||
------------- | --------- | ---------
|
||||
|31|32|33|34| | |8|9|A|B| | |4|5|6|D|
|
||||
------------- | --------- | ---------
|
||||
|21|22|23|24| | |4|5|6|7| | |7|8|9|E|
|
||||
------------- | --------- | ---------
|
||||
|11|12|13|14| | |0|1|2|3| | |A|0|B|F|
|
||||
the magic function consist to first substracting 0xC from keycode for each "tens" and then substract 0x5
|
||||
|
||||
new_kcode = old_kcode - (0xC * (old_kcode / 0x10)) - 0x5
|
||||
|
||||
care should be taken that this is only used on those 16 keys aboves
|
||||
|
||||
*/
|
||||
const int CasioKb2Chip8[0xF+1] =
|
||||
{
|
||||
0xA, 0x0, 0xB, 0xF, 0x7, 0x8, 0x9, 0xE, 0x4, 0x5, 0x6, 0xD, 0x1, 0x2, 0x3, 0xC
|
||||
};
|
||||
|
||||
|
||||
void (*Chip8Table[0xF+1]) ()=
|
||||
{
|
||||
op0table, op1NNN, op2NNN, op3XKK, op4XKK, op5XY0, op6XKK, op7XKK, op8table, op9XY0, opANNN, opBNNN, opCXKK, opDXYN, opEtable, opFtable
|
||||
};
|
||||
|
||||
void (*Chip8Table0[0xF+1]) ()=
|
||||
{
|
||||
op00E0, uninplemented, uninplemented, uninplemented, uninplemented, uninplemented, uninplemented, uninplemented, uninplemented, uninplemented, uninplemented, uninplemented, uninplemented, uninplemented, op00EE, uninplemented
|
||||
};
|
||||
|
||||
void (*Chip8Table8[0xF+1]) ()=
|
||||
{
|
||||
op8XY0, op8XY1, op8XY2, op8XY3, op8XY4, op8XY5, op8XY6, op8XY7, uninplemented, uninplemented, uninplemented, uninplemented, uninplemented, uninplemented, op8XYE, uninplemented
|
||||
};
|
||||
|
||||
void (*Chip8TableE[0xF+1]) ()=
|
||||
{
|
||||
uninplemented, uninplemented, uninplemented, uninplemented, uninplemented, uninplemented, uninplemented, uninplemented, uninplemented, opEX9E, opEXA1, uninplemented, uninplemented, uninplemented, uninplemented, uninplemented
|
||||
};
|
||||
|
||||
|
||||
void (*Chip8TableF[0xF+1]) ()=
|
||||
{
|
||||
uninplemented, uninplemented, uninplemented, opFX33, uninplemented, opF5table, uninplemented, opFX07, opFX18, opFX29, opFX0A, uninplemented, uninplemented, uninplemented, opFX1E, uninplemented
|
||||
};
|
||||
|
||||
void (*Chip8TableF5[0xF+1]) ()=
|
||||
{
|
||||
uninplemented, opFX15, uninplemented, uninplemented, uninplemented, opFX55, opFX65, uninplemented, uninplemented, uninplemented, uninplemented, uninplemented, uninplemented, uninplemented, uninplemented, uninplemented
|
||||
};
|
||||
|
||||
void execute()
|
||||
{
|
||||
char op[5]= "0000";
|
||||
char address[4]= "000";
|
||||
char addressI[]= "0000";
|
||||
char const hexa[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
|
||||
opcode = (((uint16_t) chip8.memory[chip8.PC]) << 8) + (chip8.memory[chip8.PC+1]);
|
||||
for(int i=0; i<4;i++)
|
||||
{
|
||||
op[i] =hexa[((opcode & (0xF000 >> (4*i) ))>>(4*(3-i)))] ;
|
||||
addressI[i] =hexa[((chip8.I & (0xF000 >> (4*i) ))>>(4*(3-i)))] ;
|
||||
}
|
||||
|
||||
for(int i=0; i<3;i++)
|
||||
{
|
||||
address[i] =hexa[((chip8.PC & (0xF00 >> (4*i) ))>>(4*(2-i)))] ;
|
||||
}
|
||||
//dclear(C_WHITE);
|
||||
dprint(1, 9, C_WHITE, C_BLACK, "%s", op);
|
||||
dprint(1, 17, C_WHITE, C_BLACK, "%s", address);
|
||||
dprint(1, 25, C_WHITE, C_BLACK, "%s", addressI);
|
||||
dupdate();
|
||||
Chip8Table[(opcode&0xF000)>>12]();
|
||||
//while(getkey().key != KEY_EXE) {}
|
||||
chip8.PC +=2;
|
||||
|
||||
}
|
||||
|
||||
void op0table()
|
||||
{
|
||||
Chip8Table0[opcode&0x000F]();
|
||||
}
|
||||
|
||||
void op00E0() //clear screen
|
||||
{
|
||||
for (int i=0; i<32; i++) chip8.vram[i]=0; //clear vram
|
||||
dclear(C_BLACK); //clear gint vram
|
||||
dupdate();
|
||||
}
|
||||
|
||||
void op00EE() //return
|
||||
{
|
||||
chip8.PC=chip8.stack[chip8.SP--]; //move and decrement stak pointeur
|
||||
if(chip8.SP == UINT8_MAX) //check overflow in case too much return
|
||||
{
|
||||
//TODO message 4 2 much return
|
||||
}
|
||||
}
|
||||
|
||||
void op1NNN() //jump to NNN
|
||||
{
|
||||
chip8.PC= NNN - 2; //PC get incremented afterward
|
||||
}
|
||||
|
||||
void op2NNN() //call function at NNN
|
||||
{
|
||||
if(chip8.SP == STACK_SIZE - 1) //where gonna buffer overflow
|
||||
{
|
||||
//TODO message 4 2 much call
|
||||
}
|
||||
chip8.stack[++chip8.SP] = chip8.PC; //increment stack pointeur and store address on top
|
||||
chip8.PC = NNN - 2; //PC get incremented afterward
|
||||
}
|
||||
|
||||
void op3XKK() //skip if reg[X] equal KK
|
||||
{
|
||||
if(chip8.regist[X] == KK) chip8.PC += 2;
|
||||
}
|
||||
|
||||
void op4XKK() //skip if reg[X] not equal KK
|
||||
{
|
||||
if(chip8.regist[X] != KK) chip8.PC += 2;
|
||||
}
|
||||
|
||||
void op5XY0() //skip if reg[X] equal reg[Y]
|
||||
{
|
||||
if(chip8.regist[X] == chip8.regist[Y]) chip8.PC += 2;
|
||||
}
|
||||
|
||||
void op6XKK() //Load KK in reg[X]
|
||||
{
|
||||
chip8.regist[X] = KK;
|
||||
}
|
||||
|
||||
void op7XKK() //reg[X] += KK, no carry
|
||||
{
|
||||
chip8.regist[X] = chip8.regist[X] + KK;
|
||||
}
|
||||
|
||||
void op8table()
|
||||
{
|
||||
Chip8Table8[opcode&0x000F]();
|
||||
}
|
||||
|
||||
void op8XY0() //load reg[Y] in reg [X]
|
||||
{
|
||||
chip8.regist[X] = chip8.regist[Y];
|
||||
}
|
||||
|
||||
void op8XY1() //OR reg[X] and reg[Y] in reg [X]
|
||||
{
|
||||
chip8.regist[X] |= chip8.regist[Y];
|
||||
}
|
||||
|
||||
void op8XY2() //AND reg[X] and reg[Y] in reg [X]
|
||||
{
|
||||
chip8.regist[X] &= chip8.regist[Y];
|
||||
}
|
||||
|
||||
void op8XY3() //XOR reg[X] and reg[Y] in reg [X]
|
||||
{
|
||||
chip8.regist[X] ^= chip8.regist[Y];
|
||||
}
|
||||
|
||||
void op8XY4() //add reg[X] and reg[Y] in reg[X] whit carry
|
||||
{
|
||||
chip8.regist[0xF] = (UINT8_MAX - chip8.regist[X] < chip8.regist[Y]);//carry
|
||||
chip8.regist[X] += chip8.regist[Y];
|
||||
}
|
||||
|
||||
void op8XY5() //reg[X] = reg[X] -reg[Y] with NOT borrow
|
||||
{
|
||||
chip8.regist[0xF] = (chip8.regist[X] > chip8.regist[Y]);
|
||||
chip8.regist[X] -= chip8.regist[Y];
|
||||
}
|
||||
|
||||
void op8XY6() //rotate reg[X] -> and save the least significant bit in the carry flag
|
||||
{
|
||||
chip8.regist[0xF] = chip8.regist[X] & 0x1;
|
||||
chip8.regist[X] >>= 1;
|
||||
}
|
||||
|
||||
void op8XY7() //reg[X] = reg[Y] - reg[X] with NOT borrow
|
||||
{
|
||||
chip8.regist[0xF] = (chip8.regist[X] < chip8.regist[Y]);
|
||||
chip8.regist[X] = chip8.regist[Y] - chip8.regist[X];
|
||||
}
|
||||
|
||||
void op8XYE() //rotate reg[X] <- and save the least significant bit in the carry flag
|
||||
{
|
||||
chip8.regist[0xF] = (chip8.regist[X] & 0x80) >> 7;;
|
||||
chip8.regist[X] <<= 1;
|
||||
}
|
||||
|
||||
void op9XY0() //skip if reg[X] equal reg[Y]
|
||||
{
|
||||
if(chip8.regist[X] != chip8.regist[Y]) chip8.PC += 2;
|
||||
}
|
||||
|
||||
void opANNN() //load NNN into I
|
||||
{
|
||||
chip8.I = NNN;
|
||||
}
|
||||
|
||||
void opBNNN() //jump to address regist[0]+NNN
|
||||
{
|
||||
chip8.PC= chip8.regist[0] + NNN - 2; //PC get incremented afterward
|
||||
}
|
||||
|
||||
void opCXKK() //set regist[X] = random(0,255) AND KK
|
||||
{
|
||||
chip8.regist[X] = 0xFF & KK; //random 0xFF determined by a fair D6 throw... JK, TODO
|
||||
}
|
||||
|
||||
//xor the sprite of size 8*N at adress I on the screen at position (regist[X],regist[Y])
|
||||
//if a pixel is erased, set set carry flag.
|
||||
//sprite are supposed to warp round the screen, so it will get messy
|
||||
void opDXYN()
|
||||
{
|
||||
uint64_t old_ram; //to save old state in order to know if pixel got erased
|
||||
uint64_t new_ram;
|
||||
uint64_t sprite_row; //temporary storage for the
|
||||
uint8_t Xpos = chip8.regist[X]% 64;
|
||||
uint8_t Ypos = chip8.regist[Y]% 32;
|
||||
|
||||
chip8.regist[0xF] = 0; //reseting flag
|
||||
|
||||
for (int i = 0; i<N; i++)
|
||||
{
|
||||
sprite_row = ((uint64_t) chip8.memory[chip8.I + i])<<56; //load row and put sprite in rigt 'cause it's easier for me afterward
|
||||
sprite_row = (sprite_row >> Xpos)|(sprite_row<<(64-Xpos));//move the sprite in the correct collums with wraping
|
||||
old_ram = chip8.vram[(Ypos+i)%32];
|
||||
new_ram = old_ram ^ sprite_row;
|
||||
chip8.regist[0xF] |= (((new_ram^old_ram)&old_ram) != 0);
|
||||
chip8.vram[(Ypos+i)%32] = new_ram;
|
||||
}
|
||||
|
||||
// drawing routine, not optimized at all TODO
|
||||
|
||||
dclear(C_BLACK);
|
||||
|
||||
for(int x = 0; x < 64; x++)
|
||||
{
|
||||
for(int y = 0; y < 32; y++)
|
||||
{
|
||||
if((chip8.vram[y]>>(63-x))&0x1) drect(2*x, 2*y, 2*x+1, 2*y+1, C_WHITE);
|
||||
}
|
||||
}
|
||||
dprint(1,33, C_WHITE, C_BLACK, "%d %d", Xpos, Ypos);
|
||||
dupdate();
|
||||
}
|
||||
|
||||
void opEtable()
|
||||
{
|
||||
Chip8TableE[(opcode&0x00F0)>>4]();
|
||||
}
|
||||
|
||||
void opEX9E() //skip if regist[X] equal value of key pressed
|
||||
{
|
||||
if(getkey().key == Chip8Kb2Casio[chip8.regist[X] & 0xF]) chip8.PC += 2;
|
||||
}
|
||||
|
||||
void opEXA1() //skip if regist[X] not equal value of key pressed
|
||||
{
|
||||
if(getkey().key != Chip8Kb2Casio[chip8.regist[X] & 0xF]) chip8.PC += 2;
|
||||
}
|
||||
|
||||
void opFtable()
|
||||
{
|
||||
Chip8TableF[opcode&0x000F]();
|
||||
}
|
||||
|
||||
void opF5table()
|
||||
{
|
||||
Chip8TableF5[(opcode&0x00F0)>>4]();
|
||||
}
|
||||
|
||||
void opFX07() //set regist[X] = DelayTimer
|
||||
{
|
||||
chip8.regist[X] = chip8.DT;
|
||||
}
|
||||
|
||||
void opFX0A() //set regist[X] = keycode of pressed key (wait for press if not any)
|
||||
{
|
||||
uint kcode = getkey().key;
|
||||
if(kcode % 0xF < 5 && kcode / 0x10 < 5) chip8.regist[X] = CasioKb2Chip8[kcode - (0xC * (kcode/0x10)) - 0x5]; //see .h for explanation
|
||||
}
|
||||
|
||||
void opFX15() //set DelayTimer = regist[X]
|
||||
{
|
||||
chip8.DT = chip8.regist[X];
|
||||
}
|
||||
|
||||
void opFX18() //set SoundTimer = regist[X]
|
||||
{
|
||||
chip8.ST = chip8.regist[X];
|
||||
}
|
||||
|
||||
void opFX1E() //set I = I + regist[X]
|
||||
{
|
||||
chip8.I += chip8.regist[X];
|
||||
}
|
||||
|
||||
void opFX29() //set I to the location to draw the char stored in regist[X]
|
||||
{
|
||||
chip8.I = 5 * (chip8.regist[X] & 0xF);//char bitmaps are 5 bytes
|
||||
//&0xF 'cause not precised what to do if regist[x] is larger than 15
|
||||
}
|
||||
|
||||
void opFX33() //store BCD representation of regist[X] in the adress I(hundreds), I+1(tens), I+2(digits)
|
||||
{
|
||||
chip8.memory[chip8.I + 2] = chip8.regist[X] %10;
|
||||
chip8.memory[chip8.I + 1] = (chip8.regist[X] /10) % 10;
|
||||
chip8.memory[chip8.I] = chip8.regist[X] / 100;
|
||||
}
|
||||
|
||||
void opFX55() //store regist[0]~regist[X] into memory adress I~I+X
|
||||
{
|
||||
for(int i=0; i<=X;i++) chip8.memory[chip8.I+i] = chip8.regist[i];
|
||||
}
|
||||
|
||||
void opFX65() //load regist[0]~regist[X] from memory adress I~I+X
|
||||
{
|
||||
for(int i=0; i<=X;i++) chip8.regist[i] = chip8.memory[chip8.I+i];
|
||||
}
|
||||
|
||||
void uninplemented()
|
||||
{
|
||||
char op[5]= "0000";
|
||||
char address[4] = "000";
|
||||
char const hexa[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
|
||||
for(int i=0; i<4;i++)
|
||||
{
|
||||
op[i] =hexa[((opcode & (0xF000 >> (4*i) ))>>(4*(3-i)))] ;
|
||||
}
|
||||
for(int i=0; i<3;i++)
|
||||
{
|
||||
address[i] =hexa[((chip8.PC & (0xF00 >> (4*i) ))>>(4*(2-i)))] ;
|
||||
}
|
||||
|
||||
dclear(C_WHITE);
|
||||
dprint(1, 1, C_WHITE, C_BLACK, "%s unimplemented", op);
|
||||
dprint(1, 9, C_WHITE, C_BLACK, "Position: %s", address);
|
||||
dupdate();
|
||||
while(getkey().key != KEY_EXIT) {}
|
||||
}
|
Loading…
Reference in New Issue