initial commit
This commit is contained in:
commit
34ae22b6a5
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
out/
|
||||||
11
Makefile
Normal file
11
Makefile
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
GDK ?= /opt/SGDK
|
||||||
|
SRC = src
|
||||||
|
OUT = out
|
||||||
|
|
||||||
|
all:
|
||||||
|
$(MAKE) -f $(GDK)/makefile_wine.gen GDK=$(GDK) WINE=wine \
|
||||||
|
SRC=$(SRC) OUT=$(OUT)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(MAKE) -f $(GDK)/makefile_wine.gen clean GDK=$(GDK) WINE=wine \
|
||||||
|
SRC=$(SRC) OUT=$(OUT)
|
||||||
33
src/boot/rom_head.c
Normal file
33
src/boot/rom_head.c
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#include "genesis.h"
|
||||||
|
|
||||||
|
__attribute__((externally_visible))
|
||||||
|
const ROMHeader rom_header = {
|
||||||
|
#if (ENABLE_BANK_SWITCH != 0)
|
||||||
|
"SEGA SSF ",
|
||||||
|
#elif (MODULE_MEGAWIFI != 0)
|
||||||
|
"SEGA MEGAWIFI ",
|
||||||
|
#else
|
||||||
|
"SEGA MEGA DRIVE ",
|
||||||
|
#endif
|
||||||
|
"(C)SGDK 2024 ",
|
||||||
|
"SAMPLE PROGRAM ",
|
||||||
|
"SAMPLE PROGRAM ",
|
||||||
|
"GM 00000000-00",
|
||||||
|
0x000,
|
||||||
|
"JD ",
|
||||||
|
0x00000000,
|
||||||
|
#if (ENABLE_BANK_SWITCH != 0)
|
||||||
|
0x003FFFFF,
|
||||||
|
#else
|
||||||
|
0x000FFFFF,
|
||||||
|
#endif
|
||||||
|
0xE0FF0000,
|
||||||
|
0xE0FFFFFF,
|
||||||
|
"RA",
|
||||||
|
0xF820,
|
||||||
|
0x00200000,
|
||||||
|
0x0020FFFF,
|
||||||
|
" ",
|
||||||
|
"DEMONSTRATION PROGRAM ",
|
||||||
|
"JUE "
|
||||||
|
};
|
||||||
367
src/boot/sega.s
Normal file
367
src/boot/sega.s
Normal file
@ -0,0 +1,367 @@
|
|||||||
|
#include "task_cst.h"
|
||||||
|
|
||||||
|
.section .text.keepboot
|
||||||
|
|
||||||
|
*-------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Sega startup code for the GNU Assembler
|
||||||
|
* Translated from:
|
||||||
|
* Sega startup code for the Sozobon C compiler
|
||||||
|
* Written by Paul W. Lee
|
||||||
|
* Modified by Charles Coty
|
||||||
|
* Modified by Stephane Dallongeville
|
||||||
|
*
|
||||||
|
*-------------------------------------------------------
|
||||||
|
|
||||||
|
.globl rom_header
|
||||||
|
|
||||||
|
.org 0x00000000
|
||||||
|
|
||||||
|
_Start_Of_Rom:
|
||||||
|
_Vecteurs_68K:
|
||||||
|
dc.l __stack /* Stack address */
|
||||||
|
dc.l _Entry_Point /* Program start address */
|
||||||
|
dc.l _Bus_Error
|
||||||
|
dc.l _Address_Error
|
||||||
|
dc.l _Illegal_Instruction
|
||||||
|
dc.l _Zero_Divide
|
||||||
|
dc.l _Chk_Instruction
|
||||||
|
dc.l _Trapv_Instruction
|
||||||
|
dc.l _Privilege_Violation
|
||||||
|
dc.l _Trace
|
||||||
|
dc.l _Line_1010_Emulation
|
||||||
|
dc.l _Line_1111_Emulation
|
||||||
|
dc.l _Error_Exception, _Error_Exception, _Error_Exception, _Error_Exception
|
||||||
|
dc.l _Error_Exception, _Error_Exception, _Error_Exception, _Error_Exception
|
||||||
|
dc.l _Error_Exception, _Error_Exception, _Error_Exception, _Error_Exception
|
||||||
|
dc.l _Error_Exception
|
||||||
|
dc.l _INT
|
||||||
|
dc.l _EXTINT
|
||||||
|
dc.l _INT
|
||||||
|
dc.l hintCaller
|
||||||
|
dc.l _INT
|
||||||
|
dc.l _VINT
|
||||||
|
dc.l _INT
|
||||||
|
dc.l _trap_0 /* Resume supervisor task */
|
||||||
|
dc.l _INT,_INT,_INT,_INT,_INT,_INT,_INT
|
||||||
|
dc.l _INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT
|
||||||
|
dc.l _INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT
|
||||||
|
dc.l _INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT
|
||||||
|
|
||||||
|
rom_header:
|
||||||
|
.incbin "out/rom_head.bin", 0, 0x100
|
||||||
|
|
||||||
|
_Entry_Point:
|
||||||
|
* disable interrupts
|
||||||
|
move #0x2700,%sr
|
||||||
|
|
||||||
|
* Configure a USER_STACK_LENGTH bytes user stack at bottom, and system stack on top of it
|
||||||
|
move %sp, %usp
|
||||||
|
sub #USER_STACK_LENGTH, %sp
|
||||||
|
|
||||||
|
* Halt Z80 (need to be done as soon as possible on reset)
|
||||||
|
move.l #0xA11100,%a0 /* Z80_HALT_PORT */
|
||||||
|
move.w #0x0100,%d0
|
||||||
|
move.w %d0,(%a0) /* HALT Z80 */
|
||||||
|
move.w %d0,0x0100(%a0) /* END RESET Z80 */
|
||||||
|
|
||||||
|
tst.l 0xa10008
|
||||||
|
bne.s SkipInit
|
||||||
|
|
||||||
|
tst.w 0xa1000c
|
||||||
|
bne.s SkipInit
|
||||||
|
|
||||||
|
* Check Version Number
|
||||||
|
move.b -0x10ff(%a0),%d0
|
||||||
|
andi.b #0x0f,%d0
|
||||||
|
beq.s NoTMSS
|
||||||
|
|
||||||
|
* Sega Security Code (SEGA)
|
||||||
|
move.l #0x53454741,0x2f00(%a0)
|
||||||
|
|
||||||
|
NoTMSS:
|
||||||
|
jmp _start_entry
|
||||||
|
|
||||||
|
SkipInit:
|
||||||
|
jmp _reset_entry
|
||||||
|
|
||||||
|
|
||||||
|
*------------------------------------------------
|
||||||
|
*
|
||||||
|
* interrupt functions
|
||||||
|
*
|
||||||
|
*------------------------------------------------
|
||||||
|
|
||||||
|
_INT:
|
||||||
|
movem.l %d0-%d1/%a0-%a1,-(%sp)
|
||||||
|
move.l intCB, %a0
|
||||||
|
jsr (%a0)
|
||||||
|
movem.l (%sp)+,%d0-%d1/%a0-%a1
|
||||||
|
rte
|
||||||
|
|
||||||
|
_EXTINT:
|
||||||
|
movem.l %d0-%d1/%a0-%a1,-(%sp)
|
||||||
|
move.l eintCB, %a0
|
||||||
|
jsr (%a0)
|
||||||
|
movem.l (%sp)+,%d0-%d1/%a0-%a1
|
||||||
|
rte
|
||||||
|
|
||||||
|
_VINT:
|
||||||
|
btst #5, (%sp) /* Skip context switch if not in user task */
|
||||||
|
bne.s no_user_task
|
||||||
|
|
||||||
|
tst.w task_lock
|
||||||
|
bne.s 1f
|
||||||
|
move.w #0, -(%sp) /* TSK_superPend() will return 0 */
|
||||||
|
bra.s unlock /* If lock == 0, supervisor task is not locked */
|
||||||
|
|
||||||
|
1:
|
||||||
|
bcs.s no_user_task /* If lock < 0, super is locked with infinite wait */
|
||||||
|
subq.w #1, task_lock /* Locked with wait, subtract 1 to the frame count */
|
||||||
|
bne.s no_user_task /* And do not unlock if we did not reach 0 */
|
||||||
|
move.w #1, -(%sp) /* TSK_superPend() will return 1 */
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
/* Save bg task registers (excepting a7, that is stored in usp) */
|
||||||
|
move.l %a0, task_regs
|
||||||
|
lea (task_regs + UTSK_REGS_LEN), %a0
|
||||||
|
movem.l %d0-%d7/%a1-%a6, -(%a0)
|
||||||
|
|
||||||
|
move.w (%sp)+, %d0 /* Load return value previously pushed to stack */
|
||||||
|
|
||||||
|
move.w (%sp)+, task_sr /* Pop user task sr and pc, and save them, */
|
||||||
|
move.l (%sp)+, task_pc /* so they can be restored later. */
|
||||||
|
movem.l (%sp)+, %d2-%d7/%a2-%a6 /* Restore non clobberable registers */
|
||||||
|
|
||||||
|
no_user_task:
|
||||||
|
/* At this point, we always have in the stack the SR and PC of the task */
|
||||||
|
/* we want to jump after processing the interrupt, that might be the */
|
||||||
|
/* point where we came from (if there is no context switch) or the */
|
||||||
|
/* supervisor task (if we unlocked it). */
|
||||||
|
|
||||||
|
movem.l %d0-%d1/%a0-%a1,-(%sp)
|
||||||
|
ori.w #0x0001, intTrace /* in V-Int */
|
||||||
|
addq.l #1, vtimer /* increment frame counter (more a vint counter) */
|
||||||
|
btst #3, VBlankProcess+1 /* PROCESS_XGM_TASK ? (use VBlankProcess+1 as btst is a byte operation) */
|
||||||
|
beq.s no_xgm_task
|
||||||
|
|
||||||
|
jsr XGM_doVBlankProcess /* do XGM vblank task */
|
||||||
|
|
||||||
|
no_xgm_task:
|
||||||
|
btst #1, VBlankProcess+1 /* PROCESS_BITMAP_TASK ? (use VBlankProcess+1 as btst is a byte operation) */
|
||||||
|
beq.s no_bmp_task
|
||||||
|
|
||||||
|
jsr BMP_doVBlankProcess /* do BMP vblank task */
|
||||||
|
|
||||||
|
no_bmp_task:
|
||||||
|
move.l vintCB, %a0 /* load user callback */
|
||||||
|
jsr (%a0) /* call user callback */
|
||||||
|
andi.w #0xFFFE, intTrace /* out V-Int */
|
||||||
|
movem.l (%sp)+,%d0-%d1/%a0-%a1
|
||||||
|
rte
|
||||||
|
|
||||||
|
*------------------------------------------------
|
||||||
|
*
|
||||||
|
* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose
|
||||||
|
* on any computer system, and to redistribute it freely, with the
|
||||||
|
* following restrictions:
|
||||||
|
* 1) No charge may be made other than reasonable charges for reproduction.
|
||||||
|
* 2) Modified versions must be clearly marked as such.
|
||||||
|
* 3) The authors are not responsible for any harmful consequences
|
||||||
|
* of using this software, even if they result from defects in it.
|
||||||
|
*
|
||||||
|
*------------------------------------------------
|
||||||
|
|
||||||
|
ldiv:
|
||||||
|
move.l 4(%a7),%d0
|
||||||
|
bpl ld1
|
||||||
|
neg.l %d0
|
||||||
|
ld1:
|
||||||
|
move.l 8(%a7),%d1
|
||||||
|
bpl ld2
|
||||||
|
neg.l %d1
|
||||||
|
eor.b #0x80,4(%a7)
|
||||||
|
ld2:
|
||||||
|
bsr i_ldiv /* d0 = d0/d1 */
|
||||||
|
tst.b 4(%a7)
|
||||||
|
bpl ld3
|
||||||
|
neg.l %d0
|
||||||
|
ld3:
|
||||||
|
rts
|
||||||
|
|
||||||
|
lmul:
|
||||||
|
move.l 4(%a7),%d0
|
||||||
|
bpl lm1
|
||||||
|
neg.l %d0
|
||||||
|
lm1:
|
||||||
|
move.l 8(%a7),%d1
|
||||||
|
bpl lm2
|
||||||
|
neg.l %d1
|
||||||
|
eor.b #0x80,4(%a7)
|
||||||
|
lm2:
|
||||||
|
bsr i_lmul /* d0 = d0*d1 */
|
||||||
|
tst.b 4(%a7)
|
||||||
|
bpl lm3
|
||||||
|
neg.l %d0
|
||||||
|
lm3:
|
||||||
|
rts
|
||||||
|
|
||||||
|
lrem:
|
||||||
|
move.l 4(%a7),%d0
|
||||||
|
bpl lr1
|
||||||
|
neg.l %d0
|
||||||
|
lr1:
|
||||||
|
move.l 8(%a7),%d1
|
||||||
|
bpl lr2
|
||||||
|
neg.l %d1
|
||||||
|
lr2:
|
||||||
|
bsr i_ldiv /* d1 = d0%d1 */
|
||||||
|
move.l %d1,%d0
|
||||||
|
tst.b 4(%a7)
|
||||||
|
bpl lr3
|
||||||
|
neg.l %d0
|
||||||
|
lr3:
|
||||||
|
rts
|
||||||
|
|
||||||
|
ldivu:
|
||||||
|
move.l 4(%a7),%d0
|
||||||
|
move.l 8(%a7),%d1
|
||||||
|
bsr i_ldiv
|
||||||
|
rts
|
||||||
|
|
||||||
|
lmulu:
|
||||||
|
move.l 4(%a7),%d0
|
||||||
|
move.l 8(%a7),%d1
|
||||||
|
bsr i_lmul
|
||||||
|
rts
|
||||||
|
|
||||||
|
lremu:
|
||||||
|
move.l 4(%a7),%d0
|
||||||
|
move.l 8(%a7),%d1
|
||||||
|
bsr i_ldiv
|
||||||
|
move.l %d1,%d0
|
||||||
|
rts
|
||||||
|
*
|
||||||
|
* A in d0, B in d1, return A*B in d0
|
||||||
|
*
|
||||||
|
i_lmul:
|
||||||
|
move.l %d3,%a2 /* save d3 */
|
||||||
|
move.w %d1,%d2
|
||||||
|
mulu %d0,%d2 /* d2 = Al * Bl */
|
||||||
|
|
||||||
|
move.l %d1,%d3
|
||||||
|
swap %d3
|
||||||
|
mulu %d0,%d3 /* d3 = Al * Bh */
|
||||||
|
|
||||||
|
swap %d0
|
||||||
|
mulu %d1,%d0 /* d0 = Ah * Bl */
|
||||||
|
|
||||||
|
add.l %d3,%d0 /* d0 = (Ah*Bl + Al*Bh) */
|
||||||
|
swap %d0
|
||||||
|
clr.w %d0 /* d0 = (Ah*Bl + Al*Bh) << 16 */
|
||||||
|
|
||||||
|
add.l %d2,%d0 /* d0 = A*B */
|
||||||
|
move.l %a2,%d3 /* restore d3 */
|
||||||
|
rts
|
||||||
|
*
|
||||||
|
*A in d0, B in d1, return A/B in d0, A%B in d1
|
||||||
|
*
|
||||||
|
i_ldiv:
|
||||||
|
tst.l %d1
|
||||||
|
bne nz1
|
||||||
|
|
||||||
|
* divide by zero
|
||||||
|
* divu #0,%d0 /* cause trap */
|
||||||
|
move.l #0x80000000,%d0
|
||||||
|
move.l %d0,%d1
|
||||||
|
rts
|
||||||
|
nz1:
|
||||||
|
move.l %d3,%a2 /* save d3 */
|
||||||
|
cmp.l %d1,%d0
|
||||||
|
bhi norm
|
||||||
|
beq is1
|
||||||
|
* A<B, so ret 0, rem A
|
||||||
|
move.l %d0,%d1
|
||||||
|
clr.l %d0
|
||||||
|
move.l %a2,%d3 /* restore d3 */
|
||||||
|
rts
|
||||||
|
* A==B, so ret 1, rem 0
|
||||||
|
is1:
|
||||||
|
moveq.l #1,%d0
|
||||||
|
clr.l %d1
|
||||||
|
move.l %a2,%d3 /* restore d3 */
|
||||||
|
rts
|
||||||
|
* A>B and B is not 0
|
||||||
|
norm:
|
||||||
|
cmp.l #1,%d1
|
||||||
|
bne not1
|
||||||
|
* B==1, so ret A, rem 0
|
||||||
|
clr.l %d1
|
||||||
|
move.l %a2,%d3 /* restore d3 */
|
||||||
|
rts
|
||||||
|
* check for A short (implies B short also)
|
||||||
|
not1:
|
||||||
|
cmp.l #0xffff,%d0
|
||||||
|
bhi slow
|
||||||
|
* A short and B short -- use 'divu'
|
||||||
|
divu %d1,%d0 /* d0 = REM:ANS */
|
||||||
|
swap %d0 /* d0 = ANS:REM */
|
||||||
|
clr.l %d1
|
||||||
|
move.w %d0,%d1 /* d1 = REM */
|
||||||
|
clr.w %d0
|
||||||
|
swap %d0
|
||||||
|
move.l %a2,%d3 /* restore d3 */
|
||||||
|
rts
|
||||||
|
* check for B short
|
||||||
|
slow:
|
||||||
|
cmp.l #0xffff,%d1
|
||||||
|
bhi slower
|
||||||
|
* A long and B short -- use special stuff from gnu
|
||||||
|
move.l %d0,%d2
|
||||||
|
clr.w %d2
|
||||||
|
swap %d2
|
||||||
|
divu %d1,%d2 /* d2 = REM:ANS of Ahi/B */
|
||||||
|
clr.l %d3
|
||||||
|
move.w %d2,%d3 /* d3 = Ahi/B */
|
||||||
|
swap %d3
|
||||||
|
|
||||||
|
move.w %d0,%d2 /* d2 = REM << 16 + Alo */
|
||||||
|
divu %d1,%d2 /* d2 = REM:ANS of stuff/B */
|
||||||
|
|
||||||
|
move.l %d2,%d1
|
||||||
|
clr.w %d1
|
||||||
|
swap %d1 /* d1 = REM */
|
||||||
|
|
||||||
|
clr.l %d0
|
||||||
|
move.w %d2,%d0
|
||||||
|
add.l %d3,%d0 /* d0 = ANS */
|
||||||
|
move.l %a2,%d3 /* restore d3 */
|
||||||
|
rts
|
||||||
|
* A>B, B > 1
|
||||||
|
slower:
|
||||||
|
move.l #1,%d2
|
||||||
|
clr.l %d3
|
||||||
|
moreadj:
|
||||||
|
cmp.l %d0,%d1
|
||||||
|
bhs adj
|
||||||
|
add.l %d2,%d2
|
||||||
|
add.l %d1,%d1
|
||||||
|
bpl moreadj
|
||||||
|
* we shifted B until its >A or sign bit set
|
||||||
|
* we shifted #1 (d2) along with it
|
||||||
|
adj:
|
||||||
|
cmp.l %d0,%d1
|
||||||
|
bhi ltuns
|
||||||
|
or.l %d2,%d3
|
||||||
|
sub.l %d1,%d0
|
||||||
|
ltuns:
|
||||||
|
lsr.l #1,%d1
|
||||||
|
lsr.l #1,%d2
|
||||||
|
bne adj
|
||||||
|
* d3=answer, d0=rem
|
||||||
|
move.l %d0,%d1
|
||||||
|
move.l %d3,%d0
|
||||||
|
move.l %a2,%d3 /* restore d3 */
|
||||||
|
rts
|
||||||
BIN
src/gfx/pointer.png
Normal file
BIN
src/gfx/pointer.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
68
src/main.c
Normal file
68
src/main.c
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#include "genesis.h"
|
||||||
|
|
||||||
|
#define MOUSE_PORT ((volatile u8*)0xA10003)
|
||||||
|
#define Z80_HALT *((volatile u16*)0xA11100)
|
||||||
|
|
||||||
|
#define MOUSE_DELAY 32
|
||||||
|
|
||||||
|
static inline void delay() {
|
||||||
|
for(int i=0;i<MOUSE_DELAY;i++) asm volatile("nop");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
VDP_setTextPlane(0);
|
||||||
|
VDP_drawText("Sega Mega Mouse RAW reader", 2, 16);
|
||||||
|
|
||||||
|
u8 nibbles[16];
|
||||||
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
while(TRUE) {
|
||||||
|
|
||||||
|
SYS_doVBlankProcess();
|
||||||
|
|
||||||
|
VDP_clearTextArea(0, 0, 40, 13);
|
||||||
|
|
||||||
|
// считываем нибблы напрямую
|
||||||
|
Z80_HALT = 0x0100;
|
||||||
|
*MOUSE_PORT = 0x60; delay();
|
||||||
|
*MOUSE_PORT = 0x60; delay();
|
||||||
|
|
||||||
|
for(int i=1;i<10;i++) {
|
||||||
|
*MOUSE_PORT = (i&1)?0x00:0x20;
|
||||||
|
delay();
|
||||||
|
nibbles[i] = *MOUSE_PORT & 0x0F;
|
||||||
|
delay();
|
||||||
|
}
|
||||||
|
|
||||||
|
*MOUSE_PORT = 0x60; delay();
|
||||||
|
Z80_HALT = 0x0000;
|
||||||
|
|
||||||
|
// выводим нибблы на экран
|
||||||
|
char buf[64];
|
||||||
|
int dx = (nibbles[6] << 4) | nibbles[7];
|
||||||
|
int dy = (nibbles[8] << 4) | nibbles[9];
|
||||||
|
|
||||||
|
if (nibbles[3]&8) dy = 255;
|
||||||
|
if (nibbles[3]&4) dx = 255;
|
||||||
|
if (nibbles[3]&2) dy = -dy;
|
||||||
|
if (nibbles[3]&1) dx = -dx;
|
||||||
|
|
||||||
|
x+=dx;
|
||||||
|
y+=dy;
|
||||||
|
|
||||||
|
|
||||||
|
sprintf(buf, "dx: %+04d dy: %+04d x: %+04d y: %+04d", dx,dy,x/64,y/64);
|
||||||
|
VDP_drawText(buf, 2, 12);
|
||||||
|
sprintf(buf, "buttons: %c%c%c%c", (nibbles[4]&8&&1)+'0',(nibbles[4]&4&&1)+'0',(nibbles[4]&2&&1)+'0',(nibbles[4]&1&&1)+'0');
|
||||||
|
VDP_drawText(buf, 2, 10);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
1
src/resource.res
Normal file
1
src/resource.res
Normal file
@ -0,0 +1 @@
|
|||||||
|
SPRITE pointer "gfx/pointer.png" 6 6 FAST
|
||||||
Loading…
x
Reference in New Issue
Block a user