diff --git a/core/boot.asm b/core/boot.asm index 36a0ccf..ab717a1 100644 --- a/core/boot.asm +++ b/core/boot.asm @@ -4,24 +4,17 @@ #import "../core/module.asm" #import "../core/system.asm" +#import "../hardware/cia.asm" +#import "../hardware/sid.asm" +#import "../hardware/mc6502.asm" +#import "../hardware/ram.asm" +#import "../hardware/vic.asm" .filenamespace Boot -.const INIT_IRQ = $fda3 -.const INIT_MEM = $fd50 -.const INIT_IO = $fd15 -.const INIT_VID = $ff5b -.const SCRN_CTRL = $d016 - -.const MAIN_COLOR = $03 -.const BORDER_COLOR = $05 -.const INTERRUPT_CTRL = $dc0d -.const NMSK_INTERRUPT_CTRL = $dd0d -.const TIMER_A_CTRL = $DC0E * = * "Boot Core" - // ======================================================== // ////// METHODS ///////////////////////////////////////// // ======================================================== @@ -35,50 +28,78 @@ coldStart: { sei txs cld - stx SCRN_CTRL // Set Screen Bits - jsr INIT_IRQ // Prepare IRQ - jsr INIT_MEM // Init memory. Rewrite this routine to speed up boot process. - jsr INIT_IO // Init I/O - jsr INIT_VID // Init video + stx Vic.CR2 // Set Video Bits + jsr Boot.initIRQ // Prepare IRQ + jsr Ram.init // Init memory. + jsr Vic.init // Init video cli jmp warmStart } +// -------------------------------------------------------- +// initIRQ - +// Initialize Interrupt states after a cold start. +// Should never be executed as standard Init and should +// always be before it. This is extracted by c64 kernel +// routine IOINIT. +// -------------------------------------------------------- +initIRQ: { + lda #$7F // KILL INTERRUPTS + sta Cia.C1ICR + sta Cia.C2ICR + + sta Cia.C1PRA // TURN ON STOP KEY + + lda #%00001000 // SHUT OFF TIMERS + sta Cia.C1CRA + sta Cia.C2CRA + sta Cia.C1CRB + sta Cia.C2CRB + + // CONFIGURE PORTS + ldx #$00 // SET UP KEYBOARD INPUTS + stx Cia.C1DDRB // KEYBOARD INPUTS + stx Cia.C2DDRB // USER PORT (NO RS-232) + + stx Sid.FMVC // TURN OFF SID + + dex // set X = $FF + + stx Cia.C1DDRA // KEYBOARD OUTPUTS + + lda #%00000111 // SET SERIAL/VA14/15 (CLKHI) + sta Cia.C2PRA + + lda #%00111111 // ;SET SERIAL IN/OUT, VA14/15OUT + sta Cia.C2DDRA + + // SET UP THE 6510 LINES + lda #%11100111 // MOTOR ON, HIRAM LOWRAM CHAREN HIGH + sta MC6502.ZR1 // set 1110 0111, motor off, enable I/O, enable KERNAL, Disable BASIC + + lda #%00101111 // set 0010 1111, 0 = input, 1 = output + sta MC6502.ZR0 // save the 6510 I/O port direction register + + rts +} + + + // -------------------------------------------------------- // warmStart - // Restore pressed or program restart after first Power ON // -------------------------------------------------------- warmStart: { - sei - lda #$7f - sta INTERRUPT_CTRL // disable timer interrupts which can be generated by the two CIA chips - sta NMSK_INTERRUPT_CTRL // the kernal uses such an interrupt to flash the cursor and scan the keyboard, so we better - // stop it. - - lda INTERRUPT_CTRL // by reading this two registers we negate any pending CIA irqs. - lda NMSK_INTERRUPT_CTRL // if we don't do this, a pending CIA irq might occur after we finish setting up our irq. - // we don't want that to happen. - - // Disable 0e TIMER - lda #254 - and TIMER_A_CTRL - sta TIMER_A_CTRL - - ScreenClearColorRam($00) - ScreenClear(' ') - ScreenSetBorderColor(BORDER_COLOR) - ScreenSetBackgroundColor(MAIN_COLOR) + jsr Boot.init // Init Self as Module cli - jsr Boot.init // Init Self as Module jsr System.start // Start Core System // If System Exit - reboot // TODO: We can print a message here // and delay a bit... jmp warmStart - } // -------------------------------------------------------- diff --git a/core/mem_map.asm b/core/mem_map.asm index 73b49ce..438c8e1 100644 --- a/core/mem_map.asm +++ b/core/mem_map.asm @@ -20,7 +20,7 @@ TempStringPointer: .word 0 // Pointer to string address as it get printend to screen } -.namespace SCREEN { +.namespace VIDEO { TempVideoPointer: .word 0 // Pointer to video mem used to target char pos CursorCol: .byte 0 // Actual cursor column position CursorRow: .byte 0 // Actual cursor row position diff --git a/core/module.asm b/core/module.asm index cb69b99..10484db 100644 --- a/core/module.asm +++ b/core/module.asm @@ -59,10 +59,12 @@ // ======================================================== .namespace TYPES { - .label MAIN = 00 - .label LIB = 01 - .label PROG = 02 - .label CORE = 03 + .label MAIN = 00 + .label LIB = 01 + .label PROG = 02 + .label CORE = 03 + .label DEVICE = 04 + } @@ -140,6 +142,11 @@ printType: { bne !+ PrintLine(type_core) rts + !: + cmp #Module.TYPES.DEVICE + bne !+ + PrintLine(type_device) + rts !: cmp #Module.TYPES.PROG bne !+ @@ -176,6 +183,9 @@ type_prog: .text "prog" .byte 0 +type_device: + .text "device" + .byte 0 #import "../core/mem_map.asm" diff --git a/core/system.asm b/core/system.asm index 8f6dc42..d2585ea 100644 --- a/core/system.asm +++ b/core/system.asm @@ -6,12 +6,18 @@ #import "../libs/memory.asm" #import "../libs/math.asm" #import "../libs/print.asm" -#import "../libs/keyboard.asm" -#import "../libs/screen.asm" +#import "../devices/keyboard.asm" +#import "../devices/video.asm" #import "../progs/woz_shell.asm" .filenamespace System +// ======================================================== +// ////// CONST /////////////////////////////////////////// +// ======================================================== +.const MAIN_COLOR = $03 +.const BORDER_COLOR = $05 + * = * "System Core" @@ -24,8 +30,10 @@ // System Start // -------------------------------------------------------- start: { - - + VideoClearColorRam($00) + VideoClear(' ') + VideoSetBorderColor(BORDER_COLOR) + VideoSetBackgroundColor(MAIN_COLOR) // Start Main Program jsr WozShell.start @@ -46,7 +54,7 @@ init: { // Init All Modules // TODO: How we can make this dynamic? jsr Memory.init - jsr Screen.init + jsr Video.init jsr Print.init jsr Math.init jsr Keyboard.init @@ -72,7 +80,7 @@ toDebug: { jsr Math.toDebug jsr Memory.toDebug jsr Print.toDebug - jsr Screen.toDebug + jsr Video.toDebug jsr WozShell.toDebug rts diff --git a/libs/keyboard.asm b/devices/keyboard.asm similarity index 99% rename from libs/keyboard.asm rename to devices/keyboard.asm index 3764c59..a74b7e5 100644 --- a/libs/keyboard.asm +++ b/devices/keyboard.asm @@ -22,7 +22,7 @@ -* = * "Keyboard Lib" +* = * "Device: Keyboard" // ======================================================== // ////// METHODS ROM ///////////////////////////////////// @@ -356,8 +356,8 @@ cloneEnd: // ////// DATA //////////////////////////////////////////// // ======================================================== -* = * "Keyboard Lib Data" -module_type: .byte Module.TYPES.LIB +* = * "Device: Keyboard Data" +module_type: .byte Module.TYPES.DEVICE version: .byte 1, 1, 0 .encoding "screencode_mixed" diff --git a/libs/screen.asm b/devices/video.asm similarity index 73% rename from libs/screen.asm rename to devices/video.asm index 88bec4e..d011701 100644 --- a/libs/screen.asm +++ b/devices/video.asm @@ -10,17 +10,17 @@ // ======================================================== -* = * "Screen Lib" +* = * "Device: Video" // -------------------------------------------------------- -// ScreenClearChunks - +// VideoClearChunks - // Fast clear screen mem chunks. // // Parameters: // baseAddress = Pointer to screen orcolor map Address // clearByte = Byte to use to clear screen // -------------------------------------------------------- -.macro ScreenClearChunks(baseAddress, clearByte) { +.macro VideoClearChunks(baseAddress, clearByte) { lda #clearByte ldx #0 !loop: @@ -29,94 +29,94 @@ sta baseAddress + $200, x sta baseAddress + $300, x inx - bne.r !loop- + bne !loop- } // -------------------------------------------------------- -// ScreenClear - +// VideoClear - // Fast clear screen characters mem. // // Parameters: // clearByte = Byte to use to clear screen // -------------------------------------------------------- -.macro ScreenClear(clearByte) { - ScreenClearChunks(Screen.VIDEO_ADDR, clearByte) +.macro VideoClear(clearByte) { + VideoClearChunks(Video.VIDEO_ADDR, clearByte) } // -------------------------------------------------------- -// ScreenClear - +// VideoClear - // Fast clear screen Color Ram. // // Parameters: // clearByte = Byte to use to clear screen // -------------------------------------------------------- -.macro ScreenClearColorRam(clearByte) { - ScreenClearChunks(Screen.COLOR_ADDR, clearByte) +.macro VideoClearColorRam(clearByte) { + VideoClearChunks(Video.COLOR_ADDR, clearByte) } // -------------------------------------------------------- -// ScreenSetBorderColor - -// Set Screen border color. +// VideoSetBorderColor - +// Set Video border color. // // Parameters: // color = https://www.c64-wiki.com/wiki/Color // -------------------------------------------------------- -.macro ScreenSetBorderColor(color) { +.macro VideoSetBorderColor(color) { lda #color sta $d020 } // -------------------------------------------------------- -// ScreenSetBackgroundColor - -// Set Screen Backfground color. +// VideoSetBackgroundColor - +// Set Video Backfground color. // // Parameters: // color = https://www.c64-wiki.com/wiki/Color // -------------------------------------------------------- -.macro ScreenSetBackgroundColor(color) { +.macro VideoSetBackgroundColor(color) { lda #color sta $d021 } // -------------------------------------------------------- -// ScreenSetMultiColor1 - -// Set Screen Muticolor 1. +// VideoSetMultiColor1 - +// Set Video Muticolor 1. // // Parameters: // color = https://www.c64-wiki.com/wiki/Color // -------------------------------------------------------- -.macro ScreenSetMultiColor1(color) { +.macro VideoSetMultiColor1(color) { lda #color sta $d022 } // -------------------------------------------------------- -// ScreenSetMultiColor2 - -// Set Screen Muticolor 2. +// VideoSetMultiColor2 - +// Set Video Muticolor 2. // // Parameters: // color = https://www.c64-wiki.com/wiki/Color // -------------------------------------------------------- -.macro ScreenSetMultiColor2(color) { +.macro VideoSetMultiColor2(color) { lda #color sta $d023 } // -------------------------------------------------------- -// ScreenSetMultiColorMode - -// Set Screen Muticolor 2. +// VideoSetMultiColorMode - +// Set Video Muticolor 2. // // Parameters: // color = https://www.c64-wiki.com/wiki/Multicolor_Bitmap_Mode // -------------------------------------------------------- -.macro ScreenSetMultiColorMode() { +.macro VideoSetMultiColorMode() { lda $d016 ora #16 sta $d016 } -.filenamespace Screen +.filenamespace Video // ======================================================== // ////// CONSTANTS /////////////////////////////////////// @@ -141,8 +141,8 @@ // -------------------------------------------------------- init: { lda #$00 - sta MemMap.SCREEN.CursorCol - sta MemMap.SCREEN.CursorRow + sta MemMap.VIDEO.CursorCol + sta MemMap.VIDEO.CursorRow rts } @@ -169,7 +169,7 @@ scrollUp: { sta VIDEO_ADDR+(COLUMN_NUM*(ROWS_NUM-1)), x dex bpl !- // x == -1 - dec MemMap.SCREEN.CursorRow + dec MemMap.VIDEO.CursorRow pla rts } @@ -181,35 +181,35 @@ scrollUp: { // end of screen scrolling and Backspace. // // Parameters: -// A = Character to Print SCREEN ASCII +// A = Character to Print VIDEO ASCII // -------------------------------------------------------- sendChar: { sei phx cmp #CR - bne.r !+ + bne !+ jsr screenNewLine iny jmp exit !: cmp #BS - bne.r !+ - ldx MemMap.SCREEN.CursorCol + bne !+ + ldx MemMap.VIDEO.CursorCol cmp #0 beq exit - dec MemMap.SCREEN.CursorCol + dec MemMap.VIDEO.CursorCol !: // Store Base Video Address 16 bit ldx #VIDEO_ADDR // High byte - stx MemMap.SCREEN.TempVideoPointer+1 + stx MemMap.VIDEO.TempVideoPointer+1 // Temp Save Y phy // CursorRow * 40 - ldy MemMap.SCREEN.CursorRow + ldy MemMap.VIDEO.CursorRow sty MemMap.MATH.factor1 ldy #COLUMN_NUM sty MemMap.MATH.factor2 @@ -219,28 +219,28 @@ sendChar: { clc pha lda MemMap.MATH.result - adc MemMap.SCREEN.TempVideoPointer+1 - sta MemMap.SCREEN.TempVideoPointer+1 + adc MemMap.VIDEO.TempVideoPointer+1 + sta MemMap.VIDEO.TempVideoPointer+1 lda MemMap.MATH.result+1 - adc MemMap.SCREEN.TempVideoPointer - sta MemMap.SCREEN.TempVideoPointer + adc MemMap.VIDEO.TempVideoPointer + sta MemMap.VIDEO.TempVideoPointer - ldy MemMap.SCREEN.CursorCol + ldy MemMap.VIDEO.CursorCol cpy #COLUMN_NUM // Is this > col num? - bcc.r noEndOfLine + bcc noEndOfLine jsr screenNewLine // Yes? Add new list first ldy #1 - cpy MemMap.SCREEN.ScrollUpTriggered + cpy MemMap.VIDEO.ScrollUpTriggered bne noScrollTriggered // Compensate Scroll sec - lda MemMap.SCREEN.TempVideoPointer + lda MemMap.VIDEO.TempVideoPointer sbc #1 - sta MemMap.SCREEN.TempVideoPointer + sta MemMap.VIDEO.TempVideoPointer bcs !+ - dec MemMap.SCREEN.TempVideoPointer+1 + dec MemMap.VIDEO.TempVideoPointer+1 !: noScrollTriggered: @@ -251,16 +251,16 @@ sendChar: { cmp #BS bne !+ lda #' ' - sta (MemMap.SCREEN.TempVideoPointer), y + sta (MemMap.VIDEO.TempVideoPointer), y ply jmp exit !: // insert into screen - sta (MemMap.SCREEN.TempVideoPointer), y + sta (MemMap.VIDEO.TempVideoPointer), y ply iny - inc MemMap.SCREEN.CursorCol + inc MemMap.VIDEO.CursorCol exit: plx @@ -276,28 +276,28 @@ sendChar: { screenNewLine: { pha lda #0 - sta MemMap.SCREEN.CursorCol + sta MemMap.VIDEO.CursorCol lda #ROWS_NUM-1 - cmp MemMap.SCREEN.CursorRow // Are we at the screen bottom? + cmp MemMap.VIDEO.CursorRow // Are we at the screen bottom? bne noScrollUp - jsr Screen.scrollUp + jsr Video.scrollUp lda #1 // Yes - Scroll up - sta MemMap.SCREEN.ScrollUpTriggered + sta MemMap.VIDEO.ScrollUpTriggered jmp done noScrollUp: lda #0 - sta MemMap.SCREEN.ScrollUpTriggered + sta MemMap.VIDEO.ScrollUpTriggered done: - inc MemMap.SCREEN.CursorRow + inc MemMap.VIDEO.CursorRow pla rts } -* = * "Screen Lib Data" -module_type: .byte Module.TYPES.LIB +* = * "Device: Video Data" +module_type: .byte Module.TYPES.DEVICE version: .byte 1, 0, 1 module_name: - .text "screen" + .text "video" .byte 0 #import "../core/mem_map.asm" diff --git a/hardware/cia.asm b/hardware/cia.asm new file mode 100644 index 0000000..0a794d5 --- /dev/null +++ b/hardware/cia.asm @@ -0,0 +1,209 @@ +#importonce + +.filenamespace Cia +// https://www.c64-wiki.com/wiki/CIA + +// ======================================================== +// ////// CONSTANTS /////////////////////////////////////// +// ======================================================== + +// CIA 1 +// ======================================================== + +.label C1PRA = $DC00 // CIA 1 A Register Monitoring/control of the 8 data lines of Port A + // Read/Write: Bit 0..7 keyboard matrix columns + // Read: Joystick Port 2: Bit 0..3 Direction (Left/Right/Up/Down), Bit 4 Fire button. 0 = activated. + // Read: Lightpen: Bit 4 (as fire button), connected also with "/LP" (Pin 9) of the VIC + // Read: Paddles: Bit 2..3 Fire buttons, Bit 6..7 Switch control port 1 (%01=Paddles A) or 2 (%10=Paddles B) + +.label C1PRB = $DC01 // Monitoring/control of the 8 data lines of Port B. The lines are used for multiple purposes: + // Read/Write: Bit 0..7 keyboard matrix rows + // Read: Joystick Port 1: Bit 0..3 Direction (Left/Right/Up/Down), Bit 4 Fire button. 0 = activated. + // Read: Bit 6: Timer A: Toggle/Impulse output (see register 14 bit 2) + // Read: Bit 7: Timer B: Toggle/Impulse output (see register 15 bit 2) + +.label C1DDRA = $DC02 // Bit X: 0=Input (read only), 1=Output (read and write) + +.label C1DDRB = $DC03 // Bit X: 0=Input (read only), 1=Output (read and write) + +.label C1TALO = $DC04 // Read: actual value Timer A (Low Byte) + // Writing: Set latch of Timer A (Low Byte) + +.label C1TAHI = $DC05 // Read: actual value Timer A (High Byte) + // Writing: Set latch of timer A (High Byte) - if the timer is stopped, the high-byte will automatically be re-set as well + + +.label C1TBLO = $DC06 // Read: actual value Timer B (Low Byte) + // Writing: Set latch of Timer B (Low Byte) + + +.label C1TBHI = $DC07 // Read: actual value Timer B (High Byte) + // Writing: Set latch of timer B (High Byte) - if the timer is stopped, the high-byte will automatically be re-set as well + +.label C1TOD10THS = $DC08 // Read: + // Bit 0..3: Tenth seconds in BCD-format ($0-$9) + // Bit 4..7: always 0 + // Writing: + // Bit 0..3: if CRB-Bit7=0: Set the tenth seconds in BCD-format + // Bit 0..3: if CRB-Bit7=1: Set the tenth seconds of the alarm time in BCD-format + +.label C1TODSEC = $DC09 // Bit 0..3: Single seconds in BCD-format ($0-$9) + // Bit 4..6: Ten seconds in BCD-format ($0-$5) + // Bit 7: always 0 + +.label C1TODMIN = $DC0A // Bit 0..3: Single minutes in BCD-format( $0-$9) + // Bit 4..6: Ten minutes in BCD-format ($0-$5) + // Bit 7: always 0 + +.label C1TODHR = $DC0B // Bit 0..3: Single hours in BCD-format ($0-$9) + // Bit 4..6: Ten hours in BCD-format ($0-$5) + // Bit 7: Differentiation AM/PM, 0=AM, 1=PM + // Writing into this register stops TOD, until register 8 (TOD 10THS) will be read. + +.label C1TSDR = $DC0C // The byte within this register will be shifted bitwise to or from the SP-pin with every positive slope at the CNT-pin. + +.label C1ICR = $DC0D // CIA1 is connected to the IRQ-Line. + // Read: (Bit0..4 = INT DATA, Origin of the interrupt) + // Bit 0: 1 = Underflow Timer A + // Bit 1: 1 = Underflow Timer B + // Bit 2: 1 = Time of day and alarm time is equal + // Bit 3: 1 = SDR full or empty, so full byte was transferred, depending of operating mode serial bus + // Bit 4: 1 = IRQ Signal occured at FLAG-pin (cassette port Data input, serial bus SRQ IN) + // Bit 5..6: always 0 + // Bit 7: 1 = IRQ An interrupt occured, so at least one bit of INT MASK and INT DATA is set in both registers. + // Flags will be cleared after reading the register! + // Write: (Bit 0..4 = INT MASK, Interrupt mask) + // Bit 0: 1 = Interrupt release through timer A underflow + // Bit 1: 1 = Interrupt release through timer B underflow + // Bit 2: 1 = Interrupt release if clock=alarmtime + // Bit 3: 1 = Interrupt release if a complete byte has been received/sent. + // Bit 4: 1 = Interrupt release if a positive slope occurs at the FLAG-Pin. + // Bit 5..6: unused + // Bit 7: Source bit. 0 = set bits 0..4 are clearing the according mask bit. 1 = set bits 0..4 are setting the according mask bit. If all bits 0..4 are cleared, there will be no change to the mask. + +.label C1CRA = $DC0E // Control Timer A + // Bit 0: 0 = Stop timer; 1 = Start timer + // Bit 1: 1 = Indicates a timer underflow at port B in bit 6. + // Bit 2: 0 = Through a timer overflow, bit 6 of port B will get high for one cycle , 1 = Through a timer underflow, bit 6 of port B will be inverted + // Bit 3: 0 = Timer-restart after underflow (latch will be reloaded), 1 = Timer stops after underflow. + // Bit 4: 1 = Load latch into the timer once. + // Bit 5: 0 = Timer counts system cycles, 1 = Timer counts positive slope at CNT-pin + // Bit 6: Direction of the serial shift register, 0 = SP-pin is input (read), 1 = SP-pin is output (write) + // Bit 7: Real Time Clock, 0 = 60 Hz, 1 = 50 Hz + +.label C1CRB = $DC0F // Control Timer B + // Bit 0: 0 = Stop timer; 1 = Start timer + // Bit 1: 1 = Indicates a timer underflow at port B in bit 7. + // Bit 2: 0 = Through a timer overflow, bit 7 of port B will get high for one cycle , 1 = Through a timer underflow, bit 7 of port B will be inverted + // Bit 3: 0 = Timer-restart after underflow (latch will be reloaded), 1 = Timer stops after underflow. + // Bit 4: 1 = Load latch into the timer once. + // Bit 5..6: + // %00 = Timer counts System cycle + // %01 = Timer counts positive slope on CNT-pin + // %10 = Timer counts underflow of timer A + // %11 = Timer counts underflow of timer A if the CNT-pin is high + // Bit 7: 0 = Writing into the TOD register sets the clock time, 1 = Writing into the TOD register sets the alarm time. + + +// CIA 2 +// ======================================================== + +.label C2PRA = $DD00 // CIA 2 A Register Monitoring/control of the 8 data lines of Port A + // Bit 0..1: Select the position of the VIC-memory + // %00, 0: Bank 3: $C000-$FFFF, 49152-65535 + // %01, 1: Bank 2: $8000-$BFFF, 32768-49151 + // %10, 2: Bank 1: $4000-$7FFF, 16384-32767 + // %11, 3: Bank 0: $0000-$3FFF, 0-16383 (standard) + // Bit 2: RS-232: TXD Output, userport: Data PA 2 (pin M) + // Bit 3..5: serial bus Output (0=High/Inactive, 1=Low/Active) + // Bit 3: ATN OUT + // Bit 4: CLOCK OUT + // Bit 5: DATA OUT + // Bit 6..7: serial bus Input (0=Low/Active, 1=High/Inactive) + // Bit 6: CLOCK IN + // Bit 7: DATA IN + +.label C2PRB = $DD01 // Monitoring/control of the 8 data lines of Port B. The lines are used for multiple purposes: + // Bit 0..7: userport Data PB 0-7 (Pins C,D,E,F,H,J,K,L) + // The KERNAL offers several RS232-Routines, which use the pins as followed: + // Bit 0, 3..7: RS-232: reading + // Bit 0: RXD + // Bit 3: RI + // Bit 4: DCD + // Bit 5: User port pin J + // Bit 6: CTS + // Bit 7: DSR + // Bit 1..5: RS-232: writing + // Bit 1: RTS + // Bit 2: DTR + // Bit 3: RI + // Bit 4: DCD + // Bit 5: User port pin J + +.label C2DDRA = $DD02 // Bit X: 0=Input (read only), 1=Output (read and write) + +.label C2DDRB = $DD03 // Bit X: 0=Input (read only), 1=Output (read and write) + +.label C2TALO = $DD04 // Read: actual value Timer A (Low Byte) + // Writing: Set latch of Timer A (Low Byte) + +.label C2TAHI = $DD05 // Read: actual value Timer A (High Byte) + // Writing: Set latch of timer A (High Byte) - if the timer is stopped, the high-byte will automatically be re-set as well + + +.label C2TBLO = $DD06 // Read: actual value Timer B (Low Byte) + // Writing: Set latch of Timer B (Low Byte) + + +.label C2TBHI = $DD07 // Read: actual value Timer B (High Byte) + // Writing: Set latch of timer B (High Byte) - if the timer is stopped, the high-byte will automatically be re-set as well + +.label C2TOD10THS = $DD08 // Read: + // Bit 0..3: Tenth seconds in BCD-format ($0-$9) + // Bit 4..7: always 0 + // Writing: + // Bit 0..3: if CRB-Bit7=0: Set the tenth seconds in BCD-format + // Bit 0..3: if CRB-Bit7=1: Set the tenth seconds of the alarm time in BCD-format + +.label C2TODSEC = $DD09 // Bit 0..3: Single seconds in BCD-format ($0-$9) + // Bit 4..6: Ten seconds in BCD-format ($0-$5) + // Bit 7: always 0 + +.label C2TODMIN = $DD0A // Bit 0..3: Single minutes in BCD-format( $0-$9) + // Bit 4..6: Ten minutes in BCD-format ($0-$5) + // Bit 7: always 0 + +.label C2TODHR = $DD0B // Bit 0..3: Single hours in BCD-format ($0-$9) + // Bit 4..6: Ten hours in BCD-format ($0-$5) + // Bit 7: Differentiation AM/PM, 0=AM, 1=PM + // Writing into this register stops TOD, until register 8 (TOD 10THS) will be read. + +.label C2TSDR = $DD0C // The byte within this register will be shifted bitwise to or from the SP-pin with every positive slope at the CNT-pin. + +.label C2ICR = $DD0D // CIA2 is connected to the NMI-Line. + // Bit 4: 1 = NMI Signal occured at FLAG-pin (RS-232 data received) + // Bit 7: 1 = NMI An interrupt occured, so at least one bit of INT MASK and INT DATA is set in both registers. + +.label C2CRA = $DD0E // Control Timer A + // Bit 0: 0 = Stop timer; 1 = Start timer + // Bit 1: 1 = Indicates a timer underflow at port B in bit 6. + // Bit 2: 0 = Through a timer overflow, bit 6 of port B will get high for one cycle , 1 = Through a timer underflow, bit 6 of port B will be inverted + // Bit 3: 0 = Timer-restart after underflow (latch will be reloaded), 1 = Timer stops after underflow. + // Bit 4: 1 = Load latch into the timer once. + // Bit 5: 0 = Timer counts system cycles, 1 = Timer counts positive slope at CNT-pin + // Bit 6: Direction of the serial shift register, 0 = SP-pin is input (read), 1 = SP-pin is output (write) + // Bit 7: Real Time Clock, 0 = 60 Hz, 1 = 50 Hz + +.label C2CRB = $DD0F // Control Timer B + // Bit 0: 0 = Stop timer; 1 = Start timer + // Bit 1: 1 = Indicates a timer underflow at port B in bit 7. + // Bit 2: 0 = Through a timer overflow, bit 7 of port B will get high for one cycle , 1 = Through a timer underflow, bit 7 of port B will be inverted + // Bit 3: 0 = Timer-restart after underflow (latch will be reloaded), 1 = Timer stops after underflow. + // Bit 4: 1 = Load latch into the timer once. + // Bit 5..6: + // %00 = Timer counts System cycle + // %01 = Timer counts positive slope on CNT-pin + // %10 = Timer counts underflow of timer A + // %11 = Timer counts underflow of timer A if the CNT-pin is high + // Bit 7: 0 = Writing into the TOD register sets the clock time, 1 = Writing into the TOD register sets the alarm time. + diff --git a/hardware/mc6502.asm b/hardware/mc6502.asm new file mode 100644 index 0000000..7cca51f --- /dev/null +++ b/hardware/mc6502.asm @@ -0,0 +1,25 @@ +#importonce +.filenamespace MC6502 +https://sta.c64.org/cbm64mem.html + +// ======================================================== +// ////// CONSTANTS /////////////////////////////////////// +// ======================================================== + + +.label ZR0 = $0 // Processor port data direction register. Bits: + // Bit #x: 0 = Bit #x in processor port can only be read; 1 = Bit #x in processor port can be read and written. + // Default: $2F, %00101111. + +.label ZR1 = $1 // Processor port. Bits: + // Bits #0-#2: Configuration for memory areas $A000-$BFFF, $D000-$DFFF and $E000-$FFFF. Values: + // %x00: RAM visible in all three areas. + // %x01: RAM visible at $A000-$BFFF and $E000-$FFFF. + // %x10: RAM visible at $A000-$BFFF; KERNAL ROM visible at $E000-$FFFF. + // %x11: BASIC ROM visible at $A000-$BFFF; KERNAL ROM visible at $E000-$FFFF. + // %0xx: Character ROM visible at $D000-$DFFF. (Except for the value %000, see above.) + // %1xx: I/O area visible at $D000-$DFFF. (Except for the value %100, see above.) + // Bit #3: Datasette output signal level. + // Bit #4: Datasette button status; 0 = One or more of PLAY, RECORD, F.FWD or REW pressed; 1 = No button is pressed. + // Bit #5: Datasette motor control; 0 = On; 1 = Off. + // Default: $37, %00110111. \ No newline at end of file diff --git a/hardware/ram.asm b/hardware/ram.asm new file mode 100644 index 0000000..c411ccd --- /dev/null +++ b/hardware/ram.asm @@ -0,0 +1,30 @@ +#importonce +.filenamespace Ram + +// ======================================================== +// ////// CONSTANTS /////////////////////////////////////// +// ======================================================== + + + +// ======================================================== +// ////// METHODS ///////////////////////////////////////// +// ======================================================== + + +* = * "Ram HW" + +init: { + // Clear Zero Page + lda #$00 + tay + !: + sta $0002,y + sta $0200,y + sta $0300,y + iny + bne !- + rts +} + + diff --git a/hardware/sid.asm b/hardware/sid.asm new file mode 100644 index 0000000..f9ad755 --- /dev/null +++ b/hardware/sid.asm @@ -0,0 +1,25 @@ +#importonce +.filenamespace Sid +https://www.c64-wiki.com/wiki/SID + +// ======================================================== +// ////// CONSTANTS /////////////////////////////////////// +// ======================================================== + + +.label FV1L = $d400 // frequency voice 1 low byte +.label FV1H = $d401 // frequency voice 1 high byte +.label PCWV1L = $d402 // pulse wave duty cycle voice 1 low byte + +// TODO: Add more + +.label FMVC = $d418 // filter mode and main volume control + // Bit 7 mute voice 3 + // Bit 6 high pass + // Bit 5 band pass + // Bit 4 low pass + // Bit 3-0 main volume + + + + diff --git a/hardware/vic.asm b/hardware/vic.asm new file mode 100644 index 0000000..d4b1857 --- /dev/null +++ b/hardware/vic.asm @@ -0,0 +1,36 @@ +#importonce +.filenamespace Vic +// https://www.c64-wiki.com/wiki/VIC +// https://www.c64-wiki.com/wiki/Page_208-211 + +// ======================================================== +// ////// CONSTANTS /////////////////////////////////////// +// ======================================================== + +.label VICREG = $D000 + +.label CR2 = $D016 // Control register 2 + + +* = * "VIC Functions" + +init: { + ldx #47 + px4: + lda tvic-1, x + sta VICREG-1, x + dex + bne px4 + rts +} + +* = * "VIC Init Data" + +tvic: + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $9B, $37, $00, $00, $00, $08, $00 + .byte $14, $0F, $00, $00 ,$00, $00, $00, $00 + .byte $0E, $06, $01, $02, $03, $04, $00, $01 + .byte $02, $03, $04, $05, $06, $07, $4C + diff --git a/libs/math.asm b/libs/math.asm index eef6fc4..1f3b304 100644 --- a/libs/math.asm +++ b/libs/math.asm @@ -1,7 +1,6 @@ #importonce #import "../core/module.asm" -#import "../core/module.asm" .filenamespace Math @@ -50,13 +49,13 @@ multiply: { lda #$00 ldx #$08 clc - m0: bcc.r m1 + m0: bcc m1 clc adc MemMap.MATH.factor2 m1: ror ror MemMap.MATH.factor1 dex - bpl.r m0 + bpl m0 ldx MemMap.MATH.factor1 sta MemMap.MATH.result diff --git a/libs/memory.asm b/libs/memory.asm index 8bfffb8..fdb1117 100644 --- a/libs/memory.asm +++ b/libs/memory.asm @@ -1,7 +1,6 @@ #importonce #import "../core/module.asm" -#import "../core/module.asm" #import "../core/pseudo.asm" @@ -143,7 +142,7 @@ clone: { sta (MemMap.MEMORY.dest),y iny dex - bne md3 + bne md3 cli md4: plr @@ -223,5 +222,5 @@ module_name: #import "../core/mem_map.asm" -#import "../libs/screen.asm" +#import "../devices/video.asm" diff --git a/libs/print.asm b/libs/print.asm index 925f339..3a2aed5 100644 --- a/libs/print.asm +++ b/libs/print.asm @@ -1,7 +1,7 @@ #importonce #import "math.asm" -#import "../libs/screen.asm" +#import "../devices/video.asm" #import "../core/module.asm" @@ -20,7 +20,7 @@ } .macro PrintNewLine() { - jsr Screen.screenNewLine + jsr Video.screenNewLine } @@ -52,22 +52,22 @@ toDebug: { // -------------------------------------------------------- // printPetChar - -// Convert a Char from PET ASCII and print it out on Screen +// Convert a Char from PET ASCII and print it out on Video // // Parameters: // A = PET ASCII char to print // -------------------------------------------------------- printPetChar: { phr - jsr Print.petCharToScreenChar - jsr Screen.sendChar + jsr Print.petCharToVideoChar + jsr Video.sendChar plr rts } // -------------------------------------------------------- // printLine - -// Print a Null terminated SCREEN ASCII string to screen. +// Print a Null terminated VIDEO ASCII string to screen. // // Parameters: // A = low byte string address @@ -81,7 +81,7 @@ printLine: { lda (MemMap.PRINT.TempStringPointer), y cmp #0 beq exit - jsr Screen.sendChar + jsr Video.sendChar jmp printLoop exit: rts @@ -125,16 +125,16 @@ byteToHex: { } // -------------------------------------------------------- -// petCharToScreenChar - -// Convert a PET ASCII Char to a SCREEN ASCII Char +// petCharToVideoChar - +// Convert a PET ASCII Char to a VIDEO ASCII Char // // Parameters: // A = PET ASCII Byte to Convert // // Result: -// A = Converted ASCII SCREEN Char +// A = Converted ASCII VIDEO Char // -------------------------------------------------------- -petCharToScreenChar: { +petCharToVideoChar: { // $00-$1F cmp #$1f bcs !+ diff --git a/progs/woz_shell.asm b/progs/woz_shell.asm index ba5e112..0a00cc1 100644 --- a/progs/woz_shell.asm +++ b/progs/woz_shell.asm @@ -3,7 +3,7 @@ #import "../core/system.asm" #import "../libs/print.asm" #import "../core/module.asm" -#import "../libs/keyboard.asm" +#import "../devices/keyboard.asm" .filenamespace WozShell @@ -56,9 +56,9 @@ loop: { execute: jsr WozShell.push // CR in Buffer - jsr Screen.screenNewLine + jsr Video.screenNewLine jsr WozShell.exec - jsr Screen.screenNewLine + jsr Video.screenNewLine jsr WozShell.clear jmp loop } @@ -72,7 +72,7 @@ push: { ldy MemMap.SHELL.pos iny cpy #127 - beq.r done + beq done sty MemMap.SHELL.pos sta MemMap.SHELL.buffer, y done: @@ -135,7 +135,7 @@ wozExec: { asl SETMODE: cmp #0 - beq.r !+ + beq !+ eor #%10000000 !: sta MemMap.SHELL.MODE @@ -145,7 +145,7 @@ wozExec: { NEXTITEM: lda MemMap.SHELL.buffer,Y //Get character cmp #CR - bne.r CONT // We're done if it's CR! + bne CONT // We're done if it's CR! rts CONT: cmp #'.' @@ -317,7 +317,7 @@ helpString: .byte $8e, 0 aboutString: - .text "woz64 mon - v 0.1.5" + .text "woz64 mon - v 1.2.0" .byte $8e, 0 lineString: .text "----------------------------------------"