Initial commit
This commit is contained in:
commit
e77442b840
10 changed files with 1192 additions and 0 deletions
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
*.tab
|
||||
*.o
|
||||
*.s??
|
||||
*~
|
||||
*.dblite
|
||||
build/
|
16
.vscode/c_cpp_properties.json
vendored
Normal file
16
.vscode/c_cpp_properties.json
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Main",
|
||||
"includePath": [
|
||||
"${HOME}/.vscode/extensions/entan-gl.cc65-vice-4.8.1/dist/cc65/include",
|
||||
"${workspaceFolder}/src"
|
||||
],
|
||||
"intelliSenseMode": "gcc-x64",
|
||||
"compilerPath": "${HOME}/.vscode/extensions/entan-gl.cc65-vice-4.8.1/dist/cc65/bin/cc65",
|
||||
"cStandard": "c99",
|
||||
"cppStandard": "c++98"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
41
.vscode/launch.json
vendored
Normal file
41
.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
// Verwendet IntelliSense zum Ermitteln möglicher Attribute.
|
||||
// Zeigen Sie auf vorhandene Attribute, um die zugehörigen Beschreibungen anzuzeigen.
|
||||
// Weitere Informationen finden Sie unter https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"type": "cc65-vice",
|
||||
"request": "launch",
|
||||
"name": "CC65 Vice Launch",
|
||||
"program": "${workspaceFolder}/build/msprite.d64",
|
||||
"build": {
|
||||
"cwd": "${workspaceFolder}",
|
||||
"command": "scons",
|
||||
"args": []
|
||||
},
|
||||
"debugFile": "${workspaceFolder}/build/msprite.dbg",
|
||||
"mapFile": "${workspaceFolder}/build/msprite.map",
|
||||
"labelFile": "${workspaceFolder}/build/msprite.lbl",
|
||||
"stopOnEntry": true,
|
||||
"stopOnExit": true,
|
||||
"viceArgs": [
|
||||
"-model",
|
||||
"ntsc"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
44
.vscode/settings.json
vendored
Normal file
44
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"files.associations": {
|
||||
"string.h": "c",
|
||||
"memory.h": "c",
|
||||
"cstdlib": "c",
|
||||
"*.tcc": "c",
|
||||
"memory": "c",
|
||||
"new": "c",
|
||||
"array": "c",
|
||||
"string": "c",
|
||||
"vector": "c",
|
||||
"string_view": "c",
|
||||
"functional": "c",
|
||||
"istream": "c",
|
||||
"limits": "c",
|
||||
"ostream": "c",
|
||||
"ratio": "c",
|
||||
"sstream": "c",
|
||||
"streambuf": "c",
|
||||
"stdio.h": "c",
|
||||
"atomic": "c",
|
||||
"hash_map": "c",
|
||||
"deque": "c",
|
||||
"list": "c",
|
||||
"iterator": "c",
|
||||
"memory_resource": "c",
|
||||
"type_traits": "c",
|
||||
"typeinfo": "c",
|
||||
"algorithm": "c",
|
||||
"numeric": "c",
|
||||
"random": "c",
|
||||
"fstream": "c",
|
||||
"iosfwd": "c",
|
||||
"map": "c",
|
||||
"queue": "c",
|
||||
"utility": "c",
|
||||
"stdbool.h": "c",
|
||||
"errno.h": "c",
|
||||
"_vic2.h": "c",
|
||||
"c64.h": "c",
|
||||
"cstring": "c",
|
||||
"6502.h": "c"
|
||||
}
|
||||
}
|
16
.vscode/tasks.json
vendored
Normal file
16
.vscode/tasks.json
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Build",
|
||||
"type": "shell",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"command": "sh scons.sh"
|
||||
}
|
||||
]
|
||||
}
|
60
SConstruct
Normal file
60
SConstruct
Normal file
|
@ -0,0 +1,60 @@
|
|||
# vim: syntax=python
|
||||
import os
|
||||
|
||||
screen_start = 'C000'
|
||||
sprite_start = 'C400'
|
||||
character_start = 'D800'
|
||||
|
||||
if 'CC65_HOME' in os.environ:
|
||||
cc65_home = os.environ['CC65_HOME']
|
||||
else:
|
||||
cc65_home = ''
|
||||
|
||||
if 'DISPLAY' in os.environ:
|
||||
display = os.environ['DISPLAY']
|
||||
else:
|
||||
display = ''
|
||||
|
||||
print(cc65_home)
|
||||
print(os.environ['PATH'])
|
||||
|
||||
env = Environment(
|
||||
BUILDERS = {},
|
||||
ENV = {
|
||||
'PATH': os.environ["PATH"],
|
||||
'CC65_HOME': cc65_home,
|
||||
'DISPLAY': display,
|
||||
},
|
||||
AS = 'ca65',
|
||||
ASFLAGS = ['-t', 'c64', '-g'],
|
||||
CC = 'cl65',
|
||||
CFLAGS = ['-DSCREEN_START=0x'+screen_start, '-DSPRITE_START=0x'+sprite_start, '-DCHARACTER_START=0x'+character_start, '-O', '-Osir', '-t', 'c64', '-C', 'c64.cfg', '-g', '-Wc', '--debug-tables', '-Wc', '${SOURCE}.tab'],
|
||||
LINK = 'cl65',
|
||||
LINKFLAGS = ['-g', '-C', 'c64.cfg', '-D__HIMEM__=$' + screen_start, '-Wl', '--dbgfile,build/msprite.dbg', '-Wl', '-Lnbuild/msprite.lbl', '-Wl', '--mapfile,build/msprite.map']
|
||||
)
|
||||
|
||||
prg = env.Program(target=["build/msprite.prg", "build/msprite.map", "build/msprite.dbg", "build/msprite.lbl"], source=[Glob('src/*.c'), Glob('src/*_asm.s')])
|
||||
|
||||
sprites = Glob('res/sprites/*.spd')
|
||||
|
||||
disk_files = []
|
||||
disk_files.append(prg[0])
|
||||
disk_files.append(sprites)
|
||||
|
||||
def disk_func(target, source, env):
|
||||
if not target[0].exists():
|
||||
env.Execute('c1541 -format "canada,01" d64 "%s"' % target[0])
|
||||
changes = []
|
||||
for src in source:
|
||||
basename = os.path.basename(str(src))
|
||||
typename = 's'
|
||||
if basename.endswith('prg'):
|
||||
typename = 'p'
|
||||
changes.append(""" -delete '%s' -write '%s' '%s,%s'""" % (basename, str(src), basename, typename))
|
||||
env.Execute("""c1541 -attach '%s' %s """ % (str(target[0]), ''.join(changes)))
|
||||
|
||||
disk_image = env.Command(target=["build/msprite.d64"], source=disk_files, action=disk_func)
|
||||
|
||||
env.Alias('build', disk_image)
|
||||
|
||||
Default(disk_image)
|
9
scons.sh
Normal file
9
scons.sh
Normal file
|
@ -0,0 +1,9 @@
|
|||
DIR="$( cd "$( dirname "$(readlink -f "$0")" )" > /dev/null && pwd )"
|
||||
SHPATH="$(ls -t "$HOME/.vscode/extensions/entan-gl.cc65-vice-"*"/build.sh" | head -1)"
|
||||
if test -e "$DIR/../../../build.sh"; then
|
||||
sh "$DIR/../../../build.sh" scons "$@"
|
||||
elif test -e "$SHPATH"; then
|
||||
sh "$SHPATH" scons "$@"
|
||||
else
|
||||
scons "$@"
|
||||
fi
|
284
src/c64.h
Normal file
284
src/c64.h
Normal file
|
@ -0,0 +1,284 @@
|
|||
// From cc65/cc65/asminc/c64.inc
|
||||
//
|
||||
// C64 generic definitions. Stolen from Elite128
|
||||
//
|
||||
// I prefer using this over some of the builtin structs because it is easier to
|
||||
// match to assembly code docs.
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Zero page, Commodore stuff
|
||||
|
||||
#define CPU_PORT 0x01
|
||||
|
||||
#define CPU_PORT_BANK_MASK 0x07
|
||||
|
||||
#define CPU_PORT_BANK_ALL_RAM_VISIBLE_IO_INVISIBLE 0x00
|
||||
#define CPU_PORT_BANK_LORAM_HIRAM_VISIBLE 0x01
|
||||
#define CPU_PORT_BANK_LORAM_VISIBLE_KERNAL_VISIBLE 0x02
|
||||
#define CPU_PORT_BANK_BASIC_ROM_VISIBLE_KERNAL_VISIBLE 0x03
|
||||
|
||||
#define CPU_PORT_BANK_IO_VISIBLE_CHARACTER_ROM_INVISIBLE 0x04
|
||||
|
||||
#define VARTAB 0x2D
|
||||
#define MEMSIZE 0x37 // Pointer to highest BASIC RAM location (+1)
|
||||
#define TXTPTR 0x7A // Pointer into BASIC source code
|
||||
#define TIME 0xA0 // 60 HZ clock
|
||||
#define FNAM_LEN 0xB7 // Length of filename
|
||||
#define SECADR 0xB9 // Secondary address
|
||||
#define DEVNUM 0xBA // Device number
|
||||
#define FNAM 0xBB // Pointer to filename
|
||||
#define KEY_COUNT 0xC6 // Number of keys in input buffer
|
||||
#define RVS 0xC7 // Reverse flag
|
||||
#define CURS_FLAG 0xCC // 1 cursor off
|
||||
#define CURS_BLINK 0xCD // Blink counter
|
||||
#define CURS_CHAR 0xCE // Character under the cursor
|
||||
#define CURS_STATE 0xCF // Cursor blink state
|
||||
#define SCREEN_PTR 0xD1 // Pointer to current char in text screen
|
||||
#define CURS_X 0xD3 // Cursor column
|
||||
#define CURS_Y 0xD6 // Cursor row
|
||||
#define CRAM_PTR 0xF3 // Pointer to current char in color RAM
|
||||
#define FREKZP 0xFB // Five unused bytes
|
||||
|
||||
#define SCREEN_BYTES 1000
|
||||
|
||||
#define SCREEN_BITMAP_WIDTH 320
|
||||
#define SCREEN_BITMAP_HEIGHT 200
|
||||
#define SCREEN_BITMAP_SIZE 8000
|
||||
|
||||
#define SCREEN_SPRITE_WIDTH 512
|
||||
#define SCREEN_SPRITE_HEIGHT 255
|
||||
|
||||
#define SCREEN_SPRITE_BORDER_Y_START 50
|
||||
#define SCREEN_SPRITE_BORDER_Y_END 250
|
||||
|
||||
#define SCREEN_SPRITE_BORDER_X_START 20
|
||||
#define SCREEN_SPRITE_BORDER_X_END 350
|
||||
|
||||
#define SCREEN_SPRITE_BORDER_WIDTH (SCREEN_SPRITE_BORDER_X_END - SCREEN_SPRITE_BORDER_X_START)
|
||||
|
||||
#define BASIC_BUF 0x200 // Location of command-line
|
||||
#define BASIC_BUF_LEN 89 // Maximum length of command-line
|
||||
|
||||
#define CHARCOLOR 0x286
|
||||
#define CURS_COLOR 0x287 // Color under the cursor
|
||||
#define SCREEN_IO_HI_PTR 0x288
|
||||
#define PALFLAG 0x2A6 // 0x01 PAL, 0x00 NTSC
|
||||
|
||||
#define KBDREPEAT 0x28a
|
||||
#define KBDREPEATRATE 0x28b
|
||||
#define KBDREPEATDELAY 0x28c
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Vector and other locations
|
||||
|
||||
#define IRQVec 0x0314
|
||||
#define BRKVec 0x0316
|
||||
#define NMIVec 0x0318
|
||||
|
||||
#define IRQVec_DEFAULT_ISR 0xEA31
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Screen size
|
||||
|
||||
#define XSIZE 40
|
||||
#define YSIZE 25
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// I/O: VIC
|
||||
|
||||
#define CHARACTER_ROM 0xD000
|
||||
#define CHARACTER_ROM_SIZE 0x1000
|
||||
|
||||
#define VIC_SPR0_X 0xD000
|
||||
#define VIC_SPR0_Y 0xD001
|
||||
#define VIC_SPR1_X 0xD002
|
||||
#define VIC_SPR1_Y 0xD003
|
||||
#define VIC_SPR2_X 0xD004
|
||||
#define VIC_SPR2_Y 0xD005
|
||||
#define VIC_SPR3_X 0xD006
|
||||
#define VIC_SPR3_Y 0xD007
|
||||
#define VIC_SPR4_X 0xD008
|
||||
#define VIC_SPR4_Y 0xD009
|
||||
#define VIC_SPR5_X 0xD00A
|
||||
#define VIC_SPR5_Y 0xD00B
|
||||
#define VIC_SPR6_X 0xD00C
|
||||
#define VIC_SPR6_Y 0xD00D
|
||||
#define VIC_SPR7_X 0xD00E
|
||||
#define VIC_SPR7_Y 0xD00F
|
||||
#define VIC_SPR_HI_X 0xD010
|
||||
#define VIC_SPR_ENA 0xD015
|
||||
#define VIC_SPR_EXP_Y 0xD017
|
||||
#define VIC_SPR_EXP_X 0xD01D
|
||||
#define VIC_SPR_MCOLOR 0xD01C
|
||||
#define VIC_SPR_BG_PRIO 0xD01B
|
||||
|
||||
#define VIC_SPR_MCOLOR0 0xD025
|
||||
#define VIC_SPR_MCOLOR1 0xD026
|
||||
|
||||
#define VIC_SPR0_COLOR 0xD027
|
||||
#define VIC_SPR1_COLOR 0xD028
|
||||
#define VIC_SPR2_COLOR 0xD029
|
||||
#define VIC_SPR3_COLOR 0xD02A
|
||||
#define VIC_SPR4_COLOR 0xD02B
|
||||
#define VIC_SPR5_COLOR 0xD02C
|
||||
#define VIC_SPR6_COLOR 0xD02D
|
||||
#define VIC_SPR7_COLOR 0xD02E
|
||||
|
||||
#define VIC_CTRL1 0xD011
|
||||
#define VIC_CTRL2 0xD016
|
||||
|
||||
#define VIC_SPR_SIZE 0x40
|
||||
#define VIC_SPR_COUNT 0x08
|
||||
|
||||
#define VIC_SPR_WIDTH 24
|
||||
#define VIC_SPR_HEIGHT 21
|
||||
|
||||
#define JOY_ANY_MASK (JOY_UP_MASK | JOY_DOWN_MASK | JOY_LEFT_MASK | JOY_RIGHT_MASK | JOY_BTN_1_MASK)
|
||||
|
||||
#define VIC_CTRL1_BITMAP_ON 0x20
|
||||
#define VIC_CTRL1_HLINE_MSB 0x80
|
||||
#define VIC_CTRL2_MULTICOLOR_ON 0x10
|
||||
|
||||
#define VIC_HLINE 0xD012
|
||||
|
||||
#define VIC_LPEN_X 0xD013
|
||||
#define VIC_LPEN_Y 0xD014
|
||||
|
||||
#define VIC_VIDEO_ADR 0xD018
|
||||
|
||||
// Character memory pointer bits MSB-LSB
|
||||
#define VIC_VIDEO_ADR_CHAR_PTR_MASK 0x0E
|
||||
#define VIC_VIDEO_ADR_CHAR_PTR0 0x08
|
||||
#define VIC_VIDEO_ADR_CHAR_PTR1 0x04
|
||||
#define VIC_VIDEO_ADR_CHAR_PTR2 0x02
|
||||
|
||||
#define VIC_VIDEO_ADR_CHAR_DIVISOR 0x800
|
||||
#define VIC_VIDEO_ADR_SCREEN_DIVISOR 0x400
|
||||
|
||||
#define VIC_VIDEO_ADR_CHAR_BANK_GRAPHICS_OFFSET 0x1000
|
||||
#define VIC_VIDEO_ADR_CHAR_BANK_SMALLCASE_OFFSET 0x1800
|
||||
|
||||
// Screen memory pointer bits MSB-LSB
|
||||
#define VIC_VIDEO_ADR_SCREEN_PTR_MASK 0xF0
|
||||
#define VIC_VIDEO_ADR_SCREEN_PTR0 0x80
|
||||
#define VIC_VIDEO_ADR_SCREEN_PTR1 0x40
|
||||
#define VIC_VIDEO_ADR_SCREEN_PTR2 0x20
|
||||
#define VIC_VIDEO_ADR_SCREEN_PTR3 0x10
|
||||
|
||||
#define VIC_BANK_SIZE 0x4000
|
||||
|
||||
#define VIC_IRR 0xD019 // Interrupt request register
|
||||
#define VIC_IMR 0xD01A // Interrupt mask register
|
||||
|
||||
#define VIC_IRQ_RASTER 0x01
|
||||
#define VIC_IRQ_SPRITE_BG 0x02
|
||||
#define VIC_IRQ_SPRITE_SPRITE 0x04
|
||||
#define VIC_IRQ_LIGHT_PEN 0x08
|
||||
|
||||
#define COLOR_RAM_SIZE 1000
|
||||
|
||||
#define VIC_BORDERCOLOR 0xD020
|
||||
#define VIC_BG_COLOR0 0xD021
|
||||
#define VIC_BG_COLOR1 0xD022
|
||||
#define VIC_BG_COLOR2 0xD023
|
||||
#define VIC_BG_COLOR3 0xD024
|
||||
// 128 stuff:
|
||||
#define VIC_KBD_128 0xD02F // Extended kbd bits (visible in 64 mode)
|
||||
#define VIC_CLK_128 0xD030 // Clock rate register (visible in 64 mode)
|
||||
|
||||
// I/O: SID
|
||||
|
||||
#define SID_S1Lo 0xD400
|
||||
#define SID_S1Hi 0xD401
|
||||
#define SID_PB1Lo 0xD402
|
||||
#define SID_PB1Hi 0xD403
|
||||
#define SID_Ctl1 0xD404
|
||||
#define SID_AD1 0xD405
|
||||
#define SID_SUR1 0xD406
|
||||
|
||||
#define SID_S2Lo 0xD407
|
||||
#define SID_S2Hi 0xD408
|
||||
#define SID_PB2Lo 0xD409
|
||||
#define SID_PB2Hi 0xD40A
|
||||
#define SID_Ctl2 0xD40B
|
||||
#define SID_AD2 0xD40C
|
||||
#define SID_SUR2 0xD40D
|
||||
|
||||
#define SID_S3Lo 0xD40E
|
||||
#define SID_S3Hi 0xD40F
|
||||
#define SID_PB3Lo 0xD410
|
||||
#define SID_PB3Hi 0xD411
|
||||
#define SID_Ctl3 0xD412
|
||||
#define SID_AD3 0xD413
|
||||
#define SID_SUR3 0xD414
|
||||
|
||||
#define SID_FltLo 0xD415
|
||||
#define SID_FltHi 0xD416
|
||||
#define SID_FltCtl 0xD417
|
||||
#define SID_Amp 0xD418
|
||||
#define SID_ADConv1 0xD419
|
||||
#define SID_ADConv2 0xD41A
|
||||
#define SID_Noise 0xD41B
|
||||
#define SID_Read3 0xD41C
|
||||
|
||||
// I/O: VDC (128 only)
|
||||
|
||||
#define VDC_INDEX 0xD600
|
||||
#define VDC_DATA 0xD601
|
||||
|
||||
// I/O: Complex Interface Adapters
|
||||
|
||||
#define CIA1_PRA 0xDC00 // Port A
|
||||
#define CIA1_PRB 0xDC01 // Port B
|
||||
#define CIA1_DDRA 0xDC02 // Data direction register for port A
|
||||
#define CIA1_DDRB 0xDC03 // Data direction register for port B
|
||||
#define CIA1_TA 0xDC04 // 16-bit timer A
|
||||
#define CIA1_TB 0xDC06 // 16-bit timer B
|
||||
#define CIA1_TOD10 0xDC08 // Time-of-day tenths of a second
|
||||
#define CIA1_TODSEC 0xDC09 // Time-of-day seconds
|
||||
#define CIA1_TODMIN 0xDC0A // Time-of-day minutes
|
||||
#define CIA1_TODHR 0xDC0B // Time-of-day hours
|
||||
#define CIA1_SDR 0xDC0C // Serial data register
|
||||
#define CIA1_ICR 0xDC0D // Interrupt control register
|
||||
#define CIA1_CRA 0xDC0E // Control register for timer A
|
||||
#define CIA1_CRB 0xDC0F // Control register for timer B
|
||||
|
||||
#define CIA1_CR_START_STOP 0x01
|
||||
|
||||
#define CIA2_PRA_VIC_BANK0 0x02
|
||||
#define CIA2_PRA_VIC_BANK1 0x01
|
||||
|
||||
#define CIA2_PRA 0xDD00
|
||||
#define CIA2_PRB 0xDD01
|
||||
#define CIA2_DDRA 0xDD02
|
||||
#define CIA2_DDRB 0xDD03
|
||||
#define CIA2_TA 0xDD04
|
||||
#define CIA2_TB 0xDD06
|
||||
#define CIA2_TOD10 0xDD08
|
||||
#define CIA2_TODSEC 0xDD09
|
||||
#define CIA2_TODMIN 0xDD0A
|
||||
#define CIA2_TODHR 0xDD0B
|
||||
#define CIA2_SDR 0xDD0C
|
||||
#define CIA2_ICR 0xDD0D
|
||||
#define CIA2_CRA 0xDD0E
|
||||
#define CIA2_CRB 0xDD0F
|
||||
|
||||
// Super CPU
|
||||
#define SCPU_VIC_Bank1 0xD075
|
||||
#define SCPU_Slow 0xD07A
|
||||
#define SCPU_Fast 0xD07B
|
||||
#define SCPU_EnableRegs 0xD07E
|
||||
#define SCPU_DisableRegs 0xD07F
|
||||
#define SCPU_Detect 0xD0BC
|
||||
|
||||
// Processor Port at 0x01
|
||||
|
||||
#define LORAM 0x01 // Enable the basic rom
|
||||
#define HIRAM 0x02 // Enable the kernal rom
|
||||
#define IOEN 0x04 // Enable I/O
|
||||
#define CASSDATA 0x08 // Cassette data
|
||||
#define CASSPLAY 0x10 // Cassette: Play
|
||||
#define CASSMOT 0x20 // Cassette motor on
|
||||
#define TP_FAST 0x80 // Switch Rossmoeller TurboProcess to fast mode
|
||||
|
||||
#define RAMONLY 0xF8 // (~(LORAM | HIRAM | IOEN)) & 0xFF
|
669
src/main.c
Normal file
669
src/main.c
Normal file
|
@ -0,0 +1,669 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <6502.h>
|
||||
#include <conio.h>
|
||||
#include <c64.h>
|
||||
#include "c64.h"
|
||||
#include <errno.h>
|
||||
|
||||
#define IRQ_STACK_SIZE 128
|
||||
|
||||
extern void updatepalntsc(void);
|
||||
|
||||
/* Check if system is PAL
|
||||
*/
|
||||
void pal_system(void) {
|
||||
updatepalntsc();
|
||||
}
|
||||
|
||||
unsigned char* irq_stack;
|
||||
|
||||
#define SCREEN_LAST_RASTER SCREEN_SPRITE_BORDER_Y_START + SCREEN_BITMAP_HEIGHT
|
||||
#define SPRITE_BUFFER_LINE_COUNT 8
|
||||
#define SPRITE_BUFFER_LINE_HEIGHT (SCREEN_BITMAP_HEIGHT / SPRITE_BUFFER_LINE_COUNT)
|
||||
#define SCREEN_FIRST_RASTER SCREEN_SPRITE_BORDER_Y_START - SPRITE_BUFFER_LINE_HEIGHT
|
||||
|
||||
/** Disable the IO page
|
||||
*/
|
||||
void __fastcall__ hide_io(void) {
|
||||
*(unsigned char *)CIA1_CRA &= ~CIA1_CR_START_STOP;
|
||||
|
||||
*(unsigned char *)CPU_PORT &= ~CPU_PORT_BANK_IO_VISIBLE_CHARACTER_ROM_INVISIBLE;
|
||||
}
|
||||
|
||||
/** Enable the IO page
|
||||
*/
|
||||
void __fastcall__ show_io(void) {
|
||||
*(unsigned char *)CPU_PORT |= CPU_PORT_BANK_IO_VISIBLE_CHARACTER_ROM_INVISIBLE;
|
||||
|
||||
*(unsigned char *)CIA1_CRA |= CIA1_CR_START_STOP;
|
||||
}
|
||||
|
||||
/** Copies character ROM to RAM.
|
||||
* @param use_graphics_charset - Use fancy graphics chars with no lowercase
|
||||
*/
|
||||
void character_init(bool use_graphics_charset) {
|
||||
hide_io();
|
||||
memcpy(CHARACTER_START, CHARACTER_ROM + (!use_graphics_charset * VIC_VIDEO_ADR_CHAR_DIVISOR), CHARACTER_ROM_SIZE);
|
||||
show_io();
|
||||
}
|
||||
|
||||
/** Reset the screen to VIC bank #3
|
||||
* @param clear - Clear the screen before switching to it
|
||||
*/
|
||||
void screen_init (bool clear) {
|
||||
unsigned char screen_ptr = ((SCREEN_START % VIC_BANK_SIZE) / VIC_VIDEO_ADR_SCREEN_DIVISOR) << 4;
|
||||
|
||||
// Update kernal
|
||||
*(unsigned char *)SCREEN_IO_HI_PTR = SCREEN_START >> 8;
|
||||
|
||||
// Switch to bank 3
|
||||
*(unsigned char *)CIA2_PRA &= ~3;
|
||||
|
||||
// Switch to screen memory
|
||||
VIC.addr &= ~(VIC_VIDEO_ADR_SCREEN_PTR_MASK);
|
||||
VIC.addr |= screen_ptr;
|
||||
|
||||
// Switch to character memory
|
||||
VIC.addr &= ~(VIC_VIDEO_ADR_CHAR_PTR_MASK);
|
||||
VIC.addr |= ((CHARACTER_START % VIC_BANK_SIZE) / VIC_VIDEO_ADR_CHAR_DIVISOR) << 1;
|
||||
|
||||
// Fix HLINE IRQ
|
||||
VIC.rasterline = SCREEN_FIRST_RASTER;
|
||||
VIC.ctrl1 &= ~VIC_CTRL1_HLINE_MSB;
|
||||
|
||||
// Switch off bitmap mode
|
||||
VIC.ctrl1 &= ~VIC_CTRL1_BITMAP_ON;
|
||||
VIC.ctrl2 &= ~VIC_CTRL2_MULTICOLOR_ON;
|
||||
|
||||
// Enable raster interrupts
|
||||
VIC.imr |= VIC_IRQ_RASTER;
|
||||
|
||||
if(clear) {
|
||||
clrscr();
|
||||
printf("hallo!");
|
||||
|
||||
VIC.bgcolor0 = COLOR_BLACK;
|
||||
VIC.bgcolor1 = COLOR_BLACK;
|
||||
VIC.bgcolor2 = COLOR_BLACK;
|
||||
VIC.bgcolor3 = COLOR_BLACK;
|
||||
VIC.bordercolor = COLOR_BLACK;
|
||||
bordercolor(COLOR_BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
bool is_pal = false;
|
||||
|
||||
unsigned char setup_irq_handler(unsigned char (*handler)(void)) {
|
||||
if(!irq_stack) {
|
||||
if(!(irq_stack = malloc(IRQ_STACK_SIZE))) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
set_irq(handler, irq_stack, IRQ_STACK_SIZE);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
unsigned char raster_clock = 0;
|
||||
unsigned int game_clock = 0;
|
||||
unsigned int last_updated = 0;
|
||||
|
||||
void fatal(unsigned char* message) {
|
||||
while(true);
|
||||
}
|
||||
|
||||
#define SPD_PADDING 55
|
||||
|
||||
struct spd_sprite {
|
||||
unsigned char sprite_data[63];
|
||||
unsigned char metadata;
|
||||
};
|
||||
typedef struct spd_sprite spd_sprite;
|
||||
|
||||
struct spd {
|
||||
unsigned char padding[SPD_PADDING];
|
||||
unsigned char magic[3];
|
||||
unsigned char version;
|
||||
unsigned char sprite_count;
|
||||
unsigned char animation_count;
|
||||
unsigned char background_color;
|
||||
unsigned char multicolor_0;
|
||||
unsigned char multicolor_1;
|
||||
spd_sprite sprites[];
|
||||
};
|
||||
typedef struct spd spd;
|
||||
|
||||
#define SPRITE_MAX 80
|
||||
|
||||
/* Load a sprite sheet in SpritePad format
|
||||
* @param filename - The filename on disk
|
||||
* @return - Whether the sheet successfully loaded into memory.
|
||||
*/
|
||||
unsigned char spritesheet_load(unsigned char* filename) {
|
||||
static FILE* fp;
|
||||
static spd* spd_data;
|
||||
static unsigned char* header;
|
||||
|
||||
fp = fopen(filename, "rb");
|
||||
if(!fp) {
|
||||
if(errno != 0) {
|
||||
return errno;
|
||||
}
|
||||
else {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
// Used to write this directly to the memory area, but we can't read it if we do.
|
||||
if(!(header = calloc(1, VIC_SPR_SIZE))
|
||||
|| !fread(header + SPD_PADDING, VIC_SPR_SIZE - SPD_PADDING, 1, fp)) {
|
||||
fclose(fp);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
spd_data = (spd*)header;
|
||||
|
||||
if(spd_data->sprite_count + 1 > SPRITE_MAX) {
|
||||
free(header);
|
||||
fclose(fp);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
memcpy(SPRITE_START, header, VIC_SPR_SIZE);
|
||||
|
||||
if(!fread(SPRITE_START + VIC_SPR_SIZE, VIC_SPR_SIZE, spd_data->sprite_count + 1, fp)) {
|
||||
fclose(fp);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// FIXME tf is background? The background is transparent!
|
||||
|
||||
VIC.spr_mcolor0 = spd_data->multicolor_0;
|
||||
VIC.spr_mcolor1 = spd_data->multicolor_1;
|
||||
|
||||
free(header);
|
||||
fclose(fp);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#define SPD_SPRITE_MULTICOLOR_ENABLE_MASK 0x80
|
||||
#define SPD_SPRITE_COLOR_VALUE_MASK 0x0F
|
||||
|
||||
struct sprite_data {
|
||||
unsigned char color;
|
||||
unsigned char pointer;
|
||||
unsigned char lo_x;
|
||||
unsigned char lo_y;
|
||||
|
||||
unsigned char ena;
|
||||
unsigned char hi_x;
|
||||
unsigned char dbl;
|
||||
unsigned char multi;
|
||||
};
|
||||
typedef struct sprite_data* sprite_handle;
|
||||
|
||||
#define SPRITE_POOL_SIZE 32
|
||||
struct sprite_data _sprite_pool[SPRITE_POOL_SIZE];
|
||||
sprite_handle _sprite_list[SPRITE_POOL_SIZE];
|
||||
unsigned char sprite_count;
|
||||
|
||||
void init_sprite_pool(void) {
|
||||
memset(&_sprite_pool, 0x00, sizeof(struct sprite_data) * SPRITE_POOL_SIZE);
|
||||
memset(&_sprite_list, NULL, sizeof(sprite_handle) * SPRITE_POOL_SIZE);
|
||||
}
|
||||
|
||||
void set_sprite_pointer(sprite_handle handle, unsigned char sprite_pointer) {
|
||||
static spd_sprite* sprite;
|
||||
|
||||
sprite = (spd_sprite*)(SCREEN_START + sprite_pointer * VIC_SPR_SIZE);
|
||||
|
||||
handle->pointer = sprite_pointer;
|
||||
handle->color = sprite->metadata & SPD_SPRITE_COLOR_VALUE_MASK;
|
||||
if(sprite->metadata & SPD_SPRITE_MULTICOLOR_ENABLE_MASK) {
|
||||
handle->multi = 1<<((handle - _sprite_pool)%VIC_SPR_COUNT);
|
||||
}
|
||||
else {
|
||||
handle->multi = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void set_sprite_graphic(sprite_handle handle, unsigned char sheet_index) {
|
||||
static spd* s = (spd*)SPRITE_START;
|
||||
set_sprite_pointer(handle, ((unsigned int)(&s->sprites[sheet_index]) % VIC_BANK_SIZE) / VIC_SPR_SIZE);
|
||||
}
|
||||
|
||||
void set_sprite_position(sprite_handle a, unsigned int x, unsigned char y) {
|
||||
static sprite_handle *start_handle, *comp_handle, *current_handle;
|
||||
static sprite_handle arg, comp;
|
||||
static unsigned char index, last_index, hi_mask, comp_y, yarg;
|
||||
static bool direction;
|
||||
|
||||
yarg = y;
|
||||
arg = a;
|
||||
|
||||
comp_y = arg->lo_y;
|
||||
hi_mask = 1<<(index%VIC_SPR_COUNT);
|
||||
if(x>>8) {
|
||||
arg->hi_x = hi_mask;
|
||||
}
|
||||
else {
|
||||
arg->hi_x = 0;
|
||||
}
|
||||
|
||||
arg->lo_x = (unsigned char)x;
|
||||
if(yarg == comp_y) {
|
||||
return;
|
||||
}
|
||||
arg->lo_y = yarg;
|
||||
|
||||
index = 0;
|
||||
for(
|
||||
start_handle = _sprite_list;
|
||||
*start_handle != arg;
|
||||
start_handle++
|
||||
) {
|
||||
index++;
|
||||
}
|
||||
|
||||
if(yarg > comp_y) {
|
||||
last_index = sprite_count - 1;
|
||||
if(last_index == index) {
|
||||
return;
|
||||
}
|
||||
direction = true;
|
||||
}
|
||||
else {
|
||||
if(index == 0) {
|
||||
return;
|
||||
}
|
||||
direction = false;
|
||||
}
|
||||
|
||||
current_handle = start_handle;
|
||||
do {
|
||||
if(direction) {
|
||||
comp_handle = current_handle + 1;
|
||||
}
|
||||
else {
|
||||
comp_handle = current_handle - 1;
|
||||
}
|
||||
comp = *comp_handle;
|
||||
if((
|
||||
direction
|
||||
? (yarg <= comp->lo_y
|
||||
|| index == last_index)
|
||||
: (comp->lo_y <= yarg
|
||||
|| index == 0)
|
||||
)
|
||||
) {
|
||||
if(current_handle == start_handle) {
|
||||
break;
|
||||
}
|
||||
|
||||
comp = arg;
|
||||
}
|
||||
|
||||
hi_mask = 1<<(index%VIC_SPR_COUNT);
|
||||
|
||||
__asm__("lda %v", comp);
|
||||
__asm__("ldx %v+1", comp);
|
||||
__asm__("ldy #%b", offsetof(struct sprite_data, ena));
|
||||
__asm__("sta ptr1");
|
||||
__asm__("stx ptr1+1");
|
||||
|
||||
__asm__("ldx %v", hi_mask);
|
||||
__asm__("loop: lda (ptr1),Y");
|
||||
__asm__("beq done");
|
||||
__asm__("txa");
|
||||
__asm__("sta (ptr1),Y");
|
||||
__asm__("done: iny");
|
||||
__asm__("tya");
|
||||
__asm__("sbc #%b", offsetof(struct sprite_data, multi));
|
||||
__asm__("bne loop");
|
||||
|
||||
if(comp == arg) {
|
||||
*current_handle = comp;
|
||||
break;
|
||||
}
|
||||
|
||||
*current_handle = comp;
|
||||
*comp_handle = arg;
|
||||
|
||||
if(direction) {
|
||||
index++;
|
||||
}
|
||||
else {
|
||||
index--;
|
||||
}
|
||||
|
||||
if(direction) {
|
||||
current_handle++;
|
||||
}
|
||||
else {
|
||||
current_handle--;
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
void discard_sprite(sprite_handle handle) {
|
||||
set_sprite_position(handle, 0xff, 0xff);
|
||||
sprite_count--;
|
||||
_sprite_list[sprite_count] = NULL;
|
||||
}
|
||||
|
||||
sprite_handle new_sprite(bool dbl) {
|
||||
static sprite_handle handle;
|
||||
|
||||
handle = &_sprite_pool[sprite_count];
|
||||
_sprite_list[sprite_count] = handle;
|
||||
handle->dbl = dbl<<(sprite_count%VIC_SPR_COUNT);
|
||||
handle->ena = 1<<(sprite_count%VIC_SPR_COUNT);
|
||||
handle->lo_x = 0xfe;
|
||||
handle->lo_y = 0xfe;
|
||||
sprite_count++;
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
#define SPR_POINTERS SCREEN_START + 0x3F8
|
||||
|
||||
unsigned char main_raster_irq(void) {
|
||||
static unsigned char sprite_index = 0xff;
|
||||
static unsigned char vic_sprite = 0;
|
||||
static unsigned char current_y = 0;
|
||||
static unsigned char new_y = 0;
|
||||
static unsigned char hi_mask = 0;
|
||||
static sprite_handle cs;
|
||||
|
||||
if(!(VIC.irr & VIC_IRQ_RASTER)) {
|
||||
return IRQ_NOT_HANDLED;
|
||||
}
|
||||
|
||||
VIC.irr |= VIC_IRQ_RASTER;
|
||||
if(sprite_index == 0xff) {
|
||||
sprite_index = 0;
|
||||
vic_sprite = 0;
|
||||
|
||||
// NTSC frame skip
|
||||
if(is_pal) {
|
||||
game_clock++;
|
||||
}
|
||||
else if(++raster_clock < 6) {
|
||||
game_clock++;
|
||||
}
|
||||
else {
|
||||
raster_clock = 0;
|
||||
}
|
||||
}
|
||||
|
||||
cs = _sprite_list[sprite_index];
|
||||
new_y = cs->lo_y;
|
||||
|
||||
do {
|
||||
current_y = new_y;
|
||||
|
||||
hi_mask = ~(1<<vic_sprite);
|
||||
|
||||
#define himasker(dest) { \
|
||||
__asm__("lda %w", dest); \
|
||||
__asm__("and %v", hi_mask); \
|
||||
__asm__("ora (ptr1),Y"); \
|
||||
__asm__("sta %w", dest); \
|
||||
}
|
||||
|
||||
__asm__("lda %v", cs);
|
||||
__asm__("ldx %v+1", cs);
|
||||
__asm__("sta ptr1");
|
||||
__asm__("stx ptr1+1");
|
||||
__asm__("ldy #%b", offsetof(struct sprite_data, color));
|
||||
|
||||
__asm__("ldx %v", vic_sprite);
|
||||
|
||||
__asm__("lda (ptr1),Y");
|
||||
__asm__("sta %w,X", VIC_SPR0_COLOR);
|
||||
|
||||
__asm__("iny");
|
||||
__asm__("lda (ptr1),Y");
|
||||
__asm__("sta %w,X", SPR_POINTERS);
|
||||
|
||||
__asm__("txa");
|
||||
__asm__("asl");
|
||||
__asm__("tax");
|
||||
__asm__("iny");
|
||||
__asm__("lda (ptr1),Y");
|
||||
__asm__("sta %w,X", VIC_SPR0_X);
|
||||
|
||||
__asm__("iny");
|
||||
__asm__("lda (ptr1),Y");
|
||||
__asm__("sta %w,X", VIC_SPR0_Y);
|
||||
__asm__("tax");
|
||||
__asm__("inx");
|
||||
__asm__("stx %w", VIC_HLINE);
|
||||
|
||||
__asm__("iny");
|
||||
himasker(VIC_SPR_ENA);
|
||||
|
||||
__asm__("iny");
|
||||
himasker(VIC_SPR_HI_X);
|
||||
|
||||
__asm__("iny");
|
||||
himasker(VIC_SPR_EXP_X);
|
||||
__asm__("sta %w", VIC_SPR_EXP_Y);
|
||||
|
||||
__asm__("iny");
|
||||
himasker(VIC_SPR_MCOLOR);
|
||||
|
||||
vic_sprite++;
|
||||
if(vic_sprite >= VIC_SPR_COUNT) {
|
||||
vic_sprite = 0;
|
||||
}
|
||||
|
||||
// sprite_index++
|
||||
__asm__("ldx %v", sprite_index);
|
||||
__asm__("inx");
|
||||
__asm__("txa");
|
||||
|
||||
// if(sprite_index == sprite_count)
|
||||
__asm__("cmp %v", sprite_count);
|
||||
|
||||
// else
|
||||
__asm__("bne moarcs");
|
||||
|
||||
// then
|
||||
__asm__("lda #$ff");
|
||||
__asm__("sta %v", sprite_index);
|
||||
__asm__("sta %w", VIC_HLINE);
|
||||
return IRQ_HANDLED;
|
||||
|
||||
// store the new sprite index
|
||||
__asm__("moarcs:");
|
||||
__asm__("sta %v", sprite_index);
|
||||
|
||||
__asm__("asl");
|
||||
__asm__("tax");
|
||||
|
||||
// cs = _sprite_list[sprite_index]
|
||||
__asm__("ldy %v,X", _sprite_list);
|
||||
__asm__("sty %v", cs);
|
||||
__asm__("sty ptr1");
|
||||
|
||||
__asm__("inx");
|
||||
__asm__("ldy %v,X", _sprite_list);
|
||||
__asm__("sty %v+1", cs);
|
||||
__asm__("sty ptr1+1");
|
||||
|
||||
// new_y = cs->lo_y
|
||||
__asm__("ldy #%b", offsetof(struct sprite_data, lo_y));
|
||||
__asm__("lda (ptr1),Y");
|
||||
__asm__("sta %v", new_y);
|
||||
|
||||
// if new_y >= current_y + buffer
|
||||
__asm__("lda %v", current_y);
|
||||
__asm__("clc");
|
||||
__asm__("adc #%b", VIC_SPR_HEIGHT - 2);
|
||||
__asm__("cmp %v", new_y);
|
||||
__asm__("bcc exitloop");
|
||||
} while(true);
|
||||
__asm__("exitloop: ");
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
#define WAW_SPRITE_COUNT 9
|
||||
#define WAW_SPRITE_OFFSET 0
|
||||
#define WAW_COLUMNS 3
|
||||
#define WAW_ROWS 3
|
||||
#define WAW_MINMOUTH -(VIC_SPR_HEIGHT / 2)
|
||||
#define WAW_MAXMOUTH VIC_SPR_HEIGHT
|
||||
#define WAW_MAXFLOAT VIC_SPR_HEIGHT * 2 * WAW_ROWS
|
||||
#define WAW_MOUTHINDEX 7
|
||||
#define WAW_MOUTHSPEED 5
|
||||
#define WAW_MOVESPEED 3
|
||||
|
||||
struct waw {
|
||||
unsigned int x;
|
||||
unsigned char y;
|
||||
signed char mouth_offset;
|
||||
bool mouth_direction;
|
||||
bool float_direction;
|
||||
sprite_handle sprites[WAW_SPRITE_COUNT];
|
||||
};
|
||||
typedef struct waw waw;
|
||||
|
||||
void init_waw(waw* w) {
|
||||
static unsigned char i, j, x, y, sprite_x, sprite_y, idx;
|
||||
static waw* waw;
|
||||
static sprite_handle sprite;
|
||||
static sprite_handle* sprites;
|
||||
waw = w;
|
||||
|
||||
x = waw->x + SCREEN_SPRITE_BORDER_X_START;
|
||||
y = waw->y + SCREEN_SPRITE_BORDER_Y_START;
|
||||
waw->y = y;
|
||||
|
||||
idx = 0;
|
||||
sprites = waw->sprites;
|
||||
for(i = 0; i < WAW_COLUMNS; i++) {
|
||||
sprite_y = y + i * VIC_SPR_HEIGHT * 2;
|
||||
for(j = 0; j < WAW_ROWS; j++) {
|
||||
sprite_x = x + j * VIC_SPR_WIDTH * 2;
|
||||
|
||||
sprite = new_sprite(true);
|
||||
set_sprite_graphic(sprite, WAW_SPRITE_OFFSET + idx);
|
||||
if(idx == WAW_MOUTHINDEX) {
|
||||
set_sprite_position(sprite, sprite_x, sprite_y + waw->mouth_offset);
|
||||
}
|
||||
else {
|
||||
set_sprite_position(sprite, sprite_x, sprite_y);
|
||||
}
|
||||
sprites[idx] = sprite;
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void update_waw(waw* w) {
|
||||
static unsigned int sprite_x;
|
||||
static unsigned char y, sprite_y;
|
||||
static unsigned char idx;
|
||||
static signed char change_y, mouth_offset;
|
||||
static sprite_handle* current_sprite;
|
||||
static sprite_handle sprite;
|
||||
static waw* waw;
|
||||
waw = w;
|
||||
mouth_offset = waw->mouth_offset;
|
||||
if(waw->mouth_direction) {
|
||||
mouth_offset+=WAW_MOUTHSPEED;
|
||||
if(mouth_offset > WAW_MAXMOUTH) {
|
||||
mouth_offset = WAW_MAXMOUTH;
|
||||
waw->mouth_direction = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mouth_offset-=WAW_MOUTHSPEED;
|
||||
if(mouth_offset < WAW_MINMOUTH) {
|
||||
mouth_offset = WAW_MINMOUTH;
|
||||
waw->mouth_direction = true;
|
||||
}
|
||||
}
|
||||
|
||||
waw->mouth_offset = mouth_offset;
|
||||
|
||||
y = waw->y;
|
||||
|
||||
if(waw->float_direction) {
|
||||
change_y = WAW_MOVESPEED;
|
||||
if(change_y + y > WAW_MAXFLOAT) {
|
||||
change_y = 0;
|
||||
waw->float_direction = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
change_y = -WAW_MOVESPEED;
|
||||
if(change_y + y < SCREEN_SPRITE_BORDER_Y_START) {
|
||||
change_y = 0;
|
||||
waw->float_direction = true;
|
||||
}
|
||||
}
|
||||
|
||||
waw->y = y + change_y;
|
||||
|
||||
current_sprite = waw->sprites;
|
||||
for(idx = 0; idx < WAW_SPRITE_COUNT; idx++) {
|
||||
sprite = *current_sprite;
|
||||
((unsigned char*)&sprite_x)[0] = sprite->lo_x;
|
||||
((unsigned char*)&sprite_x)[1] = sprite->hi_x;
|
||||
sprite_y = sprite->lo_y + change_y;
|
||||
// Mouth
|
||||
if(idx == WAW_MOUTHINDEX) {
|
||||
set_sprite_position(sprite, sprite_x, current_sprite[-1]->lo_y + mouth_offset);
|
||||
}
|
||||
else {
|
||||
set_sprite_position(sprite, sprite_x, sprite_y);
|
||||
}
|
||||
|
||||
current_sprite++;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char main(void) {
|
||||
static unsigned char err;
|
||||
//static waw waw2 = {VIC_SPR_WIDTH * WAW_COLUMNS * 2,VIC_SPR_HEIGHT * 2,0,true,true};
|
||||
static waw waw = {0,0,0,true,true};
|
||||
|
||||
updatepalntsc();
|
||||
is_pal = get_tv();
|
||||
|
||||
if(err = spritesheet_load("sprites.spd")) {
|
||||
printf("Spritesheet failed to load: %d", errno);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
init_sprite_pool();
|
||||
init_waw(&waw);
|
||||
//init_waw(&waw2);
|
||||
|
||||
character_init(true);
|
||||
setup_irq_handler(&main_raster_irq);
|
||||
screen_init(true);
|
||||
|
||||
do {
|
||||
if(last_updated == game_clock) {
|
||||
continue;
|
||||
}
|
||||
|
||||
update_waw(&waw);
|
||||
//update_waw(&waw2);
|
||||
|
||||
last_updated++;
|
||||
} while(true);
|
||||
|
||||
while(true);
|
||||
|
||||
return 0;
|
||||
}
|
47
src/palntsc_asm.s
Normal file
47
src/palntsc_asm.s
Normal file
|
@ -0,0 +1,47 @@
|
|||
.export _updatepalntsc
|
||||
; Reliable PAL/NTSC-Detector by Ninja/The Dreams/TempesT
|
||||
; for Go64!/CW issue 06/2000 (detailed description there)
|
||||
; This routine can't be fooled like $02a6 and works also with a SCPU
|
||||
|
||||
.include "c64.inc"
|
||||
|
||||
nmivec = $0318 ; NMI-vector
|
||||
|
||||
_updatepalntsc:
|
||||
jsr palntsc ; perform check
|
||||
sta PALFLAG ; update KERNAL-variable
|
||||
rts
|
||||
|
||||
palntsc:
|
||||
sei ; disable interrupts
|
||||
ldx nmivec
|
||||
ldy nmivec+1 ; remember old NMI-vector
|
||||
lda #<(done)
|
||||
sta nmivec
|
||||
lda #>(done) ; let NMI-vector point to
|
||||
sta nmivec+1 ; a RTI
|
||||
wait:
|
||||
lda VIC_HLINE
|
||||
bne wait ; wait for rasterline 0 or 256
|
||||
lda #$37
|
||||
sta VIC_HLINE
|
||||
lda #$9b ; write testline $137 to the
|
||||
sta VIC_CTRL1
|
||||
lda #$01
|
||||
sta VIC_IRR ; clear IMR-Bit 0
|
||||
wait1:
|
||||
lda VIC_CTRL1 ; Is rasterbeam in the area
|
||||
bpl wait1 ; 0-255? if yes, wait
|
||||
wait2:
|
||||
lda VIC_CTRL1 ; Is rasterbeam in the area
|
||||
bmi wait2 ; 256 to end? if yes, wait
|
||||
lda VIC_IRR ; read IMR
|
||||
and #$01 ; mask Bit 0
|
||||
sta VIC_IRR ; clear IMR-Bit 0
|
||||
stx nmivec
|
||||
sty nmivec+1 ; restore old NMI-vector
|
||||
cli ; enable interrupts
|
||||
rts ; return
|
||||
|
||||
done:
|
||||
rti
|
Loading…
Add table
Reference in a new issue